diff --git a/config.cpp b/config.cpp index 6c5e15e2..995f89d2 100644 --- a/config.cpp +++ b/config.cpp @@ -1493,11 +1493,14 @@ int read_config_args() { PHASEFROM(2); shift(); backcolor = arghex(); } else if(argis("-fillmodel")) { - PHASEFROM(2); shift(); fillmodel = arghex(); + PHASEFROM(2); shift(); modelcolor = arghex(); } else if(argis("-ring")) { PHASEFROM(2); shift(); ringcolor = arghex(); } + else if(argis("-period")) { + PHASEFROM(2); shift(); periodcolor = arghex(); + } else if(argis("-borders")) { PHASEFROM(2); shift(); bordcolor = arghex(); } diff --git a/graph.cpp b/graph.cpp index 8be319a0..3447b7d4 100644 --- a/graph.cpp +++ b/graph.cpp @@ -5498,8 +5498,6 @@ void calcparam() { callhooks(hooks_calcparam); } -int ringcolor = darkena(0xFF, 0, 0xFF); - function wrap_drawfullmap = drawfullmap; bool force_sphere_outline = false; @@ -5526,11 +5524,6 @@ void drawfullmap() { draw_model_elements(); - if(fillmodel) { - for(int i=0; i<360; i++) curvepoint(xspinpush0(i * 2 * M_PI / 360, 10)); - auto m = queuecurve(ringcolor, fillmodel, PPR::OUTCIRCLE); - } - /* if(vid.wallmode < 2 && !euclid && !patterns::whichShape) { int ls = isize(lines); if(ISMOBILE) ls /= 10; diff --git a/hyper.h b/hyper.h index c7726974..41ac8a0c 100644 --- a/hyper.h +++ b/hyper.h @@ -2300,7 +2300,7 @@ string generateHelpForItem(eItem it); bool graphglyph(); extern bool hiliteclick; extern int antialiaslines; -extern int ringcolor; +extern color_t ringcolor, periodcolor, modelcolor; #include @@ -3336,6 +3336,7 @@ extern int sagephase; extern int lastsize; extern int noiseuntil; hyperpoint xpush0(ld x); +hyperpoint ypush0(ld x); transmatrix xspinpush(ld alpha, ld x); hyperpoint xspinpush0(ld alpha, ld x); diff --git a/hyperpoint.cpp b/hyperpoint.cpp index e380f890..b297f78d 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -293,6 +293,14 @@ inline hyperpoint xpush0(ld x) { return h; } +inline hyperpoint ypush0(ld x) { + hyperpoint h; + if(euclid) return hpxy(x, 0); + else if(sphere) h[0] = 0, h[1] = sin(x), h[2] = cos(x); + else h[0] = 0, h[1] = sinh(x), h[2] = cosh(x); + return h; + } + inline hyperpoint xspinpush0(ld alpha, ld x) { // return spin(alpha)*xpush0(x); ld s; diff --git a/hypgraph.cpp b/hypgraph.cpp index 9093e0d5..124a3413 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -1142,62 +1142,100 @@ void circle_around_center(ld radius, color_t linecol, color_t fillcol, PPR prio) c.flags |= POLY_FORCE_INVERTED; } +color_t periodcolor = 0x00FF0080; +color_t ringcolor = darkena(0xFF, 0, 0xFF); +color_t modelcolor = 0; + void draw_model_elements() { - if(elliptic || (vid.grid && sphere)) - circle_around_center(M_PI/2, ringcolor, 0, PPR::CIRCLE); + switch(pmodel) { - if(pmodel == mdTwoPoint) { - ld a = -conformal::model_orientation * degree; - queuechr(xspinpush0(a, +vid.twopoint_param), vid.xres / 100, 'X', ringcolor >> 8); - queuechr(xspinpush0(a, -vid.twopoint_param), vid.xres / 100, 'X', ringcolor >> 8); - } - - if(pmodel == mdBall) { - queuecircle(vid.xcenter, vid.ycenter, vid.radius, ringcolor, PPR::OUTCIRCLE, fillmodel); - ballgeometry(); - } - - if(pmodel == mdHyperboloid && hyperbolic) { + case mdTwoPoint: { + ld a = -conformal::model_orientation * degree; + queuechr(xspinpush0(a, +vid.twopoint_param), vid.xres / 100, 'X', ringcolor >> 8); + queuechr(xspinpush0(a, -vid.twopoint_param), vid.xres / 100, 'X', ringcolor >> 8); + return; + } + + case mdBall: { + queuecircle(vid.xcenter, vid.ycenter, vid.radius, ringcolor, PPR::OUTCIRCLE, modelcolor); + ballgeometry(); + return; + } + + case mdHyperboloid: { + if(hyperbolic) { #if CAP_QUEUE - curvepoint(hpxyz(0,0,1)); - curvepoint(hpxyz(0,0,-vid.alpha)); - queuecurve(ringcolor, 0, PPR::CIRCLE); + curvepoint(hpxyz(0,0,1)); + curvepoint(hpxyz(0,0,-vid.alpha)); + queuecurve(ringcolor, 0, PPR::CIRCLE); + + ld& tz = conformal::top_z; + ld z = acosh(tz); - ld& tz = conformal::top_z; - ld z = acosh(tz); - - hyperpoint a = xpush0(z); - ld cb = conformal::cos_ball; - ld sb = conformal::sin_ball; + hyperpoint a = xpush0(z); + ld cb = conformal::cos_ball; + ld sb = conformal::sin_ball; + + a[1] = sb * a[2] / -cb; + a[0] = sqrt(-1 + a[2] * a[2] - a[1] * a[1]); - a[1] = sb * a[2] / -cb; - a[0] = sqrt(-1 + a[2] * a[2] - a[1] * a[1]); - - curvepoint(hpxyz(0,0,-vid.alpha)); - curvepoint(a); - curvepoint(hpxyz(0,0,0)); - a[0] = -a[0]; - curvepoint(a); - curvepoint(hpxyz(0,0,-vid.alpha)); - queuecurve(ringcolor, 0, PPR::CIRCLE); - - curvepoint(hpxyz(-1,0,0)); - curvepoint(hpxyz(1,0,0)); - queuecurve(ringcolor, 0, PPR::CIRCLE); - - a[1] = sb * tz / -cb; - a[0] = sqrt(tz * tz - a[1] * a[1]); - a[2] = tz - vid.alpha; - - curvepoint(a); - curvepoint(hpxyz(0,0,-vid.alpha)); - a[0] = -a[0]; - curvepoint(a); - queuecurve(ringcolor, 0, PPR::CIRCLE); + curvepoint(hpxyz(0,0,-vid.alpha)); + curvepoint(a); + curvepoint(hpxyz(0,0,0)); + a[0] = -a[0]; + curvepoint(a); + curvepoint(hpxyz(0,0,-vid.alpha)); + queuecurve(ringcolor, 0, PPR::CIRCLE); + + curvepoint(hpxyz(-1,0,0)); + curvepoint(hpxyz(1,0,0)); + queuecurve(ringcolor, 0, PPR::CIRCLE); + + a[1] = sb * tz / -cb; + a[0] = sqrt(tz * tz - a[1] * a[1]); + a[2] = tz - vid.alpha; + + curvepoint(a); + curvepoint(hpxyz(0,0,-vid.alpha)); + a[0] = -a[0]; + curvepoint(a); + queuecurve(ringcolor, 0, PPR::CIRCLE); #endif + } + return; + } + + default: break; } + } + +void queuestraight(hyperpoint X, int style, color_t lc, color_t fc, PPR p) { + + using namespace hyperpoint_vec; + hyperpoint H; + applymodel(X, H); + H *= vid.radius; + ld mul = hypot(vid.xres, vid.yres) / hypot2(H); + ld m = style == 1 ? -mul : -1; + queuereset(mdUnchanged, p); + curvepoint(H + spin(M_PI/2) * H * mul); + curvepoint(H - spin(M_PI/2) * H * mul); + curvepoint(m * H - spin(M_PI/2) * H * mul); + curvepoint(m * H + spin(M_PI/2) * H * mul); + curvepoint(H + spin(M_PI/2) * H * mul); + + queuecurve(lc, fc, p).flags |= POLY_ALWAYS_IN; + queuereset(pmodel, p); + /* + for(int i=0; i<1; i++) { + hyperpoint h = spin(i * 45 * degree) * X; + hyperpoint res; + applymodel(h, res); + if(hypot2(res) < 1000 && !std::isnan(res[0]) && !std::isnan(res[1])) + queuechr(h, 16, 'X', 0xFF0000 + i * 0x20); + } */ } void draw_boundary(int w) { @@ -1205,28 +1243,19 @@ void draw_boundary(int w) { if(w == 1) return; color_t lc = ringcolor; - color_t fc = fillmodel; + color_t fc = modelcolor; PPR p = PPR::OUTCIRCLE; if(haveaura()) lc = 0; if(lc == 0 && fc == 0) return; + + ld fakeinf = sphere ? M_PI-1e-5 : hyperbolic ? 10 : exp(10); + if(elliptic && !among(pmodel, mdBand, mdBandEquidistant, mdBandEquiarea, mdSinusoidal)) + circle_around_center(M_PI/2, periodcolor, 0, PPR::CIRCLE); + switch(pmodel) { - case mdSinusoidal: { - if(stereo::active() || !sphere) return; - queuereset(vid.usingGL ? mdDisk : mdUnchanged, PPR::CIRCLE); - - for(ld a=-45; a<45+1e-6; a+=pow(.5, vid.linequality)) { - curvepoint(hpxyz(cos(a * M_PI / 90) * vid.radius, a * vid.radius / 90, 0)); - } - for(ld a=45; a>=-45-1e-6; a-=pow(.5, vid.linequality)) { - curvepoint(hpxyz(-cos(a * M_PI / 90) * vid.radius, a * vid.radius / 90, 0)); - } - queuecurve(lc, fc, p); - return; - } - case mdTwoPoint: { if(twopoint_do_flips || stereo::active() || !sphere) return; queuereset(vid.usingGL ? mdDisk : mdUnchanged, p); @@ -1252,25 +1281,37 @@ void draw_boundary(int w) { return; } - case mdBand: case mdBandEquidistant: case mdBandEquiarea: { - ld rad = 0; - if(pmodel == mdBand && hyperbolic) rad = vid.radius; - if(pmodel == mdBandEquidistant && sphere) rad = vid.radius / 2; - if(pmodel == mdBandEquiarea && sphere) rad = vid.radius / M_PI; - - if(rad) { - queuereset(vid.usingGL ? mdDisk : mdUnchanged, PPR::CIRCLE); - curvepoint(hpxyz(-vid.xcenter, -rad, 0)); - curvepoint(hpxyz(vid.xres-vid.xcenter, -rad, 0)); - queuecurve(ringcolor, 0, PPR::CIRCLE); - curvepoint(hpxyz(-vid.xcenter, rad, 0)); - curvepoint(hpxyz(vid.xres-vid.xcenter, rad, 0)); - queuecurve(ringcolor, 0, PPR::CIRCLE); - queuereset(pmodel, PPR::CIRCLE); - return; + case mdBand: case mdBandEquidistant: case mdBandEquiarea: case mdSinusoidal: { + bool bndband = ((pmodel == mdBand) ? hyperbolic : sphere); + transmatrix T = spin(-conformal::model_orientation * degree); + ld right = M_PI/2 - 1e-5; + if(bndband) + queuestraight(T * ypush0(hyperbolic ? 10 : right), 2, lc, fc, p); + ld xperiod = elliptic ? fakeinf/2 : fakeinf; + if(sphere && !bndband) { + queuestraight(T * xpush0(xperiod), 2, periodcolor, 0, PPR::CIRCLE); } + if(sphere && bndband) { + ld adegree = degree-1e-6; + for(ld a=-90; a<90+1e-6; a+=pow(.5, vid.linequality)) { + curvepoint(T * xpush(xperiod) * ypush0(a * adegree)); + } + for(ld a=-90; a<90+1e-6; a+=pow(.5, vid.linequality)) { + curvepoint(T * xpush(-xperiod) * ypush0(-a * adegree)); + } + curvepoint(T * xpush(xperiod) * ypush0(-90 * adegree)); + queuecurve(periodcolor, 0, PPR::CIRCLE); + } + return; } + case mdHalfplane: + if(hyperbolic) { + queuestraight(xspinpush0(-conformal::model_orientation * degree - M_PI/2, fakeinf), 1, lc, fc, p); + return; + } + break; + default: break; } @@ -1294,8 +1335,8 @@ void draw_boundary(int w) { } */ - if(sphere) return; - circle_around_center(hyperbolic ? 20 : exp(10), lc, fc, p); + if(sphere && !among(pmodel, mdEquidistant, mdEquiarea)) return; + circle_around_center(fakeinf, lc, fc, p); /* if(pmodel == mdPolygonal || pmodel == mdPolynomial) diff --git a/polygons.cpp b/polygons.cpp index 6b2c0b0e..df1e5fe3 100644 --- a/polygons.cpp +++ b/polygons.cpp @@ -69,6 +69,9 @@ static const int POLY_PRECISE_WIDE = (1<<19); // force inverted static const int POLY_FORCE_INVERTED = (1<<20); +// always draw this +static const int POLY_ALWAYS_IN = (1<<21); + vector hpc; int prehpc; @@ -481,9 +484,9 @@ void glapplymatrix(const transmatrix& V) { void dqi_poly::gldraw() { auto& v = *tab; - + #if MINIMIZE_GL_CALLS - if(stereo::active() == 0 && !tinf && (color == 0 || ((flags & (POLY_VCONVEX | POLY_CCONVEX)) && !(flags & POLY_INVERSE)))) { + if(stereo::active() == 0 && !tinf && (color == 0 || ((flags & (POLY_VCONVEX | POLY_CCONVEX)) && !(flags & (POLY_INVERSE || POLY_FORCE_INVERTED))))) { if(color != triangle_color || outline != line_color || texts_merged) { glflush(); triangle_color = color; @@ -965,7 +968,7 @@ void dqi_poly::draw() { last_infront = false; addpoly(V, *tab, offset, cnt); - if(!(sphere && vid.alpha < .9)) if(pmodel != mdJoukowsky) for(int i=1; i vid.xres * 2 || dy > vid.yres * 2) return; diff --git a/screenshot.cpp b/screenshot.cpp index 0362e9d8..05f922a1 100644 --- a/screenshot.cpp +++ b/screenshot.cpp @@ -222,8 +222,6 @@ void IMAGESAVE(SDL_Surface *s, const char *fname) { hookset *hooks_hqshot; -color_t fillmodel; - void saveHighQualityShot(const char *fname, const char *caption, int fade) { resetbuffer rb;