From dd55779951ea19f5b5708401542494a32d90bcec Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sat, 18 Apr 2026 01:59:34 +0200 Subject: [PATCH] created a backed-map module for the common 'backed map' concept in arcm and arb --- backed-map.cpp | 181 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 backed-map.cpp diff --git a/backed-map.cpp b/backed-map.cpp new file mode 100644 index 00000000..26224b12 --- /dev/null +++ b/backed-map.cpp @@ -0,0 +1,181 @@ +// Hyperbolic Rogue -- Backed Maps +// Copyright (C) 2026- Zeno Rogue, see 'hyper.cpp' for details + +// utilities for maps which are "backed" by hyperbolic map + +#include "hyper.h" + +namespace hr { + +#if HDR +struct backed_map { + map > > what_at; + map> where; + hrmap *current_altmap; + + void initialize(heptagon *origin); + void assign(heptagon *actual, heptagon *backer, transmatrix T); + void rebase(heptagon*& backer, transmatrix& T, transmatrix& U); + void handle_precision_errors(heptagon *actual); + + geometry_information *alt_cgip[2]; + + geometry_information *find_alt_cgip(); + + void store(gamedata *gd); + void clear(); + void swapdim(); + }; +#endif + +/** @brief like adj, but in pure + * not used by arcm itself, but used in fake arcm + */ +geometry_information *backed_map::find_alt_cgip() { + auto& galt_cgip = alt_cgip[embedded_plane]; + if(galt_cgip) return galt_cgip; + check_cgi(); + cgi.require_basics(); + return galt_cgip = cgip; + } + +void backed_map::initialize(heptagon *origin) { + + heptagon *alt = nullptr; + + if(mhyperbolic) { + bool f = geom3::flipped; + if(f) geom3::light_flip(false); + dynamicval g(geometry, gNormal); + dynamicval gv(variation, eVariation::pure); + dynamicval gi(cgip, find_alt_cgip()); + alt = init_heptagon(S7); + alt->s = hsOrigin; + alt->alt = alt; + current_altmap = newAltMap(alt); + if(f) geom3::light_flip(true); + println(hlog, "original alt is ", alt); + } + + bool f = geom3::flipped; + if(f) geom3::light_flip(false); + transmatrix T = lxpush(.01241) * spin(1.4117) * lxpush(0.1241) * Id; + if(f) geom3::light_flip(true); + assign(origin, alt, T); + } + +void backed_map::assign(heptagon *actual, heptagon *backer, transmatrix T) { + where[actual] = make_pair(backer, T); + what_at[backer].emplace_back(actual, T); + } + +void backed_map::rebase(heptagon*& backer, transmatrix& T, transmatrix& U) { + if(mhyperbolic) { + dynamicval uc(cgip->use_count, cgip->use_count+1); + dynamicval g(geometry, gNormal); + dynamicval gv(variation, eVariation::pure); + dynamicval gi(cgip, find_alt_cgip()); + dynamicval cm(currentmap, current_altmap); + U = T; + current_altmap->virtualRebase(backer, T); + U = U * iso_inverse(T); + } + if(euclid) { + /* hash the rough coordinates as heptagon* alt */ + size_t s = size_t(T[0][LDIM]+.261) * 124101 + size_t(T[1][LDIM]+.261) * 82143; + backer = (heptagon*) s; + } + } + +bool in_hpe = false; + +void backed_map::handle_precision_errors(heptagon *h) { + if(!hyperbolic) return; + if(in_hpe) return; + in_hpe = true; + if(worst_precision_error > 1e-7) { + println(hlog, "worst_precision_error = ", worst_precision_error, ", fixing the local structure"); + worst_precision_error = 0; + set visited; + vector q; + auto enqueue = [&] (heptagon *h1) { + if(visited.count(h1)) return false; + visited.insert(h1); + q.push_back(h1); + return true; + }; + enqueue(h); + ld hpe_precision = 0; + int chances = 0, deleted = 0; + for(int i=0; i<250; i++) { + h = q[i]; + for(int d=0; dtype; d++) { + auto h2 = h->cmove(d); + bool first = enqueue(h2); + if(true) { + auto p1 = where[h]; + fixmatrix(p1.second); + heptspin hi(h, d); + // auto& t1 = current.get_triangle(hi); + // heptspin hs(h2, h->c.spin(d)); + // auto& t2 = current.get_triangle(hs); + transmatrix T = p1.second * currentmap->adj(h, d); + // spin(-t1.first) * lxpush(t1.second) * spin(M_PI + t2.first); + auto p2 = p1; + p2.second = T; + + transmatrix T0 = Id; + rebase(p2.first, p2.second, T0); + + if(first) { + if(where.count(h2)) { + auto old_p2 = where[h2]; + auto& old = what_at[old_p2.first]; + chances++; + for(auto& v: old) if(v.first == h2) { swap(v, old.back()); old.pop_back(); deleted++; break; } + } + where[h2] = p2; + what_at[p2.first].emplace_back(h2, p2.second); + } + else hpe_precision = max(hpe_precision, hdist(where[h2].second*C0, p2.second*C0)); + } + } + } + worst_precision_error = 0; println(hlog, "hpe_precision = ", hpe_precision, " deleted ", deleted, " / ", chances); + } + in_hpe = false; + } + +void backed_map::clear() { + what_at.clear(); + where.clear(); + if(current_altmap) { + dynamicval g(geometry, gNormal); + dynamicval gv(variation, eVariation::pure); + dynamicval gi(cgip, find_alt_cgip()); + delete current_altmap; + current_altmap = NULL; + } + } + +void backed_map::store(gamedata *gd) { + gd->store(what_at); gd->store(where); gd->store(current_altmap); + } + +void backed_map::swapdim() { + dynamicval g(geometry, gNormal); + dynamicval gv(variation, eVariation::pure); + + alt_cgip[0] = nullptr; + alt_cgip[1] = nullptr; + + dynamicval gi(cgip, find_alt_cgip()); + + for(auto& p: what_at) for(auto& pp: p.second) swapmatrix(pp.second); + for(auto& p: where) swapmatrix(p.second.second); + + alt_cgip[0] = nullptr; + alt_cgip[1] = nullptr; + } + +}