conformal:: new models: formula and rotated hyperboles

This commit is contained in:
Zeno Rogue 2018-11-07 00:52:48 +01:00
parent 55fdd25a6c
commit 542e80081f
5 changed files with 80 additions and 32 deletions

View File

@ -295,6 +295,9 @@ void initConfig() {
addsaver(vid.cells_drawn_limit, "limit on cells drawn", 10000);
addsaver(vid.skiprope, "mobius", 0);
addsaver(conformal::formula, "formula");
addsaverenum(conformal::basic_model, "basic model");
#if CAP_SHMUP
shmup::initConfig();

View File

@ -258,6 +258,9 @@ bool isbad(ld z) { return !isfinite(z) || fabs(z) > 1e6; }
namespace conformal {
string formula = "z^2";
eModel basic_model;
void handleKeyC(int sym, int uni);
int lastprogress;
@ -578,11 +581,11 @@ namespace conformal {
#endif
const char *modelnames[MODELCOUNT] = {
"disk", "half-plane", "band", "polygonal", "polynomial",
"disk", "half-plane", "band", "polygonal", "formula",
"azimuthal equidistant", "azimuthal equi-area",
"ball model", "Minkowski hyperboloid", "hemisphere",
"band equidistant", "band equi-area", "sinusoidal", "two-point equidistant",
"fisheye", "Joukowsky transform", "Joukowsky+inversion"
"fisheye", "Joukowsky transform", "Joukowsky+inversion", "rotated hyperboles"
};
string get_model_name(eModel pm) {
@ -610,14 +613,34 @@ namespace conformal {
return among(pmodel, mdJoukowsky, mdJoukowskyInverted, mdBand);
}
int editpos = 0;
void model_menu() {
cmode = sm::SIDE | sm::MAYDARK | sm::CENTER;
gamescreen(0);
dialog::init(XLAT("models of hyperbolic geometry"));
for(int i=0; i<mdGUARD; i++) {
eModel m = eModel(i);
if(model_available(m))
if(model_available(m)) {
dialog::addBoolItem(get_model_name(m), pmodel == m, "0123456789!@#$%^&*()" [m]);
dialog::add_action([m] () {
if(m == mdFormula) {
if(pmodel != m) basic_model = pmodel;
dialog::edit_string(formula, "formula", "");
dialog::reaction_final = [] () {
pmodel = mdFormula;
};
return;
}
pmodel = m;
polygonal::solve();
vid.alpha = 1; vid.scale = 1;
if(pmodel == mdBand && sphere)
vid.scale = .3;
if(pmodel == mdDisk && sphere)
vid.scale = .4;
});
}
}
dialog::addBreak(100);
@ -701,32 +724,7 @@ namespace conformal {
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(uni >= '0' && uni <= '9') {
pmodel = eModel(uni - '0');
polygonal::solve();
vid.alpha = 1; vid.scale = 1;
if(pmodel == mdBand && sphere)
vid.scale = .3;
if(pmodel == mdDisk && sphere)
vid.scale = .4;
}
else if(uni == '!')
pmodel = eModel(10);
else if(uni == '@')
pmodel = eModel(11);
else if(uni == '#')
pmodel = eModel(12);
else if(uni == '$')
pmodel = eModel(13);
else if(uni == '%')
pmodel = eModel(14);
else if(uni == '^')
pmodel = eModel(15);
else if(uni == '&')
pmodel = eModel(16);
else if(uni == '6')
vid.alpha = 1, vid.scale = 1;
else if(uni == 'z')
if(uni == 'z')
editScale();
else if(uni == 'p')
projectionDialog();

13
hyper.h
View File

@ -472,7 +472,9 @@ template<class T> struct walker {
return at == x.at && spin == x.spin && mirrored == x.mirrored;
}
bool operator < (const walker<T>& cw2) const {
return tie(at, spin, mirrored) < tie(cw2.at, cw2.spin, cw2.mirrored);
}
walker<T>& operator ++ (int) { return (*this) += 1; }
walker<T>& operator -- (int) { return (*this) -= 1; }
@ -1269,11 +1271,13 @@ extern ld ruggo;
#define HASLINEVIEW
enum eModel {
mdDisk, mdHalfplane, mdBand, mdPolygonal, mdPolynomial,
mdDisk, mdHalfplane, mdBand, mdPolygonal, mdFormula,
mdEquidistant, mdEquiarea, mdBall, mdHyperboloid,
mdHemisphere, mdBandEquidistant, mdBandEquiarea, mdSinusoidal, mdTwoPoint,
mdFisheye, mdJoukowsky, mdJoukowskyInverted,
mdGUARD, mdUnchanged, mdHyperboloidFlat };
mdRotatedHyperboles,
mdGUARD, mdUnchanged, mdHyperboloidFlat, mdPolynomial
};
namespace conformal {
extern bool on;
@ -1325,6 +1329,9 @@ namespace conformal {
void progress_screen();
void progress(string str);
bool model_has_orientation();
extern string formula;
extern eModel basic_model;
}
namespace polygonal {

View File

@ -516,6 +516,43 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
break;
}
case mdRotatedHyperboles: {
// ld zlev = <- not implemented
find_zlev(H); // + geom3::depth;
conformal::apply_orientation(H[0], H[1]);
ld y = asin_auto(H[1]);
ld x = asin_auto_clamp(H[0] / cos_auto(y));
// ld z = zlev == 1 ? 0 : geom3::factor_to_lev(zlev);
ld factor = geom3::lev_to_factor(y + geom3::depth);
ret[0] = sinh(x) * factor;
ret[1] = cosh(x) * factor;
ret[2] = 0;
ret[0] = atan(ret[0]);
ret[1] = atan(ret[1]);
break;
}
case mdFormula: {
dynamicval<eModel> m(pmodel, conformal::basic_model);
applymodel(H, ret);
exp_parser ep;
ep.extra_params["z"] = cld(ret[0], ret[1]);
ep.extra_params["cx"] = ret[0];
ep.extra_params["cy"] = ret[1];
ep.extra_params["cz"] = ret[2];
ep.s = conformal::formula;
cld res = ep.parse();
ret[0] = real(res);
ret[1] = imag(res);
ret[2] = 0;
break;
}
case mdGUARD: break;
}

View File

@ -191,6 +191,7 @@ bool two_sided_model() {
// if(pmodel == mdHemisphere) return true;
if(pmodel == mdDisk) return sphere;
if(pmodel == mdHemisphere) return true;
if(pmodel == mdRotatedHyperboles) return true;
return false;
}
@ -201,6 +202,8 @@ int get_side(const hyperpoint& H) {
return (H[2] <= -horizon) ? -1 : 1;
;
}
if(pmodel == mdRotatedHyperboles)
return H[1] > 0 ? -1 : 1;
if(pmodel == mdHyperboloid && hyperbolic)
return (conformal::sin_ball * H[2] > -conformal::cos_ball * H[1]) ? -1 : 1;
if(pmodel == mdHyperboloid && sphere)