diff --git a/classes.cpp b/classes.cpp index 0e38ceab..41dd2711 100644 --- a/classes.cpp +++ b/classes.cpp @@ -1031,7 +1031,7 @@ enum eModel : int { // 39..48 mdPoorMan, mdPanini, mdRetroCraig, mdRetroLittrow, mdRetroHammer, mdThreePoint, mdLiePerspective, mdLieOrthogonal, mdRelPerspective, mdRelOrthogonal, // 49..50 - mdHorocyclicEqa, mdConformalSquare, mdFisheye2, + mdHorocyclicEqa, mdConformalSquare, mdFisheye2, mdPolar, // 51.. mdGUARD, mdPixel, mdHyperboloidFlat, mdPolynomial, mdManual }; @@ -1096,6 +1096,7 @@ EX vector mdinf = { {X3("horocyclic equal-area"), mf::euc_boring | mf::equiarea | mf::orientation | mf::horocyclic}, {X3("conformal square"), mf::orientation | mf::broken | mf::transition}, {X3("variant fisheye"), 0}, + {X3("polar coordinates"), mf::orientation}, {X3("guard"), mf::technical}, {X3("pixel"), mf::technical}, {X3("hypflat"), mf::technical}, diff --git a/drawing.cpp b/drawing.cpp index 0d6b9791..09b7d595 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -1975,7 +1975,7 @@ void dqi_poly::draw() { if(isize(glcoords) <= 1) return; cyl::loop_min = cyl::loop_max = 0; - if(sphere && mdBandAny()) + if((sphere && mdBandAny()) || pmodel == mdPolar) cyl::adjust(tinf); int poly_limit = max(vid.xres, vid.yres) * 2; diff --git a/hypgraph.cpp b/hypgraph.cpp index ea702dcf..57a29af1 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -1362,6 +1362,21 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) { makeband(H_orig, ret, [] (ld& x, ld& y) { x *= cos_auto(y); }); break; + case mdPolar: { + models::scr_to_ori(H); + H = xpush(pconf.offside) * H; + ld zlev = find_zlev(H); + ld d = hdist0(H); + ld df, zf; + hypot_zlev(zlev, d, df, zf); + ret[0] = -atan2(H) / M_PI; + ret[1] = (d - pconf.offside2) / M_PI; + ret[2] = zf; + ret[3] = 1; + models::ori_to_scr(ret); + break; + } + case mdEquidistant: case mdEquiarea: case mdEquivolume: { if(vrhr::rendering() && GDIM == 3 && pmodel == mdEquidistant) { ret = inverse_exp(H_orig); diff --git a/models.cpp b/models.cpp index e413a104..67d8d46d 100644 --- a/models.cpp +++ b/models.cpp @@ -139,6 +139,7 @@ projection_configuration::projection_configuration() { ptr_ball = new transmatrix; *ptr_ball = cspin(1, 2, 20._deg); ptr_camera = new transmatrix; *ptr_camera = Id; + offside = 0; offside2 = M_PI; } EX namespace models { @@ -643,6 +644,11 @@ EX namespace models { if(among(vpmodel, mdLoximuthal, mdRetroHammer, mdRetroCraig)) add_edit(vpconf.loximuthal_parameter); + if(among(vpmodel, mdPolar)) { + add_edit(vpconf.offside); + add_edit(vpconf.offside2); + } + if(among(vpmodel, mdAitoff, mdHammer, mdWinkelTripel)) add_edit(vpconf.aitoff_parameter); @@ -1009,6 +1015,12 @@ EX namespace models { "The Aitoff projection is obtained by multiplying the longitude by 1/2, using azimuthal equidistant projection, and then dividing X by 1/2. " "Hammer projection is similar but equi-area projection is used instead. " "Here you can change this parameter.", 'b'); + param_f(p.offside, sp+"offside") + -> editable(0, TAU, TAU/10, "offside parameter", + "Do not center the projection on the player -- move the center offside. Useful in polar, where the value equal to offside2 can be used to center the projection on the player.", 'o'); + param_f(p.offside2, sp+"offside2") + -> editable(0, TAU, TAU/10, "offside parameter II", + "In polar projection, what distance to display in the center. Use asinh(1) (in hyperbolic) to make it conformal in the center, and pi to have the projection extend the same distance to the left, right, and upwards.", 'O'); param_f(p.miller_parameter, sp+"miller"); param_f(p.loximuthal_parameter, sp+"loximuthal") -> editable(-90._deg, 90._deg, .1, "loximuthal parameter",