mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-20 11:54:48 +00:00
ultra-ideal vertices should work now
This commit is contained in:
parent
403f38521e
commit
31a554f077
@ -1213,9 +1213,8 @@ struct hrmap_arbi : hrmap {
|
||||
hyperpoint get_corner(cell *c, int cid, ld cf) override {
|
||||
auto& sh = arb::current_or_slided().shapes[arb::id_of(c->master)];
|
||||
int id = gmod(cid, c->type);
|
||||
if(sh.angles[id] == 0) {
|
||||
return normalize(C0 + 999 * kleinize(sh.vertices[id]));
|
||||
}
|
||||
if(sh.angles[id] <= 0)
|
||||
return sh.vertices[id];
|
||||
return normalize(C0 + (sh.vertices[id] - C0) * 3 / cf);
|
||||
}
|
||||
|
||||
@ -1611,11 +1610,11 @@ EX void choose() {
|
||||
});
|
||||
}
|
||||
|
||||
EX pair<ld, ld> rep_ideal(ld e) {
|
||||
EX pair<ld, ld> rep_ideal(ld e, ld u IS(1)) {
|
||||
ld alpha = 2 * M_PI / e;
|
||||
hyperpoint h1 = point3(cos(alpha), -sin(alpha), 1);
|
||||
hyperpoint h2 = point3(1, 0, 1);
|
||||
hyperpoint h3 = point3(cos(alpha), sin(alpha), 1);
|
||||
hyperpoint h1 = point3(cos(alpha)*u, -sin(alpha)*u, 1);
|
||||
hyperpoint h2 = point3(u, 0, 1);
|
||||
hyperpoint h3 = point3(cos(alpha)*u, sin(alpha)*u, 1);
|
||||
hyperpoint h12 = mid(h1, h2);
|
||||
hyperpoint h23 = mid(h2, h3);
|
||||
ld len = hdist(h12, h23);
|
||||
|
@ -244,7 +244,7 @@ void geometry_information::bshape2(hpcshape& sh, PPR prio, int shapeid, matrixli
|
||||
|
||||
/* in case of apeirogonal shapes, we may need to cyclically rotate */
|
||||
bool apeirogonal = false;
|
||||
vector<hyperpoint> backup;
|
||||
vector<hyperpoint> tail, head;
|
||||
|
||||
for(int r=0; r<nsym; r+=osym/rots) {
|
||||
for(hyperpoint h: lst) {
|
||||
@ -260,17 +260,17 @@ void geometry_information::bshape2(hpcshape& sh, PPR prio, int shapeid, matrixli
|
||||
}
|
||||
if(mapped == 0) printf("warning: not mapped (shapeid %d)\n", shapeid);
|
||||
if(invalid) {
|
||||
apeirogonal = true;
|
||||
for(int i=last->s; i<isize(hpc); i++) backup.push_back(hpc[i]);
|
||||
hpc.resize(last->s);
|
||||
first = true;
|
||||
apeirogonal = true;
|
||||
for(auto h: head) tail.push_back(h);
|
||||
head.clear();
|
||||
}
|
||||
if(!invalid) hpcpush(mid(nh, nh));
|
||||
if(!invalid) head.push_back(nh);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto& b: backup) hpcpush(b);
|
||||
if(!apeirogonal) hpcpush(hpc[last->s]);
|
||||
for(auto& h: head) hpcpush(h);
|
||||
for(auto& h: tail) hpcpush(h);
|
||||
if(!apeirogonal) hpcpush(starting_point);
|
||||
}
|
||||
|
||||
template<class T> void sizeto(T& t, int n) {
|
||||
@ -353,29 +353,8 @@ namespace irr { void generate_floorshapes(); }
|
||||
void geometry_information::finish_apeirogon(hyperpoint center) {
|
||||
last->flags |= POLY_APEIROGONAL;
|
||||
last->she = isize(hpc);
|
||||
hyperpoint b = hpc.back();
|
||||
if(material(-1e-9 * C0 + center) > 0) {
|
||||
hpcpush(normalize(center));
|
||||
}
|
||||
else {
|
||||
for(int i=1; i<15; i++) hpcpush(towards_inf(b, center, i));
|
||||
hyperpoint h = 1e-9 * C0 + center;
|
||||
if(material(h) > 0)
|
||||
hpcpush(normalize(h));
|
||||
else {
|
||||
ld left = -atan2(towards_inf(b, center, 15));
|
||||
ld right = -atan2(towards_inf(hpc[last->s], center, 15));
|
||||
if(right > left + 180*degree) right -= 360*degree;
|
||||
if(right < left - 180*degree) right += 360*degree;
|
||||
hyperpoint l1 = towards_inf(b, center, 15); l1 /= l1[2];
|
||||
hyperpoint l2 = xspinpush0(left, 15); l2 /= l2[2];
|
||||
println(hlog, "doing that ", left, "..", right);
|
||||
/* call hpc.push_back directly to avoid adding points */
|
||||
for(int i=0; i<=10; i++) hpc.push_back(xspinpush0(lerp(left, right, i/10.), 15));
|
||||
}
|
||||
for(int i=15; i>=1; i--) hpcpush(towards_inf(hpc[last->s], center, i));
|
||||
}
|
||||
hpcpush(hpc[last->s]);
|
||||
hpcpush(center);
|
||||
hpcpush(starting_point);
|
||||
}
|
||||
|
||||
// !siid equals pseudohept(c)
|
||||
@ -648,11 +627,11 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
|
||||
if(i != isize(m.v)) printf("warning: i=%d sm=%d\n", i, isize(m.v));
|
||||
bshape2((ii?fsh.shadow:fsh.b)[id], fsh.prio, (fsh.shapeid2 && geosupport_football() < 2) ? fsh.shapeid2 : siid?fsh.shapeid0:fsh.shapeid1, m);
|
||||
|
||||
if(apeirogonal) {
|
||||
if(apeirogonal && !first) {
|
||||
int id = arb::id_of(c->master);
|
||||
auto &ac = arb::current_or_slided();
|
||||
auto& sh = ac.shapes[id];
|
||||
hpcpush(arb::get_adj(arb::current_or_slided(), id, cor-2, id, cor-1) * hpc[last->s]);
|
||||
hpcpush(arb::get_adj(arb::current_or_slided(), id, cor-2, id, cor-1) * starting_point);
|
||||
finish_apeirogon(sh.vertices.back());
|
||||
}
|
||||
}
|
||||
|
14
geometry.cpp
14
geometry.cpp
@ -380,8 +380,20 @@ hpcshape
|
||||
ld dlow_table[SIDEPARS], dhi_table[SIDEPARS], dfloor_table[SIDEPARS];
|
||||
|
||||
int prehpc;
|
||||
/** list of points in all shapes */
|
||||
vector<hyperpoint> hpc;
|
||||
/** what shape are we currently creating */
|
||||
hpcshape *last;
|
||||
/** is the current shape already started? first = not yet */
|
||||
bool first;
|
||||
/** starting point of the current shape, can be ultraideal */
|
||||
hyperpoint starting_point;
|
||||
/** first ideal point of the current shape */
|
||||
hyperpoint starting_ideal;
|
||||
/** last added point of the current shape, can be ultraideal */
|
||||
hyperpoint last_point;
|
||||
/** last ideal point of the current shape */
|
||||
hyperpoint last_ideal;
|
||||
|
||||
bool validsidepar[SIDEPARS];
|
||||
|
||||
@ -389,7 +401,6 @@ hpcshape
|
||||
#endif
|
||||
|
||||
hpcshape shFullCross[2];
|
||||
hpcshape *last;
|
||||
|
||||
int SD3, SD6, SD7, S12, S14, S21, S28, S42, S36, S84;
|
||||
|
||||
@ -422,6 +433,7 @@ hpcshape
|
||||
void prepare_usershapes();
|
||||
|
||||
void hpcpush(hyperpoint h);
|
||||
void hpc_connect_ideal(hyperpoint a, hyperpoint b);
|
||||
void hpcsquare(hyperpoint h1, hyperpoint h2, hyperpoint h3, hyperpoint h4);
|
||||
void chasmifyPoly(double fac, double fac2, int k);
|
||||
void shift(hpcshape& sh, double dx, double dy, double dz);
|
||||
|
@ -472,6 +472,40 @@ EX ld material(const hyperpoint& h) {
|
||||
else return h[LDIM];
|
||||
}
|
||||
|
||||
EX int safe_classify_ideals(hyperpoint h) {
|
||||
if(hyperbolic || in_h2xe()) {
|
||||
h /= h[LDIM];
|
||||
ld x = MDIM == 3 ? 1 - (h[0] * h[0] + h[1] * h[1]) : 1 - (h[0] * h[0] + h[1] * h[1] + h[2] * h[2]);
|
||||
if(x > 1e-6) return 1;
|
||||
if(x < -1e-6) return -1;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
EX ld ideal_limit = 10;
|
||||
EX ld ideal_each = degree;
|
||||
|
||||
EX hyperpoint safe_approximation_of_ideal(hyperpoint h) {
|
||||
return towards_inf(C0, h, ideal_limit);
|
||||
}
|
||||
|
||||
/** the point on the line ab which is closest to zero. Might not be normalized. Works even if a and b are (ultra)ideal */
|
||||
EX hyperpoint closest_to_zero(hyperpoint a, hyperpoint b) {
|
||||
if(sqhypot_d(MDIM, a-b) < 1e-9) return a;
|
||||
if(isnan(a[0])) return a;
|
||||
a /= a[LDIM];
|
||||
b /= b[LDIM];
|
||||
ld mul_a = 0, mul_b = 0;
|
||||
for(int i=0; i<LDIM; i++) {
|
||||
ld z = a[i] - b[i];
|
||||
mul_a += a[i] * z;
|
||||
mul_b -= b[i] * z;
|
||||
}
|
||||
|
||||
return (mul_b * a + mul_a * b) / (mul_a + mul_b);
|
||||
}
|
||||
|
||||
EX ld zlevel(const hyperpoint &h) {
|
||||
if(sl2) return sqrt(-intval(h, Hypc));
|
||||
else if(translatable) return h[LDIM];
|
||||
|
85
polygons.cpp
85
polygons.cpp
@ -15,21 +15,80 @@ static constexpr ld NEWSHAPE = (-13.5);
|
||||
#endif
|
||||
static constexpr ld WOLF = (-15.5);
|
||||
|
||||
void geometry_information::hpc_connect_ideal(hyperpoint a, hyperpoint b) {
|
||||
ld left = -atan2(a);
|
||||
ld right = -atan2(b);
|
||||
if(right > left + 180*degree) right -= 360*degree;
|
||||
if(right < left - 180*degree) right += 360*degree;
|
||||
/* call hpc.push_back directly to avoid adding points */
|
||||
ld qty = ceil(abs(right-left) / ideal_each);
|
||||
for(int i=0; i<=qty; i++) hpc.push_back(xspinpush0(lerp(left, right, i/qty), ideal_limit));
|
||||
}
|
||||
|
||||
void geometry_information::hpcpush(hyperpoint h) {
|
||||
if(sphere) h = mid(h,h);
|
||||
|
||||
if(GDIM == 3 || (last->flags & POLY_TRIANGLES)) {
|
||||
hpc.push_back(h);
|
||||
return;
|
||||
}
|
||||
|
||||
ld error_threshold = euclid ? 1000 : 1e10;
|
||||
ld threshold = (GDIM == 3 || last->flags & POLY_TRIANGLES) ? error_threshold : (sphere ? (ISMOBWEB || NONSTDVAR ? .04 : .001) : 0.1) * pow(.25, vid.linequality);
|
||||
if(/*vid.usingGL && */!first) {
|
||||
ld i = intval(hpc.back(), h);
|
||||
if(i > threshold && i < error_threshold) {
|
||||
hyperpoint md = mid(hpc.back(), h);
|
||||
hpcpush(md);
|
||||
hpcpush(h);
|
||||
return;
|
||||
ld threshold = (sphere ? (ISMOBWEB || NONSTDVAR ? .04 : .001) : 0.1) * pow(.25, vid.linequality);
|
||||
|
||||
if(first) {
|
||||
starting_ideal = starting_point = last_point = last_ideal = h;
|
||||
first = false;
|
||||
int c = safe_classify_ideals(h);
|
||||
if(c == 0) {
|
||||
starting_ideal = safe_approximation_of_ideal(h);
|
||||
hpc.push_back(starting_ideal);
|
||||
}
|
||||
else if(c > 0) {
|
||||
hpc.push_back(normalize(h));
|
||||
}
|
||||
}
|
||||
else {
|
||||
int c1 = safe_classify_ideals(last_point);
|
||||
int c2 = safe_classify_ideals(h);
|
||||
if(c1 > 0 && c2 > 0) {
|
||||
h = normalize(h);
|
||||
ld i = intval(last_point, h);
|
||||
if(i > threshold && i < error_threshold) {
|
||||
hyperpoint md = mid(hpc.back(), h);
|
||||
hpcpush(md);
|
||||
hpcpush(h);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
hpc.push_back(h);
|
||||
last_point = last_ideal = h;
|
||||
}
|
||||
}
|
||||
else if(c1 > 0 && c2 <= 0) {
|
||||
for(ld t = threshold; t < ideal_limit; t += threshold) hpc.push_back(last_ideal = towards_inf(last_point, h, t));
|
||||
last_point = h;
|
||||
}
|
||||
else if(c1 <= 0 && c2 > 0) {
|
||||
hyperpoint next_ideal = towards_inf(h, last_point, ideal_limit);
|
||||
hpc_connect_ideal(last_ideal, next_ideal);
|
||||
ld t = threshold; while(t < ideal_limit) t += threshold; t -= threshold;
|
||||
for(; t > threshold/2; t -= threshold) hpc.push_back(towards_inf(h, last_point, t));
|
||||
last_point = last_ideal = h;
|
||||
}
|
||||
else if(c1 <= 0 && c2 <= 0) {
|
||||
hyperpoint p = closest_to_zero(last_point, h);
|
||||
indenter ind(2);
|
||||
int cp = safe_classify_ideals(p);
|
||||
if(cp > 0) {
|
||||
hpcpush(normalize(p));
|
||||
hpcpush(h);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
last_ideal = last_point = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
hpc.push_back(h);
|
||||
}
|
||||
|
||||
void geometry_information::chasmifyPoly(double fac, double fac2, int k) {
|
||||
@ -119,6 +178,10 @@ hyperpoint geometry_information::turtlevertex(int u, double x, double y, double
|
||||
|
||||
void geometry_information::finishshape() {
|
||||
if(!last) return;
|
||||
|
||||
if(!first && safe_classify_ideals(starting_point) <= 0 && sqhypot_d(LDIM, starting_point - last_point) < 1e-9)
|
||||
hpc_connect_ideal(last_ideal, starting_ideal);
|
||||
|
||||
last->e = isize(hpc);
|
||||
double area = 0;
|
||||
for(int i=last->s; i<last->e-1; i++)
|
||||
|
8
util.cpp
8
util.cpp
@ -275,13 +275,17 @@ cld exp_parser::parse(int prio) {
|
||||
#endif
|
||||
else if(eat("ideal_angle(")) {
|
||||
ld edges = rparse(0);
|
||||
ld u = 1;
|
||||
skip_white(); if(eat(",")) u = rparse(0);
|
||||
force_eat(")");
|
||||
return arb::rep_ideal(edges).second;
|
||||
return arb::rep_ideal(edges, u).second;
|
||||
}
|
||||
else if(eat("ideal_edge(")) {
|
||||
ld edges = rparse(0);
|
||||
ld u = 1;
|
||||
skip_white(); if(eat(",")) u = rparse(0);
|
||||
force_eat(")");
|
||||
return arb::rep_ideal(edges).first;
|
||||
return arb::rep_ideal(edges, u).first;
|
||||
}
|
||||
else if(eat("regangle(")) {
|
||||
cld edgelen = parse(0);
|
||||
|
Loading…
Reference in New Issue
Block a user