From a9535878c434228ad5691515ebd214469e249f68 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Tue, 23 Oct 2018 16:58:19 +0200 Subject: [PATCH] model orientation --- config.cpp | 8 +++++++- conformal.cpp | 49 ++++++++++++++++++++++++++++++++++++++----------- control.cpp | 4 ++-- graph.cpp | 10 +++++++--- hyper.h | 14 +++++++++++++- hypgraph.cpp | 39 ++++++++++++++++++++++++++------------- init.cpp | 4 ++-- polygons.cpp | 42 +++++++++++++++++++++++++++++++++--------- screenshot.cpp | 17 ++++++++++++++--- 9 files changed, 142 insertions(+), 45 deletions(-) diff --git a/config.cpp b/config.cpp index a0c3e757..26ae7f64 100644 --- a/config.cpp +++ b/config.cpp @@ -208,7 +208,8 @@ void initConfig() { addsaver(conformal::bandsegment, "band segment"); addsaver(conformal::rotation, "conformal rotation"); addsaver(conformal::do_rotate, "conformal rotation mode", 1); - addsaver(conformal::lower_halfplane, "lower halfplane", false); + addsaver(conformal::model_orientation, "model orientation", 0); + addsaver(conformal::halfplane_scale, "halfplane scale", 1); addsaver(conformal::autoband, "automatic band"); addsaver(conformal::autobandhistory, "automatic band history"); addsaver(conformal::dospiral, "do spiral"); @@ -1486,6 +1487,11 @@ int read_config_args() { else if(argis("-PM")) { PHASEFROM(2); shift(); pmodel = eModel(argi()); } + else if(argis("-hp")) { + PHASEFROM(2); + shift(); conformal::model_orientation = argf(); + shift(); conformal::halfplane_scale = argf(); + } else if(argis("-zoom")) { PHASEFROM(2); shift(); vid.scale = argf(); } diff --git a/conformal.cpp b/conformal.cpp index 26df10a3..ee9e6499 100644 --- a/conformal.cpp +++ b/conformal.cpp @@ -97,12 +97,18 @@ namespace polygonal { void drawBoundary(int color) { queuereset(mdDisk, PPR::CIRCLE); + ld C, S; + auto& ho = conformal::model_orientation; + if(ho == 0) C = 1, S = 0; + else if(ho == 180) C = -1, S = 0; + else C = cos(ho * M_PI/180), S = sin(ho * M_PI / 180); + for(int r=0; r<=2000; r++) { cld z = exp(cld(0, 2*M_PI * r / 2000.0)); pair z2 = compute(real(z), imag(z), deg); hyperpoint h; - h[0] = z2.first * vid.radius; - h[1] = z2.second * vid.radius; + h[0] = (z2.first * C - z2.second * S) * vid.radius; + h[1] = (z2.second * C + z2.first * S) * vid.radius; h[2] = stereo::scrdist; curvepoint(h); } @@ -288,7 +294,10 @@ namespace conformal { int bandsegment = 16000; ld rotation = 0; int do_rotate = 1; - bool lower_halfplane; + ld model_orientation, halfplane_scale; + ld ocos, osin; + bool model_straight; + bool autoband = false; bool autobandhistory = false; bool dospiral = true; @@ -401,6 +410,13 @@ namespace conformal { movetophase(); } + + void configure() { + ocos = cos(model_orientation * M_PI / 180); + osin = sin(model_orientation * M_PI / 180); + model_straight = (ocos > 1 - 1e-9); + if(conformal::on) conformal::apply(); + } ld measureLength() { ld r = bandhalf * vid.scale; @@ -580,6 +596,11 @@ namespace conformal { return true; } + bool model_has_orientation() { + return + among(pmodel, mdHalfplane, mdPolynomial, mdPolygonal, mdTwoPoint) || mdBandAny(); + } + void model_menu() { cmode = sm::SIDE | sm::MAYDARK | sm::CENTER; gamescreen(0); @@ -608,6 +629,9 @@ namespace conformal { if(pmodel == mdDisk || pmodel == mdBall || pmodel == mdHyperboloid) { dialog::addSelItem(XLAT("Projection at the ground level"), fts3(vid.alpha), 'p'); } + + if(model_has_orientation()) + dialog::addSelItem(XLAT("model orientation"), fts(model_orientation), 'l'); if(pmodel == mdPolynomial) { dialog::addSelItem(XLAT("coefficient"), @@ -617,8 +641,9 @@ namespace conformal { dialog::addSelItem(XLAT("which coefficient"), its(polygonal::coefid), 'n'); } - if(pmodel == mdHalfplane) - dialog::addBoolItem(XLAT("lower half-plane"), lower_halfplane, 'l'); + if(pmodel == mdHalfplane) { + dialog::addSelItem(XLAT("half-plane scale"), fts(halfplane_scale), 'b'); + } if(pmodel == mdBall) dialog::addSelItem(XLAT("projection in ball model"), fts3(vid.ballproj), 'x'); @@ -638,7 +663,7 @@ namespace conformal { } if(pmodel == mdTwoPoint) { - dialog::addSelItem(XLAT("parameter"), fts3(vid.twopoint_param), 'l'); + dialog::addSelItem(XLAT("parameter"), fts3(vid.twopoint_param), 'b'); } dialog::addSelItem(XLAT("vertical stretch"), fts3(vid.stretch), 's'); @@ -679,14 +704,14 @@ namespace conformal { editScale(); else if(uni == 'p') projectionDialog(); - else if(uni == 'b') - config_camera_rotation(); #if CAP_RUG else if(uni == 'u') pushScreen(rug::show); #endif - else if(uni == 'l' && pmodel == mdHalfplane) - lower_halfplane = !lower_halfplane; + else if(uni == 'l' && model_has_orientation()) + dialog::editNumber(model_orientation, 0, 360, 90, 0, XLAT("model orientation"), ""); + else if(uni == 'b' && pmodel == mdHalfplane) + dialog::editNumber(model_orientation, 0, 2, 0.25, 1, XLAT("halfplane scale"), ""); else if(uni == 's') { dialog::editNumber(vid.stretch, 0, 10, .1, 1, XLAT("vertical stretch"), "Vertical stretch factor." @@ -720,7 +745,7 @@ namespace conformal { ); dialog::scaleLog(); } - else if(uni == 'l' && pmodel == mdTwoPoint) { + else if(uni == 'b' && pmodel == mdTwoPoint) { dialog::editNumber(vid.twopoint_param, 0, 10, .1, 1, XLAT("parameter"), "This model maps the world so that the distances from two points " "are kept. This parameter gives the distance from the two points to " @@ -728,6 +753,8 @@ namespace conformal { ); dialog::scaleLog(); } + else if(uni == 'b') + config_camera_rotation(); else if(uni == 'x' && pmodel == mdBall) dialog::editNumber(vid.ballproj, 0, 100, .1, 0, XLAT("projection in ball model"), "This parameter affects the ball model the same way as the projection parameter affects the disk model."); diff --git a/control.cpp b/control.cpp index fc422291..e8fdef54 100644 --- a/control.cpp +++ b/control.cpp @@ -485,9 +485,9 @@ void mainloopiter() { #endif optimizeview(); - - if(conformal::on) conformal::apply(); + conformal::configure(); + ticks = SDL_GetTicks(); callhooks(hooks_fixticks); diff --git a/graph.cpp b/graph.cpp index 778f436b..8789c4f4 100644 --- a/graph.cpp +++ b/graph.cpp @@ -5470,8 +5470,9 @@ void drawfullmap() { ptds.clear(); if(pmodel == mdTwoPoint) { - queuechr(xpush0(+vid.twopoint_param), vid.xres / 100, 'X', 0xFF0000); - queuechr(xpush0(-vid.twopoint_param), vid.xres / 100, 'X', 0xFF0000); + ld a = -conformal::model_orientation * M_PI / 180; + queuechr(xspinpush0(a, +vid.twopoint_param), vid.xres / 100, 'X', 0xFF0000); + queuechr(xspinpush0(a, -vid.twopoint_param), vid.xres / 100, 'X', 0xFF0000); } /* @@ -5493,11 +5494,14 @@ void drawfullmap() { ld x = sin(a * vid.twopoint_param * b / 90); ld y = 0; ld z = -sqrt(1 - x*x); + conformal::apply_orientation(y, x); hyperpoint h1; applymodel(hpxyz(x,y,z), h1); + conformal::apply_orientation(h1[0], h1[1]); h1[1] = abs(h1[1]) * b; - curvepoint(h1 * vid.radius); + conformal::apply_orientation(h1[1], h1[0]); + curvepoint(h1); } queuecurve(ringcolor, 0, PPR::CIRCLE); diff --git a/hyper.h b/hyper.h index 1bd37a1a..fe090622 100644 --- a/hyper.h +++ b/hyper.h @@ -1275,7 +1275,18 @@ namespace conformal { extern bool includeHistory; extern ld rotation; extern int do_rotate; - extern bool lower_halfplane; + extern ld model_orientation; + extern ld halfplane_scale; + extern ld ocos, osin; + extern bool model_straight; + + // screen coordinates to logical coordinates: apply_orientation(x,y) + // logical coordinates back to screen coordinates: apply_orientation(y,x) + template + void apply_orientation(A& x, A& y) { if(!model_straight) tie(x,y) = make_pair(x*ocos + y*osin, y*ocos - x*osin); } + + void configure(); + extern bool autoband; extern bool autobandhistory; extern bool dospiral; @@ -1299,6 +1310,7 @@ namespace conformal { void progress_screen(); void progress(string str); + bool model_has_orientation(); } namespace polygonal { diff --git a/hypgraph.cpp b/hypgraph.cpp index c8b85c79..f8032616 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -268,7 +268,9 @@ void applymodel(hyperpoint H, hyperpoint& ret) { apply_depth(ret, y * zf / M_PI); } else { - ld x, y, yf, zf; + conformal::apply_orientation(H[0], H[1]); + + ld x, y, yf, zf=0; y = asin_auto(H[1]); x = asin_auto_clamp(H[0] / cos_auto(y)); if(sphere) { @@ -331,9 +333,11 @@ void applymodel(hyperpoint H, hyperpoint& ret) { printf("unknown model\n"); } } - ret = hpxyz(x / M_PI, y * yf / M_PI, 0); + ld yzf = y * zf; y *= yf; + conformal::apply_orientation(y, x); + ret = hpxyz(x / M_PI, y / M_PI, 0); if(zlev_used && stereo::active()) - apply_depth(ret, y * zf / M_PI); + apply_depth(ret, yzf / M_PI); } ghcheck(ret, H); return; @@ -365,7 +369,12 @@ void applymodel(hyperpoint H, hyperpoint& ret) { tz = H[2]+vid.alpha; if(pmodel == mdPolygonal || pmodel == mdPolynomial) { + + conformal::apply_orientation(H[0], H[1]); + pair p = polygonal::compute(H[0]/tz, H[1]/tz); + + conformal::apply_orientation(p.second, p.first); ret[0] = p.first; ret[1] = p.second; ret[2] = 0; @@ -379,21 +388,25 @@ void applymodel(hyperpoint H, hyperpoint& ret) { ld x0, y0; x0 = H[0] / tz; y0 = H[1] / tz; - if(conformal::lower_halfplane) x0 = -x0, y0 = -y0; + + conformal::apply_orientation(x0, y0); + y0 += 1; double rad = x0*x0 + y0*y0; - y0 /= rad; - x0 /= rad; - y0 -= .5; - - if(conformal::lower_halfplane) x0 = -x0, y0 = -y0; + y0 /= -rad; + x0 /= -rad; + y0 += .5; - ret[0] = x0; + conformal::apply_orientation(y0, x0); + + auto& ps = conformal::halfplane_scale; + x0 *= ps, y0 *= ps; + + ret[0] = -conformal::osin + x0; if(wmspatial || mmspatial) { - if(conformal::lower_halfplane) y0 /= zlev; - else y0 *= zlev; + y0 = y0 * pow(zlev, conformal::ocos); } - ret[1] = (conformal::lower_halfplane?-1:1) - y0; + ret[1] = conformal::ocos + y0; ret[2] = 0; if(zlev != 1 && stereo::active()) apply_depth(ret, -y0 * geom3::factor_to_lev(zlev)); diff --git a/init.cpp b/init.cpp index 7a2529cf..70ffe061 100644 --- a/init.cpp +++ b/init.cpp @@ -300,8 +300,8 @@ void mobile_draw(MOBPAR_FORMAL) { // if(debfile) fprintf(debfile, "d1\n"), fflush(debfile); frames++; - if(conformal::on) conformal::apply(); - + conformal::configure(); + if(ticks > lastt) tortoise::updateVals(ticks - lastt); if(clicked && !lclicked) touchedAt = ticks; diff --git a/polygons.cpp b/polygons.cpp index 0bcaa871..ef1e9b40 100644 --- a/polygons.cpp +++ b/polygons.cpp @@ -584,14 +584,24 @@ void fixMercator(bool tinf) { else mercator_period = 2 * vid.radius; + if(!conformal::model_straight) + for(auto& g: glcoords) + conformal::apply_orientation(g[0], g[1]); + if(pmodel == mdSinusoidal) for(int i = 0; i %d\n", base, qglcoords); for(int a=0; a 0) continue; - ld c1 = h1[1], c2 = -h2[1]; + + hyperpoint ah1 = h1, ah2 = h2; + conformal::apply_orientation(ah1[0], ah1[1]); + conformal::apply_orientation(ah2[0], ah2[1]); + if(ah1[1] * ah2[1] > 0) continue; + ld c1 = ah1[1], c2 = -ah2[1]; if(c1 < 0) c1 = -c1, c2 = -c2; - hyperpoint h = h1 * c1 + h2 * c2; + hyperpoint h = ah1 * c1 + ah2 * c2; h /= hypot3(h); if(h[2] < 0 && abs(h[0]) < sin(vid.twopoint_param)) cpha = 1-cpha, pha = 2; } @@ -936,9 +956,13 @@ void dqi_poly::draw() { if(l || lastl) { for(int i=0; i animatable_parameters = { animatable_parameter(vid.ballproj), animatable_parameter(surface::dini_b), animatable_parameter(surface::hyper_b), + animatable_parameter(conformal::halfplane_scale), }; ld anim_param = 0; @@ -507,8 +508,12 @@ void apply() { rug::apply_rotation(rug::currentrot * rotmatrix(rug_rotation2 * 2 * M_PI * t / period, 0, 1) * inverse(rug::currentrot)); } } - if(ballangle_rotation) - vid.ballangle += ballangle_rotation * 360 * t / period; + if(ballangle_rotation) { + if(conformal::model_has_orientation()) + conformal::model_orientation += ballangle_rotation * 360 * t / period; + else + vid.ballangle += ballangle_rotation * 360 * t / period; + } if(paramstate == 2 && anim_param) { ld phase = (1 + sin(anim_param * 2 * M_PI * ticks / period)) / 2; for(auto& ap: animatable_parameters) if(ap.values[0] != ap.values[1]) { @@ -540,6 +545,10 @@ string animfile = "animation-%04d.png"; bool record_animation() { for(int i=0; i