vertical stretch parameter is now available in all models; more details in equi-area

This commit is contained in:
Zeno Rogue 2018-08-01 04:01:16 +02:00
parent 1e15992a22
commit 5e2a65a781
7 changed files with 59 additions and 30 deletions

View File

@ -828,14 +828,14 @@ ld realradius() {
void drawmessage(const string& s, int& y, int col) {
int rrad = (int) realradius();
int space;
if(y > vid.ycenter + rrad)
if(y > vid.ycenter + rrad * vid.stretch)
space = vid.xres;
else if(y > vid.ycenter)
space = vid.xcenter - rhypot(rrad, y-vid.ycenter);
space = vid.xcenter - rhypot(rrad, (y-vid.ycenter) / vid.stretch);
else if(y > vid.ycenter - vid.fsize)
space = vid.xcenter - rrad;
else if(y > vid.ycenter - vid.fsize - rrad)
space = vid.xcenter - rhypot(rrad, vid.ycenter-vid.fsize-y);
else if(y > vid.ycenter - vid.fsize - rrad * vid.stretch)
space = vid.xcenter - rhypot(rrad, (vid.ycenter-vid.fsize-y) / vid.stretch);
else
space = vid.xres;
@ -920,7 +920,7 @@ void drawCircle(int x, int y, int size, int color) {
if(ISMOBILE && pts > 72) pts = 72;
for(int r=0; r<pts; r++) {
float rr = (M_PI * 2 * r) / pts;
glcoords.push_back(make_array<GLfloat>(x + size * sin(rr), y + size * cos(rr), stereo::scrdist));
glcoords.push_back(make_array<GLfloat>(x + size * sin(rr), y + size * vid.stretch * cos(rr), stereo::scrdist));
}
glhr::vertices(glcoords);
glhr::set_depthtest(false);
@ -932,7 +932,10 @@ void drawCircle(int x, int y, int size, int color) {
#if CAP_XGD
gdpush(4); gdpush(color); gdpush(x); gdpush(y); gdpush(size);
#elif CAP_SDLGFX
((vid.antialias && AA_NOGL)?aacircleColor:circleColor) (s, x, y, size, color);
if(vid.stretch == 1)
((vid.antialias && AA_NOGL)?aacircleColor:circleColor) (s, x, y, size, color);
else
((vid.antialias && AA_NOGL)?aaellipseColor:ellipseColor) (s, x, y, size, size * vid.stretch, color);
#elif CAP_SDL
int pts = size * 4;
if(pts > 1500) pts = 1500;

View File

@ -641,9 +641,7 @@ namespace conformal {
dialog::addSelItem(XLAT("parameter"), fts3(vid.twopoint_param), 'l');
}
if(among(pmodel, mdBandEquidistant, mdBandEquiarea)) {
dialog::addSelItem(XLAT("parameter"), fts3(vid.stretch), 'l');
}
dialog::addSelItem(XLAT("vertical stretch"), fts3(vid.stretch), 's');
dialog::addBreak(100);
dialog::addItem(XLAT("history mode"), 'a');
@ -689,10 +687,31 @@ namespace conformal {
#endif
else if(uni == 'l' && pmodel == mdHalfplane)
lower_halfplane = !lower_halfplane;
else if(uni == 'l' && among(pmodel, mdBandEquiarea, mdBandEquidistant))
dialog::editNumber(vid.stretch, 0, 10, .1, 1, XLAT("parameter"),
else if(uni == 's') {
dialog::editNumber(vid.stretch, 0, 10, .1, 1, XLAT("vertical stretch"),
"Vertical stretch factor."
);
dialog::extra_options = [] () {
dialog::addBreak(100);
if(sphere && pmodel == mdBandEquiarea) {
dialog::addBoolItem("Gall-Peters", vid.stretch == 2, 'o');
dialog::add_action([] { vid.stretch = 2; dialog::ne.s = "2"; });
}
if(pmodel == mdBandEquiarea) {
// y = K * sin(phi)
// cos(phi) * cos(phi) = 1/K
if(sphere && vid.stretch >= 1) {
ld phi = acos(sqrt(1/vid.stretch));
dialog::addInfo(XLAT("The current value makes the map conformal at the latitude of %1 (%2°).", fts(phi), fts(phi * 180 / M_PI)));
}
else if(hyperbolic && abs(vid.stretch) <= 1 && abs(vid.stretch) >= 1e-9) {
ld phi = acosh(abs(sqrt(1/vid.stretch)));
dialog::addInfo(XLAT("The current value makes the map conformal %1 units from the main line.", fts(phi)));
}
else dialog::addInfo("");
}
};
}
else if(uni == 'a')
pushScreen(history_menu);
else if(uni == 'l' && pmodel == mdHemisphere && euclid) {

View File

@ -2260,7 +2260,7 @@ void drawaura() {
for(int x=0; x<vid.xres; x++) {
ld hx = (x * 1. - vid.xcenter) / rad;
ld hy = (y * 1. - vid.ycenter) / rad;
ld hy = (y * 1. - vid.ycenter) / rad / vid.stretch;
if(vid.camera_angle) camrotate(hx, hy);
@ -2315,7 +2315,7 @@ void drawaura() {
float rad0 = vid.alpha > -1 ? rad * facs[z] : rad / facs[z];
int rm = r % AURA;
cx[r][z][0] = rad0 * sin(rr);
cx[r][z][1] = rad0 * cos(rr);
cx[r][z][1] = rad0 * cos(rr) * vid.stretch;
for(int u=0; u<3; u++)
cx[r][z][u+2] = bak[u] + (aurac[rm][u] / (aurac[rm][3]+.1) - bak[u]) * cmul[z];
}

View File

@ -418,7 +418,7 @@ void drawStats() {
int spots = 0;
for(int u=vid.fsize; u<vid.xres/2-s; u += s)
for(int v=vid.fsize; v<vid.yres/2-s; v += s)
if(hypot(vid.xres/2-u-s, vid.yres/2-v-s) > rad) {
if(hypot(vid.xres/2-u-s, (vid.yres/2-v-s) / vid.stretch) > rad) {
spots++;
}
if(spots >= bycorner[cor] && spots >= 3) {
@ -431,7 +431,7 @@ void drawStats() {
}
for(int u=vid.fsize; u<vid.xres/2-s; u += s)
for(int v=vid.fsize; v<vid.yres/2-s; v += s)
if(hypot(vid.xres/2-u-s, vid.yres/2-v-s) > rad) {
if(hypot(vid.xres/2-u-s, (vid.yres/2-v-s) / vid.stretch) > rad) {
if(next >= isize(glyphstoshow)) break;
int cx = u;

View File

@ -317,7 +317,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
break;
}
case mdBandEquiarea: {
y = sin_auto(y) * vid.stretch;
y = sin_auto(y);
break;
}
case mdSinusoidal: {
@ -325,7 +325,6 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
break;
}
case mdBandEquidistant: {
y *= vid.stretch;
break;
}
default: {

View File

@ -178,6 +178,7 @@ void addpoint(const hyperpoint& H) {
hyperpoint Hscr;
applymodel(H, Hscr);
for(int i=0; i<3; i++) Hscr[i] *= vid.radius;
Hscr[1] *= vid.stretch;
// if(vid.alpha + H[2] <= BEHIND_LIMIT && pmodel == mdDisk) poly_flags |= POLY_BEHIND;
if(spherespecial) {
@ -314,6 +315,8 @@ void glapplymatrix(const transmatrix& V) {
mat[13] = 0;
mat[14] = GLfloat(vid.alpha);
mat[15] = 1;
if(vid.stretch != 1) mat[1] *= vid.stretch, mat[5] *= vid.stretch, mat[9] *= vid.stretch, mat[13] *= vid.stretch;
glhr::set_modelview(glhr::as_glmatrix(mat));
}
@ -451,7 +454,7 @@ 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 * M_PI);
glcoords[i][mercator_coord] /= cos(glcoords[i][1] / vid.radius / vid.stretch * M_PI);
ld hperiod = mercator_period / 2;
@ -460,7 +463,7 @@ void fixMercator(bool tinf) {
if(mercator_coord)
swap(cmin, dmin), swap(cmax, dmax);
if(pmodel == mdSinusoidal)
dmin = -vid.radius / 2, dmax = vid.radius / 2;
dmin = -vid.stretch * vid.radius / 2, dmax = vid.stretch * vid.radius / 2;
if(pmodel == mdBandEquidistant)
dmin = -vid.stretch * vid.radius / 2, dmax = vid.stretch * vid.radius / 2;
if(pmodel == mdBandEquiarea)
@ -502,7 +505,7 @@ void fixMercator(bool tinf) {
mercator_loop_max++, maxcoord += mercator_period;
if(pmodel == mdSinusoidal)
for(int i = 0; i<isize(glcoords); i++)
glcoords[i][mercator_coord] *= cos(glcoords[i][1] / vid.radius * M_PI);
glcoords[i][mercator_coord] *= cos(glcoords[i][1] / vid.radius / vid.stretch * M_PI);
}
else {
if(tinf) {
@ -529,7 +532,7 @@ 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 * M_PI);
glcoords[i][mercator_coord] *= cos(glcoords[i][1] / vid.radius / vid.stretch * M_PI);
glcoords.push_back(glcoords.back());
glcoords.push_back(glcoords[0]);
for(int u=1; u<=2; u++) {
@ -595,7 +598,7 @@ void drawpolyline(polytodraw& p) {
twopoint_sphere_flips = j;
hyperpoint h2; applymodel(h1, h2);
using namespace hyperpoint_vec;
glvertex h = glhr::pointtogl(h2 * vid.radius);
glvertex h = glhr::pointtogl(h2 * vid.radius); h[1] *= vid.stretch;
if(i == 0)
phases[j].push_back(h);
else {
@ -624,7 +627,7 @@ void drawpolyline(polytodraw& p) {
using namespace hyperpoint_vec;
hyperpoint h1 = pp.V * glhr::gltopoint((*pp.tab)[pp.offset+i]);
hyperpoint mh1; applymodel(h1, mh1);
hyperpoint mh1; applymodel(h1, mh1); mh1[1] *= vid.stretch;
phases[cpha].push_back(glhr::pointtogl(mh1 * vid.radius));
// check if the i-th edge intersects the boundary of the ellipse
@ -719,7 +722,7 @@ void drawpolyline(polytodraw& p) {
hyperpoint hscr;
hyperpoint h1 = pp.V * intester;
if(is_behind(h1)) nofill = true;
applymodel(h1, hscr); hscr[0] *= vid.radius; hscr[1] *= vid.radius;
applymodel(h1, hscr); hscr[0] *= vid.radius; hscr[1] *= vid.radius * vid.stretch;
for(int i=0; i<isize(glcoords)-1; i++) {
double x1 = glcoords[i][0] - hscr[0];
double y1 = glcoords[i][1] - hscr[1];
@ -771,7 +774,7 @@ void drawpolyline(polytodraw& p) {
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 * M_PI);
mercator_period = 2 * vid.radius * cos(glcoords[i][1] / vid.radius / vid.stretch * M_PI);
glcoords[i][mercator_coord] += mercator_period * (l - lastl);
}
lastl = l;
@ -783,7 +786,7 @@ void drawpolyline(polytodraw& p) {
ld h = atan2(glcoords[0][0], glcoords[0][1]);
for(int i=0; i<=360; i++) {
ld a = i * M_PI / 180 + h;
glcoords.push_back(make_array<GLfloat>(vid.radius * sin(a), vid.radius * cos(a), stereo::scrdist));
glcoords.push_back(make_array<GLfloat>(vid.radius * sin(a), vid.radius * vid.stretch * cos(a), stereo::scrdist));
}
poly_flags ^= POLY_INVERSE;
}
@ -2513,7 +2516,7 @@ void getcoord0(const hyperpoint& h, int& xc, int &yc, int &sc) {
hyperpoint hscr;
applymodel(h, hscr);
xc = vid.xcenter + vid.radius * hscr[0];
yc = vid.ycenter + vid.radius * hscr[1];
yc = vid.ycenter + vid.radius * vid.stretch * hscr[1];
sc = 0;
// EYETODO sc = vid.eye * vid.radius * hscr[2];
}

View File

@ -73,9 +73,14 @@ namespace svg {
void circle(int x, int y, int size, int col) {
int ba = (backcolor << 8) + 0xFF;
if(!invisible(col))
fprintf(f, "<circle cx='%s' cy='%s' r='%s' %s/>\n",
coord(x), coord(y), coord(size), stylestr(ba, col));
if(!invisible(col)) {
if(vid.stretch == 1)
fprintf(f, "<circle cx='%s' cy='%s' r='%s' %s/>\n",
coord(x), coord(y), coord(size), stylestr(ba, col));
else
fprintf(f, "<circle cx='%s' cy='%s' rx='%s' ry='%s' %s/>\n",
coord(x), coord(y), coord(size), coord(size*vid.stretch), stylestr(ba, col));
}
}
const string *link;