mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-19 15:20:27 +00:00
extra two-point projections
This commit is contained in:
parent
e5e0dfbac1
commit
ec82e5695b
@ -581,7 +581,7 @@ const modelinfo models[int(mdPolynomial)+1] = {
|
||||
{X3("band equidistant"), mf::band | mf::equidistant | mf::euc_boring},
|
||||
{X3("band equi-area"), mf::band | mf::equiarea | mf::euc_boring},
|
||||
{X3("sinusoidal"), mf::quasiband | mf::equiarea | mf::euc_boring},
|
||||
{X3("two-point equidistant"), mf::equidistant | mf::euc_boring},
|
||||
{X3("two-point equidistant"), mf::equidistant | mf::euc_boring | mf::twopoint},
|
||||
{X3("fisheye"), 0},
|
||||
{X3("Joukowsky transform"), mf::hyper_only | mf::conformal},
|
||||
{X3("Joukowsky+inversion"), mf::hyper_only | mf::conformal},
|
||||
@ -590,6 +590,8 @@ const modelinfo models[int(mdPolynomial)+1] = {
|
||||
{X3("native perspective"), 0},
|
||||
{X3("azimuthal equi-volume"), mf::azimuthal | mf::equivolume | mf::euc_boring},
|
||||
{X3("central inversion"), mf::azimuthal | mf::conformal},
|
||||
{X3("two-point azimuthal"), mf::euc_boring | mf::twopoint},
|
||||
{X3("two-point hybrid"), mf::euc_boring | mf::twopoint},
|
||||
{X3(""), 0},
|
||||
{X3(""), 0},
|
||||
{X3(""), 0},
|
||||
|
@ -256,11 +256,17 @@ struct landtacinfo { eLand l; int tries, multiplier; };
|
||||
|
||||
enum eModel {
|
||||
mdDisk, mdHalfplane, mdBand, mdPolygonal, mdFormula,
|
||||
// 5..8.
|
||||
mdEquidistant, mdEquiarea, mdBall, mdHyperboloid,
|
||||
// 9..13
|
||||
mdHemisphere, mdBandEquidistant, mdBandEquiarea, mdSinusoidal, mdTwoPoint,
|
||||
// 14..16
|
||||
mdFisheye, mdJoukowsky, mdJoukowskyInverted,
|
||||
// 17..19
|
||||
mdRotatedHyperboles, mdSpiral, mdPerspective,
|
||||
mdEquivolume, mdCentralInversion,
|
||||
// 20..22
|
||||
mdEquivolume, mdCentralInversion, mdSimulatedPerspective, mdTwoHybrid,
|
||||
// 24..
|
||||
mdGUARD, mdUnchanged, mdHyperboloidFlat, mdPolynomial, mdRug, mdFlatten
|
||||
};
|
||||
|
||||
@ -278,6 +284,7 @@ namespace mf {
|
||||
static const flagtype hyper_or_torus = 256;
|
||||
static const flagtype quasiband = 512;
|
||||
static const flagtype equivolume = 1024;
|
||||
static const flagtype twopoint = 2048;
|
||||
};
|
||||
|
||||
struct modelinfo {
|
||||
|
@ -641,7 +641,7 @@ namespace conformal {
|
||||
|
||||
bool model_has_orientation() {
|
||||
return
|
||||
among(pmodel, mdHalfplane, mdPolynomial, mdPolygonal, mdTwoPoint, mdJoukowsky, mdJoukowskyInverted, mdSpiral) || mdBandAny();
|
||||
among(pmodel, mdHalfplane, mdPolynomial, mdPolygonal, mdTwoPoint, mdJoukowsky, mdJoukowskyInverted, mdSpiral, mdSimulatedPerspective, mdTwoHybrid) || mdBandAny();
|
||||
}
|
||||
|
||||
bool model_has_transition() {
|
||||
@ -752,7 +752,7 @@ namespace conformal {
|
||||
eModel m = eModel(i);
|
||||
if(m == mdFormula && ISMOBILE) continue;
|
||||
if(model_available(m)) {
|
||||
dialog::addBoolItem(get_model_name(m), pmodel == m, "0123456789!@#$%^&*()]['" [m]);
|
||||
dialog::addBoolItem(get_model_name(m), pmodel == m, "0123456789!@#$%^&*()][{}'" [m]);
|
||||
dialog::add_action([m] () {
|
||||
if(m == mdFormula) {
|
||||
edit_formula();
|
||||
@ -927,10 +927,10 @@ namespace conformal {
|
||||
});
|
||||
}
|
||||
|
||||
if(pmodel == mdTwoPoint) {
|
||||
if(among(pmodel, mdTwoPoint, mdSimulatedPerspective, mdTwoHybrid)) {
|
||||
dialog::addSelItem(XLAT("parameter"), fts(vid.twopoint_param), 'b');
|
||||
dialog::add_action([](){
|
||||
dialog::editNumber(vid.twopoint_param, 0, 10, .1, 1, XLAT("parameter"),
|
||||
dialog::editNumber(vid.twopoint_param, 1e-3, 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 "
|
||||
"the center."
|
||||
|
110
hypgraph.cpp
110
hypgraph.cpp
@ -257,6 +257,52 @@ hyperpoint mobius(hyperpoint h, ld angle, ld scale = 1) {
|
||||
return space_to_perspective(h, 1) / scale;
|
||||
}
|
||||
|
||||
hyperpoint compute_hybrid(hyperpoint H, int rootid) {
|
||||
auto& t = vid.twopoint_param;
|
||||
hyperpoint Hl = xpush(+t) * H;
|
||||
hyperpoint Hr = xpush(-t) * H;
|
||||
ld g = (Hl[0] + 1e-7) / (Hl[1] + 1e-8);
|
||||
ld d = hdist0(Hr);
|
||||
|
||||
hyperpoint spinned = spintox(Hl) * xpush0(2*t);
|
||||
if(Hl[0] < 0) spinned = pispin * spinned;
|
||||
|
||||
ld y = asin_auto(spinned[1]);
|
||||
ld x = asin_auto_clamp(spinned[0] / cos_auto(y));
|
||||
|
||||
int sign = (Hl[0] > 0 ? 1 : -1) * hdist0(Hl) < x ? -1 : 1;
|
||||
|
||||
switch(rootid & 3) {
|
||||
case 1: sign = -sign; break;
|
||||
case 2: sign = 1; break;
|
||||
case 3: sign = -1; break;
|
||||
}
|
||||
|
||||
// (x + t) / g = y
|
||||
// yy + (x-t)(x-t) = dd
|
||||
// (x+t)*(x+t)/g*g + x*x + t*t - 2*x*t = dd
|
||||
|
||||
// x*x*(1+1/g*g) + t*t*(1+1/g*g) + 2xt (1/gg-1) = dd
|
||||
// xx + 2xt (1/gg-1) / (1+1/gg) = dd / (1+1/gg) - tt
|
||||
|
||||
ld b = t*(1/g/g - 1) / (1+1/g/g);
|
||||
ld c = d*d / (1+1/g/g) - t*t;
|
||||
|
||||
// xx + 2bx = c
|
||||
// xx + 2bx + bb = c + bb
|
||||
// (x+b)^2 = c+bb
|
||||
// x = +/- sqrt(c+bb) - b
|
||||
|
||||
ld a = c+b*b;
|
||||
|
||||
hyperpoint ret;
|
||||
ret[0] = (a > 0 ? sign * sqrt(a) : 0) - b;
|
||||
ret[1] = (ret[0] + t) / g;
|
||||
ret[2] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void applymodel(hyperpoint H, hyperpoint& ret) {
|
||||
|
||||
using namespace hyperpoint_vec;
|
||||
@ -436,6 +482,43 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
|
||||
break;
|
||||
}
|
||||
|
||||
case mdSimulatedPerspective: {
|
||||
conformal::apply_orientation_yz(H[1], H[2]);
|
||||
conformal::apply_orientation(H[0], H[1]);
|
||||
auto yz = move_z_to_y(H);
|
||||
hyperpoint Hl = xpush(-vid.twopoint_param) * H;
|
||||
hyperpoint Hr = xpush(+vid.twopoint_param) * H;
|
||||
ld lyx = (Hl[1] + 1e-7) / (Hl[0] + 1e-8);
|
||||
ld ryx = (Hr[1] + 1e-7) / (Hr[0] + 1e-8);
|
||||
// (r.x + t) * lyx = (r.x - t) * ryx = r.y
|
||||
// r.x * lyx + t * lyx = r.x * ryx - t * ryx
|
||||
// r.x * (lyx-ryx) = - t * (ryx + lyx)
|
||||
// r.x = -t * (ryx+lyx) / (lyx-ryx)
|
||||
// r.x = - 2 * t * lyx * ryx / lyx / ryx
|
||||
|
||||
ret[0] = -vid.twopoint_param * (ryx + lyx) / (lyx - ryx);
|
||||
ret[1] = (ret[0] + vid.twopoint_param) * lyx;
|
||||
ret[2] = 0;
|
||||
|
||||
move_y_to_z(ret, yz);
|
||||
conformal::apply_orientation(ret[0], ret[1]);
|
||||
conformal::apply_orientation_yz(ret[2], ret[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
case mdTwoHybrid: {
|
||||
conformal::apply_orientation_yz(H[1], H[2]);
|
||||
conformal::apply_orientation(H[0], H[1]);
|
||||
auto yz = move_z_to_y(H);
|
||||
|
||||
ret = compute_hybrid(H, whateveri[0]);
|
||||
|
||||
move_y_to_z(ret, yz);
|
||||
conformal::apply_orientation(ret[0], ret[1]);
|
||||
conformal::apply_orientation_yz(ret[2], ret[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
case mdJoukowsky:
|
||||
case mdJoukowskyInverted: {
|
||||
conformal::apply_orientation_yz(H[1], H[2]);
|
||||
@ -1394,8 +1477,33 @@ void draw_model_elements() {
|
||||
queuechr(current_display->xcenter, current_display->ycenter + current_display->radius * vid.alpha, 0, vid.fsize, 'X', ringcolor, 1, 8);
|
||||
return;
|
||||
}
|
||||
|
||||
case mdTwoHybrid: {
|
||||
queuereset(mdUnchanged, PPR::CIRCLE);
|
||||
|
||||
for(int mode=0; mode<4; mode++) {
|
||||
for(int s=-199; s<=199; s += 2) {
|
||||
ld p = s / 200.;
|
||||
ld a = vid.twopoint_param * (1+p);
|
||||
ld b = vid.twopoint_param * (1-p);
|
||||
ld h = ((mode & 2) ? -1 : 1) * sqrt(asin_auto(tan_auto(a) * tan_auto(b)));
|
||||
|
||||
hyperpoint H = xpush(p * vid.twopoint_param) * ypush0(h);
|
||||
|
||||
hyperpoint res = compute_hybrid(H, 2 | mode);
|
||||
conformal::apply_orientation(res[0], res[1]);
|
||||
conformal::apply_orientation_yz(res[2], res[1]);
|
||||
using namespace hyperpoint_vec;
|
||||
curvepoint(res * current_display->radius);
|
||||
}
|
||||
queuecurve(ringcolor, 0, PPR::CIRCLE);
|
||||
}
|
||||
|
||||
case mdTwoPoint: {
|
||||
queuereset(pmodel, PPR::CIRCLE);
|
||||
/* fallthrough */
|
||||
}
|
||||
|
||||
case mdTwoPoint: case mdSimulatedPerspective: {
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user