model orientation

This commit is contained in:
Zeno Rogue 2018-10-23 16:58:19 +02:00
parent 04c41d38ed
commit a9535878c4
9 changed files with 142 additions and 45 deletions

View File

@ -208,7 +208,8 @@ void initConfig() {
addsaver(conformal::bandsegment, "band segment");
addsaver(conformal::rotation, "conformal rotation");
addsaver(conformal::do_rotate, "conformal rotation mode", 1);
addsaver(conformal::lower_halfplane, "lower halfplane", false);
addsaver(conformal::model_orientation, "model orientation", 0);
addsaver(conformal::halfplane_scale, "halfplane scale", 1);
addsaver(conformal::autoband, "automatic band");
addsaver(conformal::autobandhistory, "automatic band history");
addsaver(conformal::dospiral, "do spiral");
@ -1486,6 +1487,11 @@ int read_config_args() {
else if(argis("-PM")) {
PHASEFROM(2); shift(); pmodel = eModel(argi());
}
else if(argis("-hp")) {
PHASEFROM(2);
shift(); conformal::model_orientation = argf();
shift(); conformal::halfplane_scale = argf();
}
else if(argis("-zoom")) {
PHASEFROM(2); shift(); vid.scale = argf();
}

View File

@ -97,12 +97,18 @@ namespace polygonal {
void drawBoundary(int color) {
queuereset(mdDisk, PPR::CIRCLE);
ld C, S;
auto& ho = conformal::model_orientation;
if(ho == 0) C = 1, S = 0;
else if(ho == 180) C = -1, S = 0;
else C = cos(ho * M_PI/180), S = sin(ho * M_PI / 180);
for(int r=0; r<=2000; r++) {
cld z = exp(cld(0, 2*M_PI * r / 2000.0));
pair<xld,xld> z2 = compute(real(z), imag(z), deg);
hyperpoint h;
h[0] = z2.first * vid.radius;
h[1] = z2.second * vid.radius;
h[0] = (z2.first * C - z2.second * S) * vid.radius;
h[1] = (z2.second * C + z2.first * S) * vid.radius;
h[2] = stereo::scrdist;
curvepoint(h);
}
@ -288,7 +294,10 @@ namespace conformal {
int bandsegment = 16000;
ld rotation = 0;
int do_rotate = 1;
bool lower_halfplane;
ld model_orientation, halfplane_scale;
ld ocos, osin;
bool model_straight;
bool autoband = false;
bool autobandhistory = false;
bool dospiral = true;
@ -401,6 +410,13 @@ namespace conformal {
movetophase();
}
void configure() {
ocos = cos(model_orientation * M_PI / 180);
osin = sin(model_orientation * M_PI / 180);
model_straight = (ocos > 1 - 1e-9);
if(conformal::on) conformal::apply();
}
ld measureLength() {
ld r = bandhalf * vid.scale;
@ -580,6 +596,11 @@ namespace conformal {
return true;
}
bool model_has_orientation() {
return
among(pmodel, mdHalfplane, mdPolynomial, mdPolygonal, mdTwoPoint) || mdBandAny();
}
void model_menu() {
cmode = sm::SIDE | sm::MAYDARK | sm::CENTER;
gamescreen(0);
@ -608,6 +629,9 @@ namespace conformal {
if(pmodel == mdDisk || pmodel == mdBall || pmodel == mdHyperboloid) {
dialog::addSelItem(XLAT("Projection at the ground level"), fts3(vid.alpha), 'p');
}
if(model_has_orientation())
dialog::addSelItem(XLAT("model orientation"), fts(model_orientation), 'l');
if(pmodel == mdPolynomial) {
dialog::addSelItem(XLAT("coefficient"),
@ -617,8 +641,9 @@ namespace conformal {
dialog::addSelItem(XLAT("which coefficient"), its(polygonal::coefid), 'n');
}
if(pmodel == mdHalfplane)
dialog::addBoolItem(XLAT("lower half-plane"), lower_halfplane, 'l');
if(pmodel == mdHalfplane) {
dialog::addSelItem(XLAT("half-plane scale"), fts(halfplane_scale), 'b');
}
if(pmodel == mdBall)
dialog::addSelItem(XLAT("projection in ball model"), fts3(vid.ballproj), 'x');
@ -638,7 +663,7 @@ namespace conformal {
}
if(pmodel == mdTwoPoint) {
dialog::addSelItem(XLAT("parameter"), fts3(vid.twopoint_param), 'l');
dialog::addSelItem(XLAT("parameter"), fts3(vid.twopoint_param), 'b');
}
dialog::addSelItem(XLAT("vertical stretch"), fts3(vid.stretch), 's');
@ -679,14 +704,14 @@ namespace conformal {
editScale();
else if(uni == 'p')
projectionDialog();
else if(uni == 'b')
config_camera_rotation();
#if CAP_RUG
else if(uni == 'u')
pushScreen(rug::show);
#endif
else if(uni == 'l' && pmodel == mdHalfplane)
lower_halfplane = !lower_halfplane;
else if(uni == 'l' && model_has_orientation())
dialog::editNumber(model_orientation, 0, 360, 90, 0, XLAT("model orientation"), "");
else if(uni == 'b' && pmodel == mdHalfplane)
dialog::editNumber(model_orientation, 0, 2, 0.25, 1, XLAT("halfplane scale"), "");
else if(uni == 's') {
dialog::editNumber(vid.stretch, 0, 10, .1, 1, XLAT("vertical stretch"),
"Vertical stretch factor."
@ -720,7 +745,7 @@ namespace conformal {
);
dialog::scaleLog();
}
else if(uni == 'l' && pmodel == mdTwoPoint) {
else if(uni == 'b' && pmodel == mdTwoPoint) {
dialog::editNumber(vid.twopoint_param, 0, 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 "
@ -728,6 +753,8 @@ namespace conformal {
);
dialog::scaleLog();
}
else if(uni == 'b')
config_camera_rotation();
else if(uni == 'x' && pmodel == mdBall)
dialog::editNumber(vid.ballproj, 0, 100, .1, 0, XLAT("projection in ball model"),
"This parameter affects the ball model the same way as the projection parameter affects the disk model.");

View File

@ -485,9 +485,9 @@ void mainloopiter() {
#endif
optimizeview();
if(conformal::on) conformal::apply();
conformal::configure();
ticks = SDL_GetTicks();
callhooks(hooks_fixticks);

View File

@ -5470,8 +5470,9 @@ void drawfullmap() {
ptds.clear();
if(pmodel == mdTwoPoint) {
queuechr(xpush0(+vid.twopoint_param), vid.xres / 100, 'X', 0xFF0000);
queuechr(xpush0(-vid.twopoint_param), vid.xres / 100, 'X', 0xFF0000);
ld a = -conformal::model_orientation * M_PI / 180;
queuechr(xspinpush0(a, +vid.twopoint_param), vid.xres / 100, 'X', 0xFF0000);
queuechr(xspinpush0(a, -vid.twopoint_param), vid.xres / 100, 'X', 0xFF0000);
}
/*
@ -5493,11 +5494,14 @@ void drawfullmap() {
ld x = sin(a * vid.twopoint_param * b / 90);
ld y = 0;
ld z = -sqrt(1 - x*x);
conformal::apply_orientation(y, x);
hyperpoint h1;
applymodel(hpxyz(x,y,z), h1);
conformal::apply_orientation(h1[0], h1[1]);
h1[1] = abs(h1[1]) * b;
curvepoint(h1 * vid.radius);
conformal::apply_orientation(h1[1], h1[0]);
curvepoint(h1);
}
queuecurve(ringcolor, 0, PPR::CIRCLE);

14
hyper.h
View File

@ -1275,7 +1275,18 @@ namespace conformal {
extern bool includeHistory;
extern ld rotation;
extern int do_rotate;
extern bool lower_halfplane;
extern ld model_orientation;
extern ld halfplane_scale;
extern ld ocos, osin;
extern bool model_straight;
// screen coordinates to logical coordinates: apply_orientation(x,y)
// logical coordinates back to screen coordinates: apply_orientation(y,x)
template<class A>
void apply_orientation(A& x, A& y) { if(!model_straight) tie(x,y) = make_pair(x*ocos + y*osin, y*ocos - x*osin); }
void configure();
extern bool autoband;
extern bool autobandhistory;
extern bool dospiral;
@ -1299,6 +1310,7 @@ namespace conformal {
void progress_screen();
void progress(string str);
bool model_has_orientation();
}
namespace polygonal {

View File

@ -268,7 +268,9 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
apply_depth(ret, y * zf / M_PI);
}
else {
ld x, y, yf, zf;
conformal::apply_orientation(H[0], H[1]);
ld x, y, yf, zf=0;
y = asin_auto(H[1]);
x = asin_auto_clamp(H[0] / cos_auto(y));
if(sphere) {
@ -331,9 +333,11 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
printf("unknown model\n");
}
}
ret = hpxyz(x / M_PI, y * yf / M_PI, 0);
ld yzf = y * zf; y *= yf;
conformal::apply_orientation(y, x);
ret = hpxyz(x / M_PI, y / M_PI, 0);
if(zlev_used && stereo::active())
apply_depth(ret, y * zf / M_PI);
apply_depth(ret, yzf / M_PI);
}
ghcheck(ret, H);
return;
@ -365,7 +369,12 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
tz = H[2]+vid.alpha;
if(pmodel == mdPolygonal || pmodel == mdPolynomial) {
conformal::apply_orientation(H[0], H[1]);
pair<long double, long double> p = polygonal::compute(H[0]/tz, H[1]/tz);
conformal::apply_orientation(p.second, p.first);
ret[0] = p.first;
ret[1] = p.second;
ret[2] = 0;
@ -379,21 +388,25 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
ld x0, y0;
x0 = H[0] / tz;
y0 = H[1] / tz;
if(conformal::lower_halfplane) x0 = -x0, y0 = -y0;
conformal::apply_orientation(x0, y0);
y0 += 1;
double rad = x0*x0 + y0*y0;
y0 /= rad;
x0 /= rad;
y0 -= .5;
if(conformal::lower_halfplane) x0 = -x0, y0 = -y0;
y0 /= -rad;
x0 /= -rad;
y0 += .5;
ret[0] = x0;
conformal::apply_orientation(y0, x0);
auto& ps = conformal::halfplane_scale;
x0 *= ps, y0 *= ps;
ret[0] = -conformal::osin + x0;
if(wmspatial || mmspatial) {
if(conformal::lower_halfplane) y0 /= zlev;
else y0 *= zlev;
y0 = y0 * pow(zlev, conformal::ocos);
}
ret[1] = (conformal::lower_halfplane?-1:1) - y0;
ret[1] = conformal::ocos + y0;
ret[2] = 0;
if(zlev != 1 && stereo::active())
apply_depth(ret, -y0 * geom3::factor_to_lev(zlev));

View File

@ -300,8 +300,8 @@ void mobile_draw(MOBPAR_FORMAL) {
// if(debfile) fprintf(debfile, "d1\n"), fflush(debfile);
frames++;
if(conformal::on) conformal::apply();
conformal::configure();
if(ticks > lastt) tortoise::updateVals(ticks - lastt);
if(clicked && !lclicked) touchedAt = ticks;

View File

@ -584,14 +584,24 @@ void fixMercator(bool tinf) {
else
mercator_period = 2 * vid.radius;
if(!conformal::model_straight)
for(auto& g: glcoords)
conformal::apply_orientation(g[0], g[1]);
if(pmodel == mdSinusoidal)
for(int i = 0; i<isize(glcoords); i++)
glcoords[i][mercator_coord] /= cos(glcoords[i][1] / vid.radius / vid.stretch * M_PI);
ld hperiod = mercator_period / 2;
mercator_coord = 0;
ld cmin = -vid.xcenter, cmax = vid.xres - vid.xcenter, dmin = -vid.ycenter, dmax = vid.yres - vid.ycenter;
auto dist = [] (ld a, ld b) { return max(b, a-b); };
ld chypot = hypot(dist(vid.xres, vid.xcenter), dist(vid.yres, vid.ycenter));
ld cmin = -chypot/2, cmax = chypot/2, dmin = -chypot, dmax = chypot;
if(mercator_coord)
swap(cmin, dmin), swap(cmax, dmax);
if(pmodel == mdSinusoidal)
@ -638,6 +648,9 @@ void fixMercator(bool tinf) {
if(pmodel == mdSinusoidal)
for(int i = 0; i<isize(glcoords); i++)
glcoords[i][mercator_coord] *= cos(glcoords[i][1] / vid.radius / vid.stretch * M_PI);
if(!conformal::model_straight)
for(auto& g: glcoords)
conformal::apply_orientation(g[1], g[0]);
}
else {
if(tinf) {
@ -671,6 +684,9 @@ void fixMercator(bool tinf) {
auto& v = glcoords[isize(glcoords)-u][1-mercator_coord];
v = v < 0 ? dmin : dmax;
}
if(!conformal::model_straight)
for(auto& g: glcoords)
conformal::apply_orientation(g[1], g[0]);
/* printf("cycling %d -> %d\n", base, qglcoords);
for(int a=0; a<qglcoords; a++)
printf("[%3d] %10.5lf %10.5lf\n", a, glcoords[a][0], glcoords[a][1]); */
@ -761,10 +777,14 @@ void dqi_poly::draw() {
// (which corresponds to the segment between the antipodes of foci)
// if yes, switch cpha to the opposite
hyperpoint h2 = V * glhr::gltopoint((*tab)[offset+(i+1)%cnt]);
if(h1[1] * h2[1] > 0) continue;
ld c1 = h1[1], c2 = -h2[1];
hyperpoint ah1 = h1, ah2 = h2;
conformal::apply_orientation(ah1[0], ah1[1]);
conformal::apply_orientation(ah2[0], ah2[1]);
if(ah1[1] * ah2[1] > 0) continue;
ld c1 = ah1[1], c2 = -ah2[1];
if(c1 < 0) c1 = -c1, c2 = -c2;
hyperpoint h = h1 * c1 + h2 * c2;
hyperpoint h = ah1 * c1 + ah2 * c2;
h /= hypot3(h);
if(h[2] < 0 && abs(h[0]) < sin(vid.twopoint_param)) cpha = 1-cpha, pha = 2;
}
@ -936,9 +956,13 @@ void dqi_poly::draw() {
if(l || lastl) {
for(int i=0; i<isize(glcoords); i++) {
if(pmodel == mdSinusoidal)
mercator_period = 2 * vid.radius * cos(glcoords[i][1] / vid.radius / vid.stretch * M_PI);
glcoords[i][mercator_coord] += mercator_period * (l - lastl);
if(pmodel == mdSinusoidal) {
ld y = glcoords[i][1], x = glcoords[i][0];
conformal::apply_orientation(x, y);
mercator_period = 2 * vid.radius * cos(y / vid.radius / vid.stretch * M_PI);
}
glcoords[i][mercator_coord] += conformal::ocos * mercator_period * (l - lastl);
glcoords[i][1-mercator_coord] += conformal::osin * mercator_period * (l - lastl);
}
lastl = l;
}

View File

@ -421,6 +421,7 @@ vector<animatable_parameter> animatable_parameters = {
animatable_parameter(vid.ballproj),
animatable_parameter(surface::dini_b),
animatable_parameter(surface::hyper_b),
animatable_parameter(conformal::halfplane_scale),
};
ld anim_param = 0;
@ -507,8 +508,12 @@ void apply() {
rug::apply_rotation(rug::currentrot * rotmatrix(rug_rotation2 * 2 * M_PI * t / period, 0, 1) * inverse(rug::currentrot));
}
}
if(ballangle_rotation)
vid.ballangle += ballangle_rotation * 360 * t / period;
if(ballangle_rotation) {
if(conformal::model_has_orientation())
conformal::model_orientation += ballangle_rotation * 360 * t / period;
else
vid.ballangle += ballangle_rotation * 360 * t / period;
}
if(paramstate == 2 && anim_param) {
ld phase = (1 + sin(anim_param * 2 * M_PI * ticks / period)) / 2;
for(auto& ap: animatable_parameters) if(ap.values[0] != ap.values[1]) {
@ -540,6 +545,10 @@ string animfile = "animation-%04d.png";
bool record_animation() {
for(int i=0; i<noframes; i++) {
ticks = i * period / noframes;
if(conformal::on) {
conformal::phase = isize(conformal::v) * i * 1. / noframes;
conformal::movetophase();
}
char buf[1000];
snprintf(buf, 1000, animfile.c_str(), i);
@ -735,7 +744,9 @@ void show() {
});
}
#endif
if(among(pmodel, mdHyperboloid, mdHemisphere, mdBall))
if(conformal::model_has_orientation())
animator(XLAT("model rotation"), ballangle_rotation, 'r');
else if(among(pmodel, mdHyperboloid, mdHemisphere, mdBall))
animator(XLAT("3D rotation"), ballangle_rotation, 'r');
animator(XLAT("animate parameter change"), anim_param, 'P');