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 equidistant"), mf::band | mf::equidistant | mf::euc_boring},
|
||||||
{X3("band equi-area"), mf::band | mf::equiarea | mf::euc_boring},
|
{X3("band equi-area"), mf::band | mf::equiarea | mf::euc_boring},
|
||||||
{X3("sinusoidal"), mf::quasiband | 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("fisheye"), 0},
|
||||||
{X3("Joukowsky transform"), mf::hyper_only | mf::conformal},
|
{X3("Joukowsky transform"), mf::hyper_only | mf::conformal},
|
||||||
{X3("Joukowsky+inversion"), 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("native perspective"), 0},
|
||||||
{X3("azimuthal equi-volume"), mf::azimuthal | mf::equivolume | mf::euc_boring},
|
{X3("azimuthal equi-volume"), mf::azimuthal | mf::equivolume | mf::euc_boring},
|
||||||
{X3("central inversion"), mf::azimuthal | mf::conformal},
|
{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},
|
{X3(""), 0},
|
||||||
{X3(""), 0},
|
{X3(""), 0},
|
||||||
|
@ -256,11 +256,17 @@ struct landtacinfo { eLand l; int tries, multiplier; };
|
|||||||
|
|
||||||
enum eModel {
|
enum eModel {
|
||||||
mdDisk, mdHalfplane, mdBand, mdPolygonal, mdFormula,
|
mdDisk, mdHalfplane, mdBand, mdPolygonal, mdFormula,
|
||||||
|
// 5..8.
|
||||||
mdEquidistant, mdEquiarea, mdBall, mdHyperboloid,
|
mdEquidistant, mdEquiarea, mdBall, mdHyperboloid,
|
||||||
|
// 9..13
|
||||||
mdHemisphere, mdBandEquidistant, mdBandEquiarea, mdSinusoidal, mdTwoPoint,
|
mdHemisphere, mdBandEquidistant, mdBandEquiarea, mdSinusoidal, mdTwoPoint,
|
||||||
|
// 14..16
|
||||||
mdFisheye, mdJoukowsky, mdJoukowskyInverted,
|
mdFisheye, mdJoukowsky, mdJoukowskyInverted,
|
||||||
|
// 17..19
|
||||||
mdRotatedHyperboles, mdSpiral, mdPerspective,
|
mdRotatedHyperboles, mdSpiral, mdPerspective,
|
||||||
mdEquivolume, mdCentralInversion,
|
// 20..22
|
||||||
|
mdEquivolume, mdCentralInversion, mdSimulatedPerspective, mdTwoHybrid,
|
||||||
|
// 24..
|
||||||
mdGUARD, mdUnchanged, mdHyperboloidFlat, mdPolynomial, mdRug, mdFlatten
|
mdGUARD, mdUnchanged, mdHyperboloidFlat, mdPolynomial, mdRug, mdFlatten
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -278,6 +284,7 @@ namespace mf {
|
|||||||
static const flagtype hyper_or_torus = 256;
|
static const flagtype hyper_or_torus = 256;
|
||||||
static const flagtype quasiband = 512;
|
static const flagtype quasiband = 512;
|
||||||
static const flagtype equivolume = 1024;
|
static const flagtype equivolume = 1024;
|
||||||
|
static const flagtype twopoint = 2048;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct modelinfo {
|
struct modelinfo {
|
||||||
|
@ -641,7 +641,7 @@ namespace conformal {
|
|||||||
|
|
||||||
bool model_has_orientation() {
|
bool model_has_orientation() {
|
||||||
return
|
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() {
|
bool model_has_transition() {
|
||||||
@ -752,7 +752,7 @@ namespace conformal {
|
|||||||
eModel m = eModel(i);
|
eModel m = eModel(i);
|
||||||
if(m == mdFormula && ISMOBILE) continue;
|
if(m == mdFormula && ISMOBILE) continue;
|
||||||
if(model_available(m)) {
|
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] () {
|
dialog::add_action([m] () {
|
||||||
if(m == mdFormula) {
|
if(m == mdFormula) {
|
||||||
edit_formula();
|
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::addSelItem(XLAT("parameter"), fts(vid.twopoint_param), 'b');
|
||||||
dialog::add_action([](){
|
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 "
|
"This model maps the world so that the distances from two points "
|
||||||
"are kept. This parameter gives the distance from the two points to "
|
"are kept. This parameter gives the distance from the two points to "
|
||||||
"the center."
|
"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;
|
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) {
|
void applymodel(hyperpoint H, hyperpoint& ret) {
|
||||||
|
|
||||||
using namespace hyperpoint_vec;
|
using namespace hyperpoint_vec;
|
||||||
@ -436,6 +482,43 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
|
|||||||
break;
|
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 mdJoukowsky:
|
||||||
case mdJoukowskyInverted: {
|
case mdJoukowskyInverted: {
|
||||||
conformal::apply_orientation_yz(H[1], H[2]);
|
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);
|
queuechr(current_display->xcenter, current_display->ycenter + current_display->radius * vid.alpha, 0, vid.fsize, 'X', ringcolor, 1, 8);
|
||||||
return;
|
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;
|
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);
|
||||||
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