From 2b61413a8149073a3cc8954ee8173bdf925aad3f Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sat, 30 Mar 2019 17:45:56 +0100 Subject: [PATCH] azimuthal equivolume projection --- classes.cpp | 1 + classes.h | 2 ++ conformal.cpp | 1 + hyper.h | 4 ++-- hyperpoint.cpp | 9 +++++++++ hypgraph.cpp | 6 ++++-- 6 files changed, 19 insertions(+), 4 deletions(-) diff --git a/classes.cpp b/classes.cpp index 8d4b092b..2880853d 100644 --- a/classes.cpp +++ b/classes.cpp @@ -585,6 +585,7 @@ const modelinfo models[int(mdPolynomial)+1] = { {X3("rotated hyperboles"), mf::hyper_only}, {X3("spiral"), mf::hyper_or_torus | mf::quasiband}, {X3("native perspective"), 0}, + {X3("azimuthal equi-volume"), mf::azimuthal | mf::equivolume | mf::euc_boring}, {X3(""), 0}, {X3(""), 0}, {X3(""), 0}, diff --git a/classes.h b/classes.h index b9a14f5e..b22e9d4f 100644 --- a/classes.h +++ b/classes.h @@ -258,6 +258,7 @@ enum eModel { mdHemisphere, mdBandEquidistant, mdBandEquiarea, mdSinusoidal, mdTwoPoint, mdFisheye, mdJoukowsky, mdJoukowskyInverted, mdRotatedHyperboles, mdSpiral, mdPerspective, + mdEquivolume, mdGUARD, mdUnchanged, mdHyperboloidFlat, mdPolynomial }; @@ -274,6 +275,7 @@ namespace mf { static const flagtype hyper_only = 128; static const flagtype hyper_or_torus = 256; static const flagtype quasiband = 512; + static const flagtype equivolume = 1024; }; struct modelinfo { diff --git a/conformal.cpp b/conformal.cpp index db70f978..5eb00d82 100644 --- a/conformal.cpp +++ b/conformal.cpp @@ -609,6 +609,7 @@ namespace conformal { if(sphere && (pm == mdHalfplane || pm == mdBall)) return false; if(DIM == 2 && pm == mdPerspective) return false; + if(DIM == 2 && pm == mdEquivolume) return false; if(DIM == 3 && among(pm, mdBall, mdHyperboloid, mdFormula, mdPolygonal, mdRotatedHyperboles, mdSpiral, mdHemisphere)) return false; return true; } diff --git a/hyper.h b/hyper.h index 4fef44d5..124e50da 100644 --- a/hyper.h +++ b/hyper.h @@ -2232,9 +2232,9 @@ void drawShape(pair* coords, int qty, color_t color); extern eModel pmodel; -inline bool mdAzimuthalEqui() { return pmodel == mdEquidistant || pmodel == mdEquiarea; } +inline bool mdAzimuthalEqui() { return among(pmodel, mdEquidistant, mdEquiarea, mdEquivolume); } -inline bool mdBandAny() { return pmodel == mdBand || pmodel == mdBandEquidistant || pmodel == mdBandEquiarea || pmodel == mdSinusoidal; } +inline bool mdBandAny() { return among(pmodel, mdBand, mdBandEquidistant, mdBandEquiarea, mdSinusoidal); } color_t darkena(color_t c, int lev, int a); diff --git a/hyperpoint.cpp b/hyperpoint.cpp index f5793be6..51795bdd 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -67,6 +67,15 @@ ld asin_auto(ld x) { } } +ld volume_auto(ld r) { + switch(cgclass) { + case gcEuclid: return 4 * r * r * r / 3 * M_PI; + case gcHyperbolic: return M_PI * (sinh(2*r) - 2 * r); + case gcSphere: return M_PI * (2 * r - sin(2*r)); + default: return 0; + } + } + ld asin_auto_clamp(ld x) { switch(cgclass) { case gcEuclid: return x; diff --git a/hypgraph.cpp b/hypgraph.cpp index d62d6402..2ad5290f 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -557,7 +557,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) { makeband(H, ret, [] (ld& x, ld& y) { x *= cos_auto(y); }); break; - case mdEquidistant: case mdEquiarea: { + case mdEquidistant: case mdEquiarea: case mdEquivolume: { ld zlev = find_zlev(H); ld rad = hypot_d(DIM, H); @@ -568,7 +568,9 @@ void applymodel(hyperpoint H, hyperpoint& ret) { // 4 pi / 2pi = M_PI - if(pmodel == mdEquiarea && sphere) + if(pmodel == mdEquivolume) + d = pow(volume_auto(d), 1/3.) * pow(M_PI / 2, 1/3.); + else if(pmodel == mdEquiarea && sphere) d = sqrt(2*(1 - cos(d))) * M_PI / 2; else if(pmodel == mdEquiarea && hyperbolic) d = sqrt(2*(cosh(d) - 1)) / 1.5;