2019-03-02 23:43:31 +00:00
// Hyperbolic Rogue -- regular honeycombs
// Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
2019-08-10 11:43:24 +00:00
/** \file reg3.cpp
* \ brief regular honeycombs
*
* works with spherical and hyperbolic ones - - Euclidean cubic tiling implemented in euclid . cpp
* includes non - quotient spaces as well as field quotient and elliptic spaces
2019-12-14 11:05:01 +00:00
* hyperbolic honeycombs rely on bt : : to deal with floating point errors ( just like archimedean )
2019-08-10 11:43:24 +00:00
*/
2019-09-05 07:15:40 +00:00
# include "hyper.h"
2019-03-02 23:43:31 +00:00
namespace hr {
2019-08-17 21:30:27 +00:00
2021-07-12 10:23:34 +00:00
EX hyperpoint final_coords ( hyperpoint h ) {
if ( sn : : in ( ) | | ! bt : : in ( ) )
return ultra_normalize ( h ) ;
# if CAP_BT
2021-10-07 23:30:35 +00:00
if ( bt : : in ( ) & & ! prod )
2021-10-02 17:49:29 +00:00
return bt : : bt_to_minkowski ( h ) ;
2021-07-12 10:23:34 +00:00
# endif
return h ;
}
2021-07-12 09:07:22 +00:00
void subcellshape : : compute_common ( ) {
reg3 : : make_vertices_only ( vertices_only , faces ) ;
faces_local = faces ;
2021-07-12 10:23:34 +00:00
for ( auto & face : faces_local ) for ( auto & v : face ) v = from_cellcenter * final_coords ( v ) ;
2021-07-12 09:07:22 +00:00
vertices_only_local = vertices_only ;
2021-07-12 10:23:34 +00:00
for ( auto & v : vertices_only_local ) v = from_cellcenter * final_coords ( v ) ;
2021-07-12 09:07:22 +00:00
int N = isize ( faces ) ;
dirdist . resize ( N ) ;
for ( int i = 0 ; i < N ; i + + ) {
auto & da = dirdist [ i ] ;
da . resize ( N , false ) ;
set < unsigned > cface ;
for ( auto & v : faces [ i ] ) cface . insert ( bucketer ( v ) ) ;
for ( int j = 0 ; j < N ; j + + ) {
int mutual = 0 ;
for ( auto & w : faces [ j ] ) if ( cface . count ( bucketer ( w ) ) ) mutual + + ;
da [ j ] = i = = j ? 0 : mutual = = 2 ? 1 : INFD ;
}
}
floyd_warshall ( dirdist ) ;
next_dir . resize ( N ) ;
for ( int a = 0 ; a < N ; a + + ) next_dir [ a ] . resize ( N ) ;
for ( int a = 0 ; a < N ; a + + )
for ( int b = 0 ; b < N ; b + + )
if ( dirdist [ a ] [ b ] = = 1 )
for ( int c = 0 ; c < N ; c + + )
if ( dirdist [ a ] [ c ] = = 1 & & dirdist [ b ] [ c ] = = 1 ) {
transmatrix t = build_matrix ( tC0 ( cgi . adjmoves [ a ] ) , tC0 ( cgi . adjmoves [ b ] ) , tC0 ( cgi . adjmoves [ c ] ) , C0 ) ;
if ( det ( t ) > 0 ) next_dir [ a ] [ b ] = c ;
}
}
void subcellshape : : compute_hept ( ) {
cellcenter = C0 ;
to_cellcenter = Id ;
from_cellcenter = Id ;
compute_common ( ) ;
}
2022-05-10 06:53:58 +00:00
EX namespace reg3 {
EX void make_vertices_only ( vector < hyperpoint > & vo , const vector < vector < hyperpoint > > & csh ) {
vo . clear ( ) ;
for ( auto & v : csh )
for ( hyperpoint h : v ) {
bool found = false ;
for ( hyperpoint h2 : vo ) if ( hdist ( h , h2 ) < 1e-6 ) found = true ;
if ( ! found ) vo . push_back ( h ) ;
}
}
EX }
# if MAXMDIM >= 4
2021-07-12 09:07:22 +00:00
void subcellshape : : compute_sub ( ) {
hyperpoint gres = Hypc ;
for ( auto & face : faces ) {
hyperpoint res = Hypc ;
for ( auto & vertex : face )
res + = vertex ;
face_centers . push_back ( normalize ( res ) ) ;
gres + = res ;
}
cellcenter = normalize ( gres ) ;
to_cellcenter = rgpushxto0 ( cellcenter ) ;
from_cellcenter = gpushxto0 ( cellcenter ) ;
2021-07-12 09:34:51 +00:00
compute_common ( ) ;
2021-07-12 09:07:22 +00:00
}
2020-03-27 20:47:09 +00:00
/** \brief regular three-dimensional tessellations */
2019-08-09 20:37:11 +00:00
EX namespace reg3 {
2021-07-06 23:48:20 +00:00
EX int subcube_count = 1 ;
2021-07-08 22:07:35 +00:00
EX flagtype coxeter_param = 0 ;
const flagtype cox_othercell = 1 ;
const flagtype cox_midedges = 2 ;
const flagtype cox_vertices = 4 ;
2021-07-06 23:48:20 +00:00
2019-08-09 20:37:11 +00:00
# if HDR
inline short & altdist ( heptagon * h ) { return h - > emeraldval ; }
# endif
2019-03-02 23:43:31 +00:00
2020-07-04 22:45:25 +00:00
EX int extra_verification ;
2020-05-27 23:50:00 +00:00
EX bool ultra_mirror_on ;
EX bool ultra_mirror_in ( ) { return ( cgflags & qULTRA ) & & ultra_mirror_on ; }
2020-04-05 08:53:34 +00:00
EX bool in ( ) {
2020-05-15 09:46:26 +00:00
if ( fake : : in ( ) ) return FPIU ( in ( ) ) ;
2020-06-03 09:48:07 +00:00
return WDIM = = 3 & & ! euclid & & ! bt : : in ( ) & & ! nonisotropic & & ! hybri & & ! kite : : in ( ) ;
2020-04-05 08:53:34 +00:00
}
2020-01-06 19:53:09 +00:00
2020-05-27 23:50:00 +00:00
EX void compute_ultra ( ) {
cgi . ultra_mirror_part = .99 ;
cgi . ultra_material_part = .99 ;
2020-07-03 13:07:59 +00:00
cgi . ultra_mirrors . clear ( ) ;
2020-05-27 23:50:00 +00:00
if ( cgflags & qULTRA ) {
2020-07-03 13:07:59 +00:00
2021-07-12 09:07:22 +00:00
for ( auto & v : cgi . heptshape - > vertices_only ) {
2020-07-03 13:07:59 +00:00
hyperpoint nei ;
2021-07-12 09:07:22 +00:00
auto & faces = cgi . heptshape - > faces ;
2020-07-03 13:07:59 +00:00
2021-07-12 09:07:22 +00:00
for ( int i = 0 ; i < isize ( faces ) ; i + + )
for ( int j = 0 ; j < isize ( faces [ i ] ) ; j + + )
if ( sqhypot_d ( WDIM , faces [ i ] [ j ] - v ) < 1e-6 )
nei = faces [ i ] [ j ? j - 1 : j + 1 ] ;
2020-07-03 13:07:59 +00:00
transmatrix T = spintox ( v ) ;
hyperpoint a = T * v ;
hyperpoint b = T * nei ;
ld f0 = 0.5 ;
ld f1 = binsearch ( 0.5 , 1 , [ & ] ( ld d ) {
hyperpoint c = lerp ( b , a , d ) ;
if ( debugflags & DF_GEOM )
println ( hlog , " d= " , d , " c= " , c , " material = " , material ( c ) ) ;
return material ( c ) < = 0 ;
} ) ;
cgi . ultra_material_part = f1 ;
auto f = [ & ] ( ld d ) {
hyperpoint c = lerp ( b , a , d ) ;
c = normalize ( c ) ;
return c [ 1 ] * c [ 1 ] + c [ 2 ] * c [ 2 ] ;
} ;
for ( int it = 0 ; it < 100 ; it + + ) {
ld fa = ( f0 * 2 + f1 ) / 3 ;
ld fb = ( f0 * 1 + f1 * 2 ) / 3 ;
if ( debugflags & DF_GEOM )
println ( hlog , " f( " , fa , " ) = " , f ( fa ) , " f( " , fb , " ) = " , f ( fb ) ) ;
if ( f ( fa ) > f ( fb ) ) f0 = fa ;
else f1 = fb ;
}
cgi . ultra_mirror_part = f0 ;
hyperpoint c = lerp ( b , a , f0 ) ;
2020-05-27 23:50:00 +00:00
c = normalize ( c ) ;
2020-07-03 13:07:59 +00:00
c [ 1 ] = c [ 2 ] = 0 ;
c = normalize ( c ) ;
cgi . ultra_mirror_dist = hdist0 ( c ) ;
if ( cgi . ultra_mirror_part > = 1 - 1e-6 ) continue ;
cgi . ultra_mirrors . push_back ( rspintox ( v ) * xpush ( cgi . ultra_mirror_dist * 2 ) * MirrorX * spintox ( v ) ) ;
2020-05-27 23:50:00 +00:00
}
2020-07-03 13:07:59 +00:00
}
2020-05-27 23:50:00 +00:00
}
2019-08-09 20:37:11 +00:00
EX void generate ( ) {
2020-05-15 09:46:26 +00:00
if ( fake : : in ( ) ) {
fake : : generate ( ) ;
return ;
}
2019-03-02 23:43:31 +00:00
2021-07-12 10:23:34 +00:00
auto & hsh = get_hsh ( ) ;
2021-07-12 09:07:22 +00:00
2020-04-05 08:53:34 +00:00
int & loop = cgi . loop ;
int & face = cgi . face ;
auto & spins = cgi . spins ;
2021-07-12 10:23:34 +00:00
auto & cellshape = hsh . faces ;
2020-04-05 08:53:34 +00:00
auto & adjcheck = cgi . adjcheck ;
2020-05-26 22:54:15 +00:00
int & mid = cgi . schmid ;
mid = 3 ;
face = 3 ;
2019-03-02 23:43:31 +00:00
if ( S7 = = 6 ) face = 4 ;
2020-05-26 22:54:15 +00:00
if ( S7 = = 8 ) mid = 4 ;
2019-03-02 23:43:31 +00:00
if ( S7 = = 12 ) face = 5 ;
2020-05-26 22:54:15 +00:00
if ( S7 = = 20 ) mid = 5 ;
2019-03-02 23:43:31 +00:00
/* icosahedron not implemented */
loop = ginf [ geometry ] . tiling_name [ 5 ] - ' 0 ' ;
2020-05-26 22:54:15 +00:00
DEBB ( DF_GEOM , ( " face = " , face , " loop = " , loop , " S7 = " , S7 ) ) ;
2019-03-02 23:43:31 +00:00
2020-05-26 22:54:15 +00:00
ld angle_between_faces , hcrossf ;
2019-03-02 23:43:31 +00:00
2020-05-26 22:54:15 +00:00
/* frontal face direction */
hyperpoint h0 , h1 , h2 , h3 , h012 , h013 ;
if ( 1 ) {
dynamicval < eGeometry > dg ( geometry , gSphere ) ;
angle_between_faces = edge_of_triangle_with_angles ( 2 * M_PI / mid , M_PI / face , M_PI / face ) ;
h0 = xtangent ( 1 ) ;
h1 = cspin ( 0 , 1 , angle_between_faces ) * h0 ;
h2 = cspin ( 1 , 2 , 2 * M_PI / face ) * h1 ;
h3 = cspin ( 1 , 2 , - 2 * M_PI / face ) * h1 ;
hcrossf = edge_of_triangle_with_angles ( M_PI / 2 , M_PI / mid , M_PI / face ) ;
h012 = cspin ( 1 , 2 , M_PI / face ) * cspin ( 0 , 1 , hcrossf ) * h0 ;
h013 = cspin ( 1 , 2 , - M_PI / face ) * cspin ( 0 , 1 , hcrossf ) * h0 ;
2019-03-02 23:43:31 +00:00
}
2020-05-26 22:54:15 +00:00
for ( auto hx : { & h0 , & h1 , & h2 , & h3 , & h012 , & h013 } ) ( * hx ) [ 3 ] = 0 ;
2019-03-02 23:43:31 +00:00
2020-05-26 22:54:15 +00:00
ld klein_scale = binsearch ( 0 , 10 , [ & ] ( ld d ) {
dynamicval < eGeometry > g ( geometry , elliptic ? gCell120 : geometry ) ;
/* center of an edge */
hyperpoint u = C0 + ( h012 + h013 ) * d / 2 ;
2019-10-10 11:15:43 +00:00
2020-05-26 22:54:15 +00:00
if ( material ( u ) < = 0 ) {
println ( hlog , " klein_scale = " , d , " bad " ) ;
return true ;
}
2019-10-10 11:15:43 +00:00
2020-05-26 22:54:15 +00:00
u = normalize ( u ) ;
2019-10-10 11:15:43 +00:00
2020-05-26 22:54:15 +00:00
hyperpoint h = C0 * face ;
for ( int i = 0 ; i < face ; i + + ) h + = d * ( cspin ( 1 , 2 , M_PI * 2 * i / face ) * h012 ) ;
h = normalize ( h ) ;
hyperpoint h2 = rspintox ( h ) * xpush0 ( 2 * hdist0 ( h ) ) ;
h2 = spintox ( u ) * h2 ;
u = spintox ( u ) * u ;
h2 = gpushxto0 ( u ) * h2 ;
u = gpushxto0 ( u ) * u ;
ld x = hypot ( h2 [ 1 ] , h2 [ 2 ] ) ;
ld y = h2 [ 0 ] ;
2019-03-02 23:43:31 +00:00
2020-05-26 22:54:15 +00:00
ld loop2 = 360 / ( 90 + atan ( y / x ) / degree ) ;
println ( hlog , " d= " , d , " loop2= " , loop2 ) ;
if ( sphere ) return loop2 < loop ;
return loop2 > loop ;
} ) ;
2019-10-10 11:15:43 +00:00
2020-05-26 22:54:15 +00:00
/* precise ideal vertex */
if ( klein_scale > 1 - 1e-5 & & klein_scale < 1 + 1e-5 ) klein_scale = 1 ;
2019-10-10 11:15:43 +00:00
2020-05-26 22:54:15 +00:00
/* actual vertex */
hyperpoint v2 = C0 + klein_scale * h012 ;
hyperpoint midface = Hypc ;
for ( int i = 0 ; i < face ; i + + ) midface + = cspin ( 1 , 2 , 2 * i * M_PI / face ) * v2 ;
midface = normalize ( midface ) ;
ld between_centers = 2 * hdist0 ( midface ) ;
DEBB ( DF_GEOM , ( " between_centers = " , between_centers ) ) ;
2019-10-10 11:15:43 +00:00
2020-05-26 22:54:15 +00:00
if ( S7 = = 20 ) {
spins [ 0 ] = Id ;
spins [ 1 ] = cspin ( 0 , 1 , angle_between_faces ) * cspin ( 1 , 2 , M_PI ) ;
spins [ 2 ] = spins [ 1 ] * cspin ( 1 , 2 , - 2 * M_PI / face ) * spins [ 1 ] ;
spins [ 3 ] = spins [ 1 ] * cspin ( 1 , 2 , + 2 * M_PI / face ) * spins [ 1 ] ;
for ( int a = 4 ; a < 10 ; a + + ) spins [ a ] = cspin ( 1 , 2 , 2 * M_PI / face ) * spins [ a - 3 ] ;
for ( int a = S7 / 2 ; a < S7 ; a + + ) spins [ a ] = spins [ a - S7 / 2 ] * cspin ( 0 , 1 , M_PI ) ;
}
2019-03-02 23:43:31 +00:00
if ( S7 = = 12 | | S7 = = 8 ) {
spins [ 0 ] = Id ;
2019-10-10 11:15:43 +00:00
spins [ 1 ] = cspin ( 0 , 1 , angle_between_faces ) * cspin ( 1 , 2 , M_PI ) ;
2019-03-02 23:43:31 +00:00
for ( int a = 2 ; a < face + 1 ; a + + ) spins [ a ] = cspin ( 1 , 2 , 2 * M_PI * ( a - 1 ) / face ) * spins [ 1 ] ;
for ( int a = S7 / 2 ; a < S7 ; a + + ) spins [ a ] = cspin ( 0 , 1 , M_PI ) * spins [ a - S7 / 2 ] ;
2019-10-12 11:19:18 +00:00
if ( S7 = = 8 ) swap ( spins [ 6 ] , spins [ 7 ] ) ;
if ( S7 = = 12 ) swap ( spins [ 8 ] , spins [ 11 ] ) ;
if ( S7 = = 12 ) swap ( spins [ 9 ] , spins [ 10 ] ) ;
2019-03-02 23:43:31 +00:00
}
if ( S7 = = 6 ) {
spins [ 0 ] = Id ;
2019-10-10 11:15:43 +00:00
spins [ 1 ] = cspin ( 0 , 1 , angle_between_faces ) * cspin ( 1 , 2 , M_PI ) ;
2019-03-02 23:43:31 +00:00
spins [ 2 ] = cspin ( 1 , 2 , M_PI / 2 ) * spins [ 1 ] ;
for ( int a = S7 / 2 ; a < S7 ; a + + ) spins [ a ] = spins [ a - S7 / 2 ] * cspin ( 0 , 1 , M_PI ) ;
}
if ( S7 = = 4 ) {
spins [ 0 ] = Id ;
2019-10-10 11:15:43 +00:00
spins [ 1 ] = cspin ( 0 , 1 , angle_between_faces ) * cspin ( 1 , 2 , M_PI ) ;
2019-03-02 23:43:31 +00:00
for ( int a = 2 ; a < face + 1 ; a + + ) spins [ a ] = cspin ( 1 , 2 , 2 * M_PI * ( a - 1 ) / face ) * spins [ 1 ] ;
}
cellshape . clear ( ) ;
2021-03-25 10:12:58 +00:00
cellshape . resize ( S7 ) ;
for ( int a = 0 ; a < S7 ; a + + ) {
for ( int b = 0 ; b < face ; b + + )
cellshape [ a ] . push_back ( spins [ a ] * cspin ( 1 , 2 , 2 * M_PI * b / face ) * v2 ) ;
}
2019-03-02 23:43:31 +00:00
2020-04-05 08:53:34 +00:00
cgi . adjmoves [ 0 ] = cpush ( 0 , between_centers ) * cspin ( 0 , 2 , M_PI ) ;
for ( int i = 1 ; i < S7 ; i + + ) cgi . adjmoves [ i ] = spins [ i ] * cgi . adjmoves [ 0 ] ;
2019-03-02 23:43:31 +00:00
for ( int a = 0 ; a < S7 ; a + + )
2020-04-05 08:53:34 +00:00
DEBB ( DF_GEOM , ( " center of " , a , " is " , tC0 ( cgi . adjmoves [ a ] ) ) ) ;
2019-03-02 23:43:31 +00:00
2020-04-05 08:53:34 +00:00
DEBB ( DF_GEOM , ( " doublemove = " , tC0 ( cgi . adjmoves [ 0 ] * cgi . adjmoves [ 0 ] ) ) ) ;
2019-03-10 17:37:09 +00:00
2020-04-05 08:53:34 +00:00
adjcheck = hdist ( tC0 ( cgi . adjmoves [ 0 ] ) , tC0 ( cgi . adjmoves [ 1 ] ) ) * 1.0001 ;
2019-03-10 17:37:09 +00:00
2020-04-05 08:53:34 +00:00
if ( loop = = 4 ) cgi . strafedist = adjcheck ;
else cgi . strafedist = hdist ( cgi . adjmoves [ 0 ] * C0 , cgi . adjmoves [ 1 ] * C0 ) ;
2020-05-08 19:18:47 +00:00
2020-05-09 08:41:15 +00:00
if ( stretch : : applicable ( ) ) {
2020-05-08 19:18:47 +00:00
transmatrix T = cspin ( 0 , 2 , 90 * degree ) ;
transmatrix iT = inverse ( T ) ;
for ( auto & v : cgi . adjmoves ) v = T * v * iT ;
2021-03-25 10:12:58 +00:00
for ( auto & vv : cellshape ) for ( auto & v : vv ) v = T * v ;
2020-05-08 19:18:47 +00:00
}
2019-04-08 14:16:16 +00:00
2021-07-12 10:23:34 +00:00
hsh . compute_hept ( ) ;
2020-05-27 23:50:00 +00:00
compute_ultra ( ) ;
2021-07-06 23:48:20 +00:00
generate_subcells ( ) ;
}
2021-07-08 21:30:53 +00:00
EX void generate_plain_subcubes ( ) {
2021-07-09 08:10:44 +00:00
if ( S7 ! = 6 ) throw hr_exception ( " generate_plain_subcubes but no cubes " ) ;
2021-07-06 23:48:20 +00:00
auto & ssh = cgi . subshapes ;
2021-07-07 16:26:03 +00:00
const int sub = subcube_count ;
2021-07-12 09:07:22 +00:00
auto vx = abs ( cgi . heptshape - > faces [ 0 ] [ 0 ] [ 0 ] ) ;
auto vz = abs ( cgi . heptshape - > faces [ 0 ] [ 0 ] [ 3 ] ) ;
2021-07-08 21:30:53 +00:00
for ( int x = 1 - sub ; x < sub ; x + = 2 )
for ( int y = 1 - sub ; y < sub ; y + = 2 )
for ( int z = 1 - sub ; z < sub ; z + = 2 ) {
ssh . emplace_back ( ) ;
auto & ss = ssh . back ( ) ;
2021-07-12 09:07:22 +00:00
ss . faces = cgi . heptshape - > faces ;
2021-07-08 21:30:53 +00:00
for ( auto & face : ss . faces ) for ( auto & v : face ) {
v [ 0 ] + = vx * x ;
v [ 1 ] + = vx * y ;
v [ 2 ] + = vx * z ;
v [ 3 ] + = vz * ( sub - 1 ) ;
2021-07-06 23:48:20 +00:00
}
}
2021-07-08 21:30:53 +00:00
}
2021-07-08 22:07:35 +00:00
EX void generate_coxeter ( flagtype f ) {
auto & ssh = cgi . subshapes ;
2021-07-12 09:07:22 +00:00
for ( auto & fac : cgi . heptshape - > faces ) {
2021-07-08 22:07:35 +00:00
hyperpoint facectr = Hypc ;
vector < hyperpoint > ring ;
hyperpoint last = fac . back ( ) ;
ring . push_back ( last ) ;
for ( hyperpoint h : fac ) {
if ( f & cox_midedges )
ring . push_back ( mid ( last , h ) ) ;
ring . push_back ( last = h ) ;
facectr + = h ;
}
facectr = normalize ( facectr ) ;
hyperpoint fc2 = rspintox ( facectr ) * xpush0 ( 2 * hdist0 ( facectr ) ) ;
if ( f & cox_vertices ) {
for ( int i = 1 ; i < isize ( ring ) ; i + + ) {
ssh . emplace_back ( ) ;
auto & ss = ssh . back ( ) ;
auto h = ( f & cox_othercell ) ? facectr : fc2 ;
ss . faces . push_back ( { C0 , h , ring [ i - 1 ] } ) ;
ss . faces . push_back ( { C0 , h , ring [ i ] } ) ;
ss . faces . push_back ( { C0 , ring [ i - 1 ] , ring [ i ] } ) ;
ss . faces . push_back ( { h , ring [ i - 1 ] , ring [ i ] } ) ;
}
}
else if ( f & cox_midedges ) {
ring . push_back ( ring [ 1 ] ) ;
for ( int i = 3 ; i < isize ( ring ) ; i + = 2 ) {
ssh . emplace_back ( ) ;
auto & ss = ssh . back ( ) ;
auto h = ( f & cox_othercell ) ? facectr : fc2 ;
ss . faces . push_back ( { C0 , ring [ i - 2 ] , ring [ i - 1 ] } ) ;
ss . faces . push_back ( { C0 , ring [ i - 1 ] , ring [ i - 0 ] } ) ;
ss . faces . push_back ( { C0 , h , ring [ i - 2 ] } ) ;
ss . faces . push_back ( { C0 , h , ring [ i - 0 ] } ) ;
if ( f & cox_othercell ) {
ss . faces . push_back ( { facectr , ring [ i - 2 ] , ring [ i - 1 ] , ring [ i - 0 ] } ) ;
}
else {
ss . faces . push_back ( { fc2 , ring [ i - 1 ] , ring [ i - 0 ] } ) ;
ss . faces . push_back ( { fc2 , ring [ i - 2 ] , ring [ i - 1 ] } ) ;
}
}
}
else {
ssh . emplace_back ( ) ;
auto & ss = ssh . back ( ) ;
for ( int i = 1 ; i < isize ( ring ) ; i + + )
ss . faces . push_back ( { C0 , ring [ i - 1 ] , ring [ i ] } ) ;
if ( f & cox_othercell ) {
ring . pop_back ( ) ;
ss . faces . push_back ( ring ) ;
}
else {
for ( int i = 1 ; i < isize ( ring ) ; i + + )
ss . faces . push_back ( { fc2 , ring [ i - 1 ] , ring [ i ] } ) ;
}
}
}
}
2021-07-08 21:30:53 +00:00
EX void generate_special_subcubes ( bool bch ) {
2021-07-09 08:10:44 +00:00
if ( S7 ! = 6 ) throw hr_exception ( " generate_plain_subcubes but no cubes " ) ;
2021-07-08 21:30:53 +00:00
const int sub = subcube_count ;
if ( 1 ) {
2021-07-12 09:07:22 +00:00
auto vx = abs ( cgi . heptshape - > faces [ 0 ] [ 0 ] [ 0 ] ) ;
auto vz = abs ( cgi . heptshape - > faces [ 0 ] [ 0 ] [ 3 ] ) ;
2021-07-07 16:26:03 +00:00
auto step = hdist0 ( tC0 ( cgi . adjmoves [ 0 ] ) ) ;
array < int , 3 > co ;
int s = bch ? 1 : 2 ;
for ( co [ 0 ] = - sub ; co [ 0 ] < = sub ; co [ 0 ] + = s )
for ( co [ 1 ] = - sub ; co [ 1 ] < = sub ; co [ 1 ] + = s )
for ( co [ 2 ] = - sub ; co [ 2 ] < = sub ; co [ 2 ] + = s )
if ( ( ( co [ 0 ] ^ co [ 1 ] ^ 1 ) & 1 ) & & ( ( co [ 0 ] ^ co [ 2 ] ^ 1 ) & 1 ) ) {
hyperpoint ctr = Hypc ;
ctr [ 3 ] = vz * sub ;
2021-07-08 18:34:49 +00:00
struct direction {
hyperpoint dir ;
int limit ;
transmatrix mirror ;
void flip ( ) { dir = - dir ; limit = 200 - limit ; }
} ;
array < direction , 3 > di ;
2021-07-08 18:25:27 +00:00
int mi = 0 ;
2021-07-07 16:26:03 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
ctr [ i ] + = co [ i ] * vx ;
2021-07-08 18:34:49 +00:00
auto & dii = di [ i ] ;
if ( co [ i ] > = 0 ) {
dii . dir = ctangent ( i , vx ) ;
dii . limit = sub - co [ i ] ;
dii . mirror = cpush ( i , + step / 2 ) * cmirror ( i ) * cpush ( i , - step / 2 ) ;
2021-07-07 16:26:03 +00:00
}
2021-07-08 18:34:49 +00:00
else {
dii . dir = ctangent ( i , - vx ) ;
dii . limit = co [ i ] + sub ;
dii . mirror = cpush ( i , - step / 2 ) * cmirror ( i ) * cpush ( i , + step / 2 ) ;
2021-07-07 16:26:03 +00:00
}
2021-07-08 18:34:49 +00:00
if ( dii . limit = = 0 ) mi + + ;
2021-07-07 16:26:03 +00:00
}
2021-07-08 18:34:49 +00:00
sort ( di . begin ( ) , di . end ( ) , [ ] ( direction & d1 , direction & d2 ) { return d1 . limit > d2 . limit ; } ) ;
2021-07-07 16:26:03 +00:00
cgi . subshapes . emplace_back ( ) ;
auto & ss = cgi . subshapes . back ( ) ;
2021-07-08 18:25:27 +00:00
2021-07-08 19:38:11 +00:00
auto pt0 = [ & ] ( const array < ld , 3 > & x ) {
2021-07-08 18:25:27 +00:00
transmatrix M = Id ;
2021-07-08 19:38:11 +00:00
hyperpoint res = ctr ;
for ( int i = 0 ; i < 3 ; i + + ) {
ld xx = x [ i ] ;
if ( xx > di [ i ] . limit ) xx = 2 * di [ i ] . limit - xx , M = di [ i ] . mirror * M ;
res + = di [ i ] . dir * xx ;
}
return normalize ( M * res ) ;
} ;
auto pt = [ & ] ( ld x , ld y , ld z ) {
if ( sub = = 1 | | ! bch | | sphere ) return pt0 ( make_array ( x , y , z ) ) ;
// Unfortunately using the rule above for bch (with sub > 1) generates faces which are not flat.
// Therefore, we replace the vertices by the centers of their Voronoi cells
// we do this only in the hyperbolic case -- it does not work correctly in the spherical case because of Voronoi not working as expected
// the arguments for pt1 are the Voronoi centers for: (x,y,z) = (1,.5,0)
// pt1 rearranges them to whatever (x,y,z) actually is
array < ld , 3 > arg1 = { x , y , z } ;
auto pt1 = [ & ] ( ld x1 , ld y1 , ld z1 ) {
array < ld , 3 > arg0 ;
for ( int i = 0 ; i < 3 ; i + + ) {
if ( arg1 [ i ] = = 1 ) arg0 [ i ] = x1 ;
else if ( arg1 [ i ] = = - 1 ) arg0 [ i ] = - x1 ;
else if ( arg1 [ i ] = = .5 ) arg0 [ i ] = y1 ;
else if ( arg1 [ i ] = = - .5 ) arg0 [ i ] = - y1 ;
else if ( arg1 [ i ] = = 0 ) arg0 [ i ] = z1 ;
else throw hr_exception ( " unknown number in pt1 " ) ;
}
return normalize ( pt0 ( arg0 ) ) ;
} ;
hyperpoint a = pt1 ( 0 , 0 , 0 ) ;
hyperpoint b = pt1 ( 2 , 0 , 0 ) ;
hyperpoint c = pt1 ( 1 , 1 , 1 ) ;
hyperpoint d = pt1 ( 1 , 1 , - 1 ) ;
hyperpoint res = circumscribe ( a , b , c , d ) ;
return res ;
2021-07-07 16:26:03 +00:00
} ;
auto add_face = [ & ] ( std : : initializer_list < hyperpoint > vh ) {
ss . faces . push_back ( vh ) ;
} ;
const ld h = .5 ;
if ( mi = = 0 ) {
for ( int s : { - 1 , 1 } ) {
for ( int i = 0 ; i < 3 ; i + + ) {
if ( bch )
add_face ( { pt ( 0 , .5 , s ) , pt ( .5 , 0 , s ) , pt ( 0 , - .5 , s ) , pt ( - .5 , 0 , s ) } ) ;
else
add_face ( { pt ( - 1 , - 1 , s ) , pt ( - 1 , + 1 , s ) , pt ( + 1 , + 1 , s ) , pt ( + 1 , - 1 , s ) } ) ;
2021-07-08 18:34:49 +00:00
tie ( di [ 0 ] , di [ 1 ] , di [ 2 ] ) = make_tuple ( di [ 1 ] , di [ 2 ] , di [ 0 ] ) ;
2021-07-07 16:26:03 +00:00
}
}
if ( bch ) for ( int u = 0 ; u < 8 ; u + + ) {
2021-07-08 18:34:49 +00:00
for ( int j = 0 ; j < 3 ; j + + ) if ( ( u > > j ) & 1 ) di [ j ] . flip ( ) ;
2021-07-07 16:26:03 +00:00
add_face ( { pt ( 0 , .5 , 1 ) , pt ( 0 , 1 , .5 ) , pt ( .5 , 1 , 0 ) , pt ( 1 , .5 , 0 ) , pt ( 1 , 0 , .5 ) , pt ( .5 , 0 , 1 ) } ) ;
2021-07-08 18:34:49 +00:00
for ( int j = 0 ; j < 3 ; j + + ) if ( ( u > > j ) & 1 ) di [ j ] . flip ( ) ;
2021-07-07 16:26:03 +00:00
}
}
else if ( mi = = 1 ) {
2021-07-08 18:34:49 +00:00
auto & M = di [ 2 ] . mirror ;
2021-07-07 16:26:03 +00:00
for ( int s : { - 1 , 1 } ) {
if ( bch )
2021-07-08 18:25:27 +00:00
add_face ( { pt ( 0 , h , s ) , pt ( h , 0 , s ) , pt ( 0 , - h , s ) , pt ( - h , 0 , s ) } ) ;
2021-07-07 16:26:03 +00:00
else
2021-07-08 18:25:27 +00:00
add_face ( { pt ( - 1 , - 1 , s ) , pt ( - 1 , + 1 , s ) , pt ( + 1 , + 1 , s ) , pt ( + 1 , - 1 , s ) } ) ;
2021-07-07 16:26:03 +00:00
for ( int i = 0 ; i < 2 ; i + + ) {
if ( bch )
2021-07-08 18:25:27 +00:00
add_face ( { pt ( 1 , 0 , - .5 ) , pt ( 1 , - .5 , 0 ) , M * pt ( 1 , 0 , - .5 ) , pt ( 1 , .5 , 0 ) } ) ;
2021-07-07 16:26:03 +00:00
else
2021-07-08 18:25:27 +00:00
add_face ( { pt ( - 1 , - 1 , - 1 ) , pt ( - 1 , + 1 , - 1 ) , pt ( - 1 , + 1 , + 1 ) , pt ( - 1 , - 1 , + 1 ) } ) ;
2021-07-08 18:34:49 +00:00
tie ( di [ 0 ] , di [ 1 ] ) = make_tuple ( di [ 1 ] , di [ 0 ] ) ; di [ 0 ] . flip ( ) ;
2021-07-07 16:26:03 +00:00
}
}
2021-07-08 18:25:27 +00:00
if ( bch ) for ( ld s : { - 1 , 1 } ) for ( int i = 0 ; i < 4 ; i + + ) {
add_face ( { pt ( 0 , .5 , s ) , pt ( 0 , 1 , s / 2 ) , pt ( .5 , 1 , 0 ) , pt ( 1 , .5 , 0 ) , pt ( 1 , 0 , s / 2 ) , pt ( .5 , 0 , s ) } ) ;
2021-07-08 18:34:49 +00:00
tie ( di [ 0 ] , di [ 1 ] ) = make_tuple ( di [ 1 ] , di [ 0 ] ) ; di [ 0 ] . flip ( ) ;
2021-07-07 16:26:03 +00:00
}
}
else {
2021-07-08 18:34:49 +00:00
transmatrix spi = mi = = 2 ? di [ 1 ] . mirror * di [ 2 ] . mirror : di [ 0 ] . mirror * di [ 1 ] . mirror ;
2021-07-07 16:26:03 +00:00
if ( cgi . loop = = 5 ) spi = spi * spi ;
vector < transmatrix > spi_power = { Id } ;
for ( int i = 1 ; i < cgi . loop ; i + + ) spi_power . push_back ( spi_power . back ( ) * spi ) ;
if ( mi = = 2 ) {
for ( auto P : spi_power ) {
if ( bch )
2021-07-08 18:34:49 +00:00
add_face ( { P * pt ( .5 , 0 , - 1 ) , P * pt ( 0 , - .5 , - 1 ) , P * pt ( - .5 , 0 , - 1 ) , P * pt ( 0 , .5 , - 1 ) } ) ;
2021-07-07 16:26:03 +00:00
else
add_face ( { P * pt ( - 1 , - 1 , - 1 ) , P * pt ( 1 , - 1 , - 1 ) , P * spi * pt ( 1 , - 1 , - 1 ) , P * spi * pt ( - 1 , - 1 , - 1 ) } ) ;
}
vector < hyperpoint > f0 , f1 ;
for ( auto P : spi_power ) f0 . push_back ( bch ? P * pt ( - 1 , - .5 , 0 ) : P * pt ( - 1 , - 1 , - 1 ) ) ;
for ( auto P : spi_power ) f1 . push_back ( bch ? P * pt ( + 1 , - .5 , 0 ) : P * pt ( + 1 , - 1 , - 1 ) ) ;
ss . faces . push_back ( f0 ) ;
ss . faces . push_back ( f1 ) ;
if ( bch ) for ( auto P : spi_power ) for ( int s : { - 1 , 1 } )
add_face ( { P * pt ( - .5 * s , 0 , - 1 ) , P * pt ( 0 , - .5 , - 1 ) , P * pt ( 0 , - 1 , - .5 ) , P * pt ( - .5 * s , - 1 , 0 ) , P * pt ( - 1 * s , - .5 , 0 ) , P * pt ( - 1 * s , 0 , - .5 ) } ) ;
}
else {
vector < transmatrix > face_dirs = { Id } ;
for ( int i = 0 ; i < isize ( face_dirs ) ; i + + )
for ( int j = 0 ; j < 2 ; j + + )
for ( auto P1 : spi_power ) {
auto T = face_dirs [ i ] ;
2021-07-08 18:34:49 +00:00
if ( j = = 0 ) T = T * P1 * di [ 1 ] . mirror * di [ 2 ] . mirror ;
if ( j = = 1 ) T = T * P1 * di [ 2 ] . mirror * di [ 0 ] . mirror ;
2021-07-07 16:26:03 +00:00
bool fnd = false ;
for ( auto & F : face_dirs )
for ( auto P : spi_power )
if ( eqmatrix ( T , F * P ) ) fnd = true ;
if ( ! fnd ) face_dirs . push_back ( T ) ;
}
// tetrahedron in {4,3,3}; dodecahedron in {4,3,5}
if ( cgi . loop = = 3 ) hassert ( isize ( face_dirs ) = = 4 ) ;
if ( cgi . loop = = 5 ) hassert ( isize ( face_dirs ) = = 12 ) ;
for ( auto F : face_dirs ) {
vector < hyperpoint > f0 ;
for ( auto P : spi_power ) f0 . push_back ( bch ? F * P * pt ( - .5 , 0 , - 1 ) : F * P * pt ( - 1 , - 1 , - 1 ) ) ;
ss . faces . push_back ( f0 ) ;
}
vector < transmatrix > vertex_dirs ;
2021-07-08 19:38:11 +00:00
hyperpoint pter = normalize ( pt0 ( make_array ( - .5 , - .5 , - .5 ) ) ) ;
2021-07-07 16:26:03 +00:00
for ( auto & F : face_dirs ) for ( auto & P : spi_power ) {
transmatrix T = F * P ;
bool fnd = false ;
for ( auto T1 : vertex_dirs ) if ( hdist ( T * pter , T1 * pter ) < 1e-3 ) fnd = true ;
if ( ! fnd ) vertex_dirs . push_back ( T ) ;
}
if ( cgi . loop = = 3 ) hassert ( isize ( vertex_dirs ) = = 4 ) ;
if ( cgi . loop = = 5 ) hassert ( isize ( vertex_dirs ) = = 20 ) ;
if ( bch ) for ( auto & V : vertex_dirs )
add_face ( { V * pt ( - 1 , - .5 , 0 ) , V * pt ( - 1 , 0 , - .5 ) , V * pt ( - .5 , 0 , - 1 ) , V * pt ( 0 , - .5 , - 1 ) , V * pt ( 0 , - 1 , - .5 ) , V * pt ( - .5 , - 1 , 0 ) } ) ;
}
}
}
}
2021-07-08 21:30:53 +00:00
}
2021-07-13 13:12:03 +00:00
EX void generate_bch_oct ( ) {
if ( S7 ! = 6 ) throw hr_exception ( " generate_bch_oct but no cubes " ) ;
const int sub = subcube_count ;
if ( 1 ) {
auto vx = abs ( cgi . heptshape - > faces [ 0 ] [ 0 ] [ 0 ] ) ;
auto vz = abs ( cgi . heptshape - > faces [ 0 ] [ 0 ] [ 3 ] ) ;
array < int , 3 > co ;
// vx = 1; vz = 0;
for ( co [ 0 ] = - sub ; co [ 0 ] < sub ; co [ 0 ] + + )
for ( co [ 1 ] = - sub ; co [ 1 ] < sub ; co [ 1 ] + + )
for ( co [ 2 ] = - sub ; co [ 2 ] < sub ; co [ 2 ] + + ) {
auto co1 = co ;
array < ld , 3 > sgn = { 1 , 1 , 1 } ;
if ( ( co [ 1 ] ^ co [ 0 ] ) & 1 ) co1 [ 1 ] + + , sgn [ 1 ] = - 1 ;
if ( ( co [ 2 ] ^ co [ 0 ] ) & 1 ) co1 [ 2 ] + + , sgn [ 2 ] = - 1 ;
hyperpoint ctr = Hypc ;
ctr [ 3 ] = vz * sub ;
auto pt = [ & ] ( int m , ld x0 , ld x1 , ld x2 ) {
hyperpoint res = ctr ;
auto x = make_array ( x0 , x1 , x2 ) ;
for ( int i = 0 ; i < 3 ; i + + )
res [ i ] = vx * ( co1 [ i ] + x [ ( m + i ) % 3 ] * sgn [ i ] ) ;
return res ;
} ;
for ( int it = 0 ; it < 2 ; it + + ) {
cgi . subshapes . emplace_back ( ) ;
auto & ss = cgi . subshapes . back ( ) ;
for ( int m = 0 ; m < 3 ; m + + ) {
ss . faces . push_back ( { pt ( m , 0 , 0 , 0 ) , pt ( m , 1 , 0 , 0 ) , pt ( m , 1 , 0 , .5 ) , pt ( m , .5 , 0 , 1 ) , pt ( m , 0 , 0 , 1 ) } ) ;
ss . faces . push_back ( { pt ( m , 1 , 0 , 0 ) , pt ( m , 1 , 0 , .5 ) , pt ( m , 1 , .5 , 0 ) } ) ;
}
ss . faces . push_back ( { pt ( 0 , 1 , 0 , .5 ) , pt ( 0 , 1 , .5 , 0 ) , pt ( 0 , .5 , 1 , 0 ) , pt ( 0 , 0 , 1 , .5 ) , pt ( 0 , 0 , .5 , 1 ) , pt ( 0 , .5 , 0 , 1 ) } ) ;
for ( int d = 0 ; d < 3 ; d + + )
co1 [ d ] + = sgn [ d ] , sgn [ d ] * = - 1 ;
println ( hlog , ss . faces ) ;
}
}
}
}
2021-07-08 21:30:53 +00:00
EX void generate_subcells ( ) {
switch ( variation ) {
case eVariation : : subcubes :
generate_plain_subcubes ( ) ;
break ;
case eVariation : : dual_subcubes :
generate_special_subcubes ( false ) ;
break ;
case eVariation : : bch :
generate_special_subcubes ( true ) ;
break ;
2021-07-13 13:12:03 +00:00
case eVariation : : bch_oct :
generate_bch_oct ( ) ;
break ;
2021-07-08 22:07:35 +00:00
case eVariation : : coxeter :
generate_coxeter ( coxeter_param ) ;
break ;
2021-07-08 21:30:53 +00:00
case eVariation : : pure : {
cgi . subshapes . emplace_back ( ) ;
2021-07-12 09:07:22 +00:00
cgi . subshapes [ 0 ] . faces = cgi . heptshape - > faces ;
2021-07-08 21:30:53 +00:00
break ;
}
default :
throw hr_exception ( " unknown variation in generate_subcells " ) ;
2021-07-06 23:48:20 +00:00
}
2021-07-08 21:30:53 +00:00
2021-07-12 09:07:22 +00:00
for ( auto & ss : cgi . subshapes ) ss . compute_sub ( ) ;
2021-07-08 21:30:53 +00:00
println ( hlog , " subcells generated = " , isize ( cgi . subshapes ) ) ;
2019-03-02 23:43:31 +00:00
}
void binary_rebase ( heptagon * h , const transmatrix & V ) {
}
void test ( ) ;
2019-10-12 11:19:58 +00:00
2020-01-06 19:53:09 +00:00
# if HDR
2021-07-07 16:26:03 +00:00
/** \brief vertex_adjacencies[heptagon id] is a list of other heptagons which are vertex adjacent
* note : in case of ideal vertices this is just the face adjacency
* */
struct vertex_adjacency_info {
/** id of the adjacent heptagon */
int h_id ;
/** transition matrix to that heptagon */
transmatrix T ;
2021-07-11 21:22:00 +00:00
/** the sequence of moves we need to make to get there */
2021-07-07 16:26:03 +00:00
vector < int > move_sequence ;
} ;
2021-07-06 23:48:20 +00:00
struct hrmap_closed3 : hrmap {
2019-03-15 12:46:23 +00:00
vector < heptagon * > allh ;
2021-07-11 09:03:35 +00:00
vector < vector < vector < int > > > strafe_data ;
2019-10-12 11:19:58 +00:00
vector < vector < transmatrix > > tmatrices ;
2021-07-06 23:48:20 +00:00
vector < vector < transmatrix > > tmatrices_cell ;
2020-01-06 20:23:17 +00:00
vector < cell * > acells ;
2021-07-09 08:26:26 +00:00
map < cell * , pair < int , int > > local_id ; /* acells index, subshape index */
2021-07-06 23:48:20 +00:00
vector < vector < cell * > > acells_by_master ;
2021-07-07 16:26:03 +00:00
vector < vector < vertex_adjacency_info > > vertex_adjacencies ;
2021-07-09 08:26:26 +00:00
vector < vector < vector < int > > > move_sequences ;
2019-11-14 15:51:50 +00:00
2020-01-06 21:18:10 +00:00
transmatrix adj ( heptagon * h , int d ) override { return tmatrices [ h - > fieldval ] [ d ] ; }
2021-07-09 14:07:26 +00:00
transmatrix adj ( cell * c , int d ) override { return tmatrices_cell [ local_id . at ( c ) . first ] [ d ] ; }
2020-01-06 19:53:09 +00:00
heptagon * getOrigin ( ) override { return allh [ 0 ] ; }
2021-07-12 13:20:04 +00:00
transmatrix relative_matrixc ( cell * h2 , cell * h1 , const hyperpoint & hint ) override ;
2020-01-06 20:23:17 +00:00
void initialize ( int cell_count ) ;
vector < cell * > & allcells ( ) override { return acells ; }
2020-01-15 16:58:41 +00:00
2021-07-12 09:07:22 +00:00
subcellshape & get_cellshape ( cell * c ) override {
if ( PURE ) return * cgi . heptshape ;
2021-07-09 14:07:26 +00:00
int id = local_id . at ( c ) . second ;
2021-07-12 09:07:22 +00:00
return cgi . subshapes [ id ] ;
2021-07-06 23:48:20 +00:00
}
2021-07-09 08:10:13 +00:00
2021-07-11 21:22:00 +00:00
transmatrix master_relative ( cell * c , bool get_inverse ) override {
2021-07-09 14:07:26 +00:00
int id = local_id . at ( c ) . second ;
2021-07-09 08:10:13 +00:00
auto & ss = cgi . subshapes [ id ] ;
return get_inverse ? ss . from_cellcenter : ss . to_cellcenter ;
}
2021-07-06 23:48:20 +00:00
void make_subconnections ( ) ;
2021-07-09 08:09:31 +00:00
int wall_offset ( cell * c ) override ;
2021-07-11 21:22:00 +00:00
int shvid ( cell * c ) override { return local_id . at ( c ) . second ; }
2021-07-09 17:33:01 +00:00
2021-07-11 21:22:00 +00:00
transmatrix ray_iadj ( cell * c , int i ) override ;
2021-07-11 09:48:33 +00:00
cellwalker strafe ( cellwalker cw , int j ) override {
int id = local_id . at ( cw . at ) . first ;
return cellwalker ( cw . at - > cmove ( j ) , strafe_data [ id ] [ j ] [ cw . spin ] ) ;
}
2021-07-13 00:34:24 +00:00
const vector < int > & get_move_seq ( cell * c , int i ) override {
int id = local_id . at ( c ) . first ;
return move_sequences [ id ] [ i ] ;
}
2019-10-12 11:19:58 +00:00
} ;
2021-07-06 23:48:20 +00:00
struct hrmap_quotient3 : hrmap_closed3 { } ;
2020-01-06 19:53:09 +00:00
# endif
2021-07-09 17:33:01 +00:00
transmatrix hrmap_closed3 : : ray_iadj ( cell * c , int i ) {
if ( PURE ) return iadj ( c , i ) ;
auto & v = get_face_vertices ( c , i ) ;
hyperpoint h =
project_on_triangle ( v [ 0 ] , v [ 1 ] , v [ 2 ] ) ;
transmatrix T = rspintox ( h ) ;
return T * xpush ( - 2 * hdist0 ( h ) ) * spintox ( h ) ;
}
2020-01-06 19:53:09 +00:00
2021-07-09 08:09:31 +00:00
int hrmap_closed3 : : wall_offset ( cell * c ) {
2021-07-09 08:26:26 +00:00
if ( PURE ) return 0 ;
2021-07-09 17:33:01 +00:00
auto & wo = cgi . walloffsets [ local_id . at ( c ) . second ] ;
2021-07-06 23:48:20 +00:00
if ( wo . second = = nullptr )
wo . second = c ;
return wo . first ;
}
2021-07-07 21:32:22 +00:00
EX const vector < hyperpoint > & get_face_vertices ( cell * c , int d ) {
2021-07-09 08:09:31 +00:00
return cgi . subshapes [ currentmap - > shvid ( c ) ] . faces_local [ d ] ;
2021-07-07 21:32:22 +00:00
}
EX int get_face_vertex_count ( cell * c , int d ) {
return isize ( get_face_vertices ( c , d ) ) ;
2021-07-06 23:48:20 +00:00
}
void hrmap_closed3 : : initialize ( int big_cell_count ) {
allh . resize ( big_cell_count ) ;
tmatrices . resize ( big_cell_count ) ;
2020-01-06 20:23:17 +00:00
acells . clear ( ) ;
2021-07-06 23:48:20 +00:00
for ( int a = 0 ; a < big_cell_count ; a + + ) {
2021-07-04 08:36:16 +00:00
allh [ a ] = init_heptagon ( S7 ) ;
2020-01-06 20:23:17 +00:00
allh [ a ] - > fieldval = a ;
}
2021-07-06 23:48:20 +00:00
}
2021-07-08 20:04:14 +00:00
const static bool testing_subconnections = false ;
2021-07-06 23:48:20 +00:00
void hrmap_closed3 : : make_subconnections ( ) {
auto & ss = cgi . subshapes ;
2021-07-07 16:26:03 +00:00
auto & vas = vertex_adjacencies ;
vas . resize ( isize ( allh ) ) ;
for ( int a = 0 ; a < isize ( allh ) ; a + + ) {
auto & va = vas [ a ] ;
va . emplace_back ( vertex_adjacency_info { a , Id , { } } ) ;
2021-07-09 12:03:32 +00:00
set < unsigned > buckets ;
2021-07-12 09:07:22 +00:00
for ( auto & v : cgi . heptshape - > vertices_only ) buckets . insert ( bucketer ( v ) ) ;
2021-07-09 12:03:32 +00:00
2021-07-07 16:26:03 +00:00
if ( cgflags & qIDEAL ) {
for ( int d = 0 ; d < S7 ; d + + ) {
transmatrix T = adj ( allh [ a ] , d ) ;
va . emplace_back ( vertex_adjacency_info { allh [ a ] - > move ( d ) - > fieldval , T , { d } } ) ;
}
}
else
for ( int i = 0 ; i < isize ( va ) ; i + + ) {
for ( int d = 0 ; d < S7 ; d + + ) {
transmatrix T = va [ i ] . T * adj ( allh [ va [ i ] . h_id ] , d ) ;
bool found = false ;
for ( auto & va2 : va ) if ( eqmatrix ( va2 . T , T ) ) found = true ;
if ( found ) continue ;
bool found_va = false ;
2021-07-12 09:07:22 +00:00
for ( auto & w : cgi . heptshape - > vertices_only )
2021-07-09 12:03:32 +00:00
if ( buckets . count ( bucketer ( T * w ) ) )
2021-07-07 16:26:03 +00:00
found_va = true ;
if ( ! found_va ) continue ;
va . emplace_back ( vertex_adjacency_info { allh [ va [ i ] . h_id ] - > move ( d ) - > fieldval , T , va [ i ] . move_sequence } ) ;
va . back ( ) . move_sequence . push_back ( d ) ;
}
}
}
map < int , int > by_sides ;
2021-07-08 20:03:31 +00:00
vector < map < unsigned , vector < hyperpoint > > > which_cell_0 ;
which_cell_0 . resize ( isize ( allh ) ) ;
2021-07-07 16:26:03 +00:00
acells_by_master . resize ( isize ( allh ) ) ;
for ( int a = 0 ; a < isize ( allh ) ; a + + ) {
for ( int id = 0 ; id < isize ( ss ) ; id + + ) {
bool exists = false ;
2021-07-08 20:03:31 +00:00
auto & cc = ss [ id ] . cellcenter ;
2021-07-07 16:26:03 +00:00
for ( auto & va : vertex_adjacencies [ a ] ) {
2021-07-08 20:03:31 +00:00
hyperpoint h = iso_inverse ( va . T ) * cc ;
for ( auto h1 : which_cell_0 [ va . h_id ] [ bucketer ( h ) ] )
if ( hdist ( h1 , h ) < 1e-6 )
2021-07-07 16:26:03 +00:00
exists = true ;
}
if ( exists ) continue ;
cell * c = newCell ( isize ( ss [ id ] . faces ) , allh [ a ] ) ;
by_sides [ isize ( ss [ id ] . faces ) ] + + ;
if ( ! allh [ a ] - > c7 )
allh [ a ] - > c7 = c ;
local_id [ c ] = { isize ( acells ) , id } ;
acells . push_back ( c ) ;
acells_by_master [ a ] . push_back ( c ) ;
2021-07-08 20:03:31 +00:00
which_cell_0 [ a ] [ bucketer ( cc ) ] . push_back ( cc ) ;
2021-07-07 16:26:03 +00:00
}
}
println ( hlog , " found " , isize ( acells ) , " cells, " , by_sides ) ;
2021-07-06 23:48:20 +00:00
tmatrices_cell . resize ( isize ( acells ) ) ;
2021-07-09 08:26:26 +00:00
move_sequences . resize ( isize ( acells ) ) ;
2021-07-06 23:48:20 +00:00
int failures = 0 ;
2021-07-08 19:55:18 +00:00
vector < map < unsigned , vector < pair < cell * , int > > > > which_cell ;
which_cell . resize ( isize ( allh ) ) ;
for ( cell * c : acells ) {
int id = local_id [ c ] . second ;
for ( int i = 0 ; i < c - > type ; i + + )
which_cell [ c - > master - > fieldval ] [ bucketer ( ss [ id ] . face_centers [ i ] ) ] . emplace_back ( c , i ) ;
}
2021-07-11 09:03:35 +00:00
strafe_data . resize ( isize ( acells ) ) ;
2021-07-06 23:48:20 +00:00
for ( cell * c : acells ) {
int id = local_id [ c ] . second ;
2021-07-11 09:03:35 +00:00
int cid = local_id [ c ] . first ;
auto & tmcell = tmatrices_cell [ cid ] ;
2021-07-07 16:26:03 +00:00
vector < int > foundtab ;
vector < tuple < int , int , int > > foundtab_ids ;
2021-07-11 09:03:35 +00:00
strafe_data [ cid ] . resize ( c - > type ) ;
2021-07-06 23:48:20 +00:00
for ( int i = 0 ; i < c - > type ; i + + ) {
int found = 0 ;
hyperpoint ctr = ss [ id ] . face_centers [ i ] ;
2021-07-09 13:56:26 +00:00
transmatrix T1 = Id ;
int h_id = c - > master - > fieldval ;
vector < int > path ;
while ( true ) {
int d = - 1 ;
ld dist = hdist0 ( ctr ) ;
for ( int d1 = 0 ; d1 < S7 ; d1 + + ) {
auto ctr1 = iso_inverse ( tmatrices [ h_id ] [ d1 ] ) * ctr ;
ld dist1 = hdist0 ( ctr1 ) ;
if ( dist1 < dist - 1e-6 ) d = d1 , dist = dist1 ;
}
if ( d = = - 1 ) break ;
path . push_back ( d ) ;
T1 = T1 * tmatrices [ h_id ] [ d ] ;
ctr = iso_inverse ( tmatrices [ h_id ] [ d ] ) * ctr ;
h_id = allh [ h_id ] - > move ( d ) - > fieldval ;
}
for ( auto & va : vertex_adjacencies [ h_id ] ) {
2021-07-08 19:55:18 +00:00
hyperpoint ctr1 = iso_inverse ( va . T ) * ctr ;
auto bucket = bucketer ( ctr1 ) ;
for ( auto p : which_cell [ va . h_id ] [ bucket ] ) {
cell * c1 = p . first ;
int j = p . second ;
2021-07-06 23:48:20 +00:00
int id1 = local_id [ c1 ] . second ;
2021-07-08 19:55:18 +00:00
if ( hdist ( ctr1 , ss [ id1 ] . face_centers [ j ] ) < 1e-6 ) {
2021-07-09 13:56:26 +00:00
transmatrix T2 = T1 * va . T ;
if ( id = = id1 & & eqmatrix ( T2 , Id ) ) continue ;
2021-07-08 19:55:18 +00:00
c - > c . connect ( i , c1 , j , false ) ;
2021-07-09 13:56:26 +00:00
if ( ! found ) {
tmcell . push_back ( ss [ id ] . from_cellcenter * T2 * ss [ id1 ] . to_cellcenter ) ;
2021-08-04 13:28:17 +00:00
if ( elliptic ) fixelliptic ( tmcell . back ( ) ) ;
2021-07-09 13:56:26 +00:00
auto & ms = move_sequences [ local_id [ c ] . first ] ;
ms . push_back ( path ) ;
for ( auto dir : va . move_sequence ) ms . back ( ) . push_back ( dir ) ;
2021-07-11 09:03:35 +00:00
auto & sd = strafe_data [ cid ] [ i ] ;
sd . resize ( c - > type , - 1 ) ;
for ( int i1 = 0 ; i1 < c - > type ; i1 + + ) {
set < unsigned > facevertices ;
for ( auto v : ss [ id ] . faces [ i1 ] ) facevertices . insert ( bucketer ( v ) ) ;
2021-07-11 13:07:40 +00:00
if ( ss [ id ] . dirdist [ i ] [ i1 ] = = 1 ) {
2021-07-11 09:03:35 +00:00
int found_strafe = 0 ;
for ( int j1 = 0 ; j1 < c1 - > type ; j1 + + ) if ( j1 ! = j ) {
int num = 0 ;
for ( auto v : ss [ id1 ] . faces [ j1 ] )
if ( facevertices . count ( bucketer ( T2 * v ) ) )
num + + ;
if ( num = = 2 ) sd [ i1 ] = j1 , found_strafe + + ;
}
if ( found_strafe ! = 1 ) println ( hlog , " found_strafe = " , found_strafe ) ;
}
}
2021-07-11 13:07:40 +00:00
/* for bch, also provide second-order strafe */
if ( variation = = eVariation : : bch ) for ( int i1 = 0 ; i1 < c - > type ; i1 + + ) {
if ( ss [ id ] . dirdist [ i ] [ i1 ] ! = 2 ) continue ;
if ( isize ( ss [ id ] . faces [ i ] ) = = 6 ) continue ;
if ( isize ( ss [ id ] . faces [ i1 ] ) = = 6 ) continue ;
vector < int > fac ;
for ( int i2 = 0 ; i2 < c - > type ; i2 + + ) if ( ss [ id ] . dirdist [ i ] [ i2 ] = = 1 & & ss [ id ] . dirdist [ i2 ] [ i1 ] = = 1 )
fac . push_back ( sd [ i2 ] ) ;
if ( isize ( fac ) ! = 2 ) {
println ( hlog , " fac= " , fac ) ;
2021-07-18 09:14:29 +00:00
throw hr_exception ( " fac error " ) ;
2021-07-11 13:07:40 +00:00
}
int found_strafe = 0 ;
for ( int j1 = 0 ; j1 < c1 - > type ; j1 + + ) if ( j1 ! = j )
if ( ss [ id1 ] . dirdist [ j1 ] [ fac [ 0 ] ] = = 1 )
if ( ss [ id1 ] . dirdist [ j1 ] [ fac [ 1 ] ] = = 1 ) {
sd [ i1 ] = j1 ;
found_strafe + + ;
}
if ( found_strafe ! = 1 ) println ( hlog , " found_strafe = " , found_strafe , " (second order) " ) ;
}
2021-07-09 08:26:26 +00:00
}
2021-07-08 19:55:18 +00:00
foundtab_ids . emplace_back ( va . h_id , id1 , j ) ;
found + + ;
2021-07-06 23:48:20 +00:00
}
}
2021-07-08 20:04:14 +00:00
if ( found & & ! testing_subconnections ) break ;
}
if ( testing_subconnections & & ! found ) {
c - > c . connect ( i , c , i , false ) ;
tmcell . push_back ( Id ) ;
2021-07-06 23:48:20 +00:00
}
2021-07-07 16:26:03 +00:00
foundtab . push_back ( found ) ;
2021-07-06 23:48:20 +00:00
if ( found ! = 1 ) failures + + ;
}
2021-07-08 20:04:14 +00:00
if ( testing_subconnections ) println ( hlog , " foundtab = " , foundtab ) ;
2021-07-06 23:48:20 +00:00
}
println ( hlog , " total failures = " , failures ) ;
2021-07-08 20:04:14 +00:00
if ( failures & & ! testing_subconnections ) throw hr_exception ( " hrmap_closed3 failures " ) ;
2020-01-06 20:23:17 +00:00
}
2021-07-12 13:20:04 +00:00
transmatrix hrmap_closed3 : : relative_matrixc ( cell * c2 , cell * c1 , const hyperpoint & hint ) {
2021-07-06 23:48:20 +00:00
if ( c1 = = c2 ) return Id ;
int d = hr : : celldistance ( c2 , c1 ) ;
2019-10-12 11:19:58 +00:00
2021-07-08 20:37:06 +00:00
for ( int a = 0 ; a < c1 - > type ; a + + ) if ( hr : : celldistance ( c2 , c1 - > move ( a ) ) < d )
2021-07-06 23:48:20 +00:00
return adj ( c1 , a ) * relative_matrix ( c2 , c1 - > move ( a ) , hint ) ;
2020-01-16 15:50:07 +00:00
2021-07-08 20:37:06 +00:00
for ( int a = 0 ; a < c1 - > type ; a + + ) println ( hlog , " d= " , d , " vs " , hr : : celldistance ( c2 , c1 - > move ( a ) ) ) ;
2020-01-06 19:53:09 +00:00
println ( hlog , " error in hrmap_quotient3:::relative_matrix " ) ;
return Id ;
}
2020-05-04 01:21:14 +00:00
# if CAP_CRYSTAL
2022-07-11 14:04:07 +00:00
int encode_coord ( int bits , const crystal : : coord & co ) {
2019-10-12 11:19:58 +00:00
int c = 0 ;
2022-07-11 14:04:07 +00:00
for ( int i = 0 ; i < ( 1 < < bits ) ; i + + ) c | = ( ( co [ i ] > > 1 ) & ( ( 1 < < bits ) - 1 ) ) < < ( bits * i ) ;
2019-10-12 11:19:58 +00:00
return c ;
}
2022-07-11 14:04:07 +00:00
EX crystal : : coord decode_coord ( int bits , int a ) {
2019-10-12 11:19:58 +00:00
crystal : : coord co ;
2022-07-11 14:04:07 +00:00
for ( int i = 0 ; i < ( 1 < < bits ) ; i + + ) co [ i ] = ( a & ( ( 1 < < bits ) - 1 ) ) * 2 , a > > = bits ;
2019-10-12 11:19:58 +00:00
return co ;
}
struct hrmap_from_crystal : hrmap_quotient3 {
2022-07-11 14:04:07 +00:00
int bits ;
hrmap_from_crystal ( int b ) : bits ( b ) {
int size = 1 < < ( 4 * bits ) ;
initialize ( size ) ;
2019-10-12 11:19:58 +00:00
if ( 1 ) {
auto m = crystal : : new_map ( ) ;
dynamicval < hrmap * > cm ( currentmap , m ) ;
2022-07-11 14:04:07 +00:00
for ( int a = 0 ; a < size ; a + + ) {
auto co = decode_coord ( bits , a ) ;
2019-10-12 11:19:58 +00:00
heptagon * h1 = get_heptagon_at ( co ) ;
for ( int d = 0 ; d < 8 ; d + + ) {
2022-07-11 14:04:07 +00:00
int b = encode_coord ( bits , crystal : : get_coord ( h1 - > cmove ( d ) ) ) ;
2019-10-12 11:19:58 +00:00
allh [ a ] - > c . connect ( d , allh [ b ] , h1 - > c . spin ( d ) , false ) ;
tmatrices [ a ] . push_back ( crystal : : get_adj ( h1 , d ) ) ;
}
}
delete m ;
}
}
} ;
2020-05-04 01:21:14 +00:00
# endif
2020-01-15 16:58:41 +00:00
struct hrmap_field3 : reg3 : : hrmap_quotient3 {
2019-03-15 12:46:23 +00:00
2020-01-26 00:20:42 +00:00
fieldpattern : : fpattern * f ;
hrmap_field3 ( fieldpattern : : fpattern * ptr ) {
f = ptr ;
2020-01-15 16:58:41 +00:00
2020-01-26 00:20:42 +00:00
auto lgr = f - > local_group ;
2019-03-15 12:46:23 +00:00
2020-01-26 00:20:42 +00:00
int N = isize ( f - > matrices ) / lgr ;
2020-01-15 16:58:41 +00:00
initialize ( N ) ;
2019-03-15 12:46:23 +00:00
2020-01-15 16:58:41 +00:00
vector < int > moveid ( S7 ) , movedir ( lgr ) ;
for ( int s = 0 ; s < lgr ; s + + )
2020-04-05 08:53:34 +00:00
for ( int i = 0 ; i < S7 ; i + + ) if ( eqmatrix ( f - > fullv [ s ] * cgi . adjmoves [ 0 ] , cgi . adjmoves [ i ] ) )
2020-01-15 16:58:41 +00:00
moveid [ i ] = s ;
2019-03-15 12:46:23 +00:00
2020-01-15 16:58:41 +00:00
for ( int s = 0 ; s < lgr ; s + + )
2020-04-05 08:53:34 +00:00
for ( int i = 0 ; i < S7 ; i + + ) if ( hdist ( tC0 ( inverse ( f - > fullv [ s ] ) * cgi . adjmoves [ 0 ] ) , tC0 ( cgi . adjmoves [ i ] ) ) < 1e-4 )
2020-01-15 16:58:41 +00:00
movedir [ s ] = i ;
2019-03-15 12:46:23 +00:00
2020-01-15 16:58:41 +00:00
for ( int a = 0 ; a < N ; a + + ) {
tmatrices [ a ] . resize ( S7 ) ;
for ( int b = 0 ; b < S7 ; b + + ) {
int k = lgr * a ;
2021-05-20 20:59:24 +00:00
k = f - > matcode [ f - > mmul ( f - > mmul ( f - > matrices [ k ] , f - > matrices [ moveid [ b ] ] ) , f - > P ) ] ;
2020-01-26 00:20:42 +00:00
for ( int l = 0 ; l < lgr ; l + + ) if ( f - > gmul ( k , l ) % lgr = = 0 ) {
2020-04-05 08:53:34 +00:00
tmatrices [ a ] [ b ] = cgi . adjmoves [ b ] * f - > fullv [ l ] ;
2020-01-15 16:58:41 +00:00
allh [ a ] - > c . connect ( b , allh [ k / lgr ] , movedir [ l ] , false ) ;
2019-03-15 12:46:23 +00:00
}
}
2020-01-15 16:58:41 +00:00
}
2021-07-06 23:48:20 +00:00
make_subconnections ( ) ;
2019-03-15 15:42:14 +00:00
create_patterns ( ) ;
}
set < cellwalker > plane ;
void make_plane ( cellwalker cw ) {
if ( plane . count ( cw ) ) return ;
plane . insert ( cw ) ;
2021-07-12 09:07:22 +00:00
auto & ss = get_cellshape ( cw . at ) ;
for ( int i = 0 ; i < cw . at - > type ; i + + )
if ( ss . dirdist [ i ] [ cw . spin ] = = 1 )
2021-07-11 09:48:33 +00:00
make_plane ( strafe ( cw , i ) ) ;
2019-03-15 15:42:14 +00:00
}
void create_patterns ( ) {
2020-01-28 14:16:50 +00:00
DEBB ( DF_GEOM , ( " creating pattern = " , isize ( allh ) ) ) ;
2021-07-06 23:48:20 +00:00
if ( ! PURE ) {
println ( hlog , " create_patterns not implemented " ) ;
return ;
}
2020-01-28 14:16:50 +00:00
2019-03-15 15:42:14 +00:00
// also, strafe needs currentmap
dynamicval < hrmap * > c ( currentmap , this ) ;
if ( S7 = = 12 ) {
// Emerald in 534
cell * a = gamestart ( ) ;
2019-04-04 12:36:58 +00:00
cell * b = a ;
2019-03-15 15:42:14 +00:00
for ( cell * c : allcells ( ) )
2020-01-28 14:16:50 +00:00
if ( bounded_celldistance ( a , c ) = = 5 ) {
2019-03-15 15:42:14 +00:00
b = c ;
break ;
}
for ( cell * c : allcells ( ) )
2020-01-28 14:16:50 +00:00
if ( bounded_celldistance ( a , c ) > bounded_celldistance ( b , c ) )
2019-03-15 15:42:14 +00:00
c - > master - > zebraval | = 1 ;
// Vineyard in 534
b = ( cellwalker ( a , 0 ) + wstep + rev + wstep ) . at ;
for ( cell * c : allcells ( ) )
2020-01-28 14:16:50 +00:00
if ( bounded_celldistance ( a , c ) = = bounded_celldistance ( b , c ) )
2019-03-15 15:42:14 +00:00
c - > master - > zebraval | = 2 ;
}
2020-01-26 00:21:07 +00:00
if ( S7 = = 6 & & ginf [ geometry ] . vertex = = 5 ) {
2019-03-15 15:42:14 +00:00
// Emerald in 534
cell * a = gamestart ( ) ;
for ( cell * c : allcells ( ) )
2020-01-28 14:16:50 +00:00
if ( bounded_celldistance ( a , c ) > 3 )
2019-03-15 15:42:14 +00:00
c - > master - > zebraval | = 1 ;
// Vineyard in 435
make_plane ( cellwalker ( gamestart ( ) , 0 ) ) ;
2020-01-28 09:35:54 +00:00
DEBB ( DF_GEOM , ( " plane size = " , isize ( plane ) ) ) ;
2019-03-15 15:42:14 +00:00
set < int > plane_indices ;
for ( auto cw : plane ) plane_indices . insert ( cw . at - > master - > fieldval ) ;
2020-03-25 12:47:06 +00:00
int fN = isize ( f - > matrices ) ;
2019-03-15 15:42:14 +00:00
set < int > nwi ;
2020-03-25 12:47:06 +00:00
for ( int i = 0 ; i < fN ; i + + ) {
2019-03-15 15:42:14 +00:00
bool ok = true ;
for ( auto o : plane_indices ) {
2020-01-28 18:47:27 +00:00
int j = f - > gmul ( i , o * f - > local_group ) / f - > local_group ;
2019-03-15 15:42:14 +00:00
if ( plane_indices . count ( j ) ) ok = false ;
forCellEx ( c1 , allcells ( ) [ j ] ) if ( plane_indices . count ( c1 - > master - > fieldval ) ) ok = false ;
}
if ( ok ) nwi . insert ( i ) ;
}
2019-04-04 12:36:58 +00:00
int gpow = 0 ;
2019-03-15 15:42:14 +00:00
for ( int i : nwi ) {
int pw = 1 ;
int at = i ;
while ( true ) {
2020-01-28 18:47:27 +00:00
at = f - > gmul ( at , i ) ;
2019-03-15 15:42:14 +00:00
if ( ! nwi . count ( at ) ) break ;
pw + + ;
}
if ( pw = = 4 ) gpow = i ;
}
int u = 0 ;
for ( int a = 0 ; a < 5 ; a + + ) {
for ( int o : plane_indices ) {
2020-03-25 12:47:06 +00:00
int j = f - > gmul ( u , o * f - > local_group ) / f - > local_group ;
2019-03-15 15:42:14 +00:00
allcells ( ) [ j ] - > master - > zebraval | = 2 ;
}
2020-01-28 18:47:27 +00:00
u = f - > gmul ( u , gpow ) ;
2019-03-15 15:42:14 +00:00
}
}
2019-03-15 12:46:23 +00:00
}
2020-01-06 19:53:09 +00:00
} ;
2020-03-27 20:47:09 +00:00
/** \brief homology cover of the Seifert-Weber space */
2020-01-06 19:53:09 +00:00
namespace seifert_weber {
using crystal : : coord ;
vector < coord > periods ;
int flip ( int x ) { return ( x + 6 ) % 12 ; }
void build_reps ( ) {
// start_game();
2021-07-12 10:23:34 +00:00
auto & hsh = get_hsh ( ) ;
2019-03-15 12:46:23 +00:00
2020-01-06 19:53:09 +00:00
set < coord > boundaries ;
for ( int a = 0 ; a < 12 ; a + + )
2021-07-12 10:23:34 +00:00
for ( int b = 0 ; b < 12 ; b + + ) if ( hsh . dirdist [ a ] [ b ] = = 1 ) {
2020-01-06 19:53:09 +00:00
coord res = crystal : : c0 ;
int sa = a , sb = b ;
do {
// printf("%d ", sa);
if ( sa < 6 ) res [ sa ] + + ; else res [ sa - 6 ] - - ;
sa = flip ( sa ) ;
sb = flip ( sb ) ;
swap ( sa , sb ) ;
2021-07-12 10:23:34 +00:00
sb = hsh . next_dir [ sa ] [ sb ] ;
2020-01-06 19:53:09 +00:00
// sb = next_dirsa][sb];
}
while ( a ! = sa | | b ! = sb ) ;
// printf("\n");
if ( res > crystal : : c0 )
boundaries . insert ( res ) ;
}
2019-03-15 12:46:23 +00:00
2020-01-06 19:53:09 +00:00
periods . clear ( ) ;
2019-03-15 12:46:23 +00:00
2020-01-06 19:53:09 +00:00
for ( int index = 5 ; index > = 0 ; index - - ) {
for ( auto k : boundaries ) println ( hlog , k ) ;
2020-01-28 09:35:54 +00:00
DEBB ( DF_GEOM , ( " simplifying... " ) ) ;
2020-01-06 19:53:09 +00:00
for ( auto by : boundaries ) if ( among ( by [ index ] , 1 , - 1 ) ) {
2020-01-28 09:35:54 +00:00
DEBB ( DF_GEOM , ( " simplifying by " , by ) ) ;
2020-01-06 19:53:09 +00:00
periods . push_back ( by ) ;
set < coord > nb ;
for ( auto v : boundaries )
if ( v = = by ) ;
else if ( v [ index ] % by [ index ] = = 0 )
nb . insert ( v - by * ( v [ index ] / by [ index ] ) ) ;
else println ( hlog , " error " ) ;
2022-07-05 17:23:05 +00:00
boundaries = std : : move ( nb ) ;
2020-01-06 19:53:09 +00:00
break ;
}
2019-03-15 12:46:23 +00:00
}
}
2019-11-14 15:51:50 +00:00
2020-01-06 19:53:09 +00:00
int get_rep ( coord a ) {
a = a - periods [ 0 ] * ( a [ 5 ] / periods [ 0 ] [ 5 ] ) ;
a = a - periods [ 1 ] * ( a [ 4 ] / periods [ 1 ] [ 4 ] ) ;
a = a - periods [ 2 ] * ( a [ 3 ] / periods [ 2 ] [ 3 ] ) ;
for ( int i = 0 ; i < 3 ; i + + ) a [ i ] = gmod ( a [ i ] , 5 ) ;
return a [ 2 ] * 25 + a [ 1 ] * 5 + a [ 0 ] ;
2019-03-15 12:46:23 +00:00
}
2020-01-06 19:53:09 +00:00
coord decode ( int id ) {
coord res = crystal : : c0 ;
for ( int a = 0 ; a < 3 ; a + + ) res [ a ] = id % 5 , id / = 5 ;
return res ;
2019-04-08 14:16:16 +00:00
}
2020-01-06 19:53:09 +00:00
2020-01-06 20:24:21 +00:00
struct hrmap_singlecell : hrmap_quotient3 {
hrmap_singlecell ( ld angle ) {
initialize ( 1 ) ;
tmatrices [ 0 ] . resize ( S7 ) ;
for ( int b = 0 ; b < S7 ; b + + ) {
allh [ 0 ] - > c . connect ( b , allh [ 0 ] , ( b + S7 / 2 ) % S7 , false ) ;
2020-04-05 08:53:34 +00:00
transmatrix T = cgi . adjmoves [ b ] ;
2020-01-06 20:24:21 +00:00
hyperpoint p = tC0 ( T ) ;
tmatrices [ 0 ] [ b ] = rspintox ( p ) * xpush ( hdist0 ( p ) ) * cspin ( 2 , 1 , angle ) * spintox ( p ) ;
}
2021-08-07 09:32:54 +00:00
make_subconnections ( ) ;
2020-01-06 20:24:21 +00:00
}
} ;
2020-01-06 19:53:09 +00:00
struct hrmap_seifert_cover : hrmap_quotient3 {
hrmap_seifert_cover ( ) {
if ( periods . empty ( ) ) build_reps ( ) ;
2020-01-06 20:23:17 +00:00
initialize ( 125 ) ;
2020-01-06 19:53:09 +00:00
for ( int a = 0 ; a < 125 ; a + + ) {
tmatrices [ a ] . resize ( 12 ) ;
for ( int b = 0 ; b < 12 ; b + + ) {
coord x = decode ( a ) ;
if ( b < 6 ) x [ b ] + + ;
else x [ b - 6 ] - - ;
int a1 = get_rep ( x ) ;
allh [ a ] - > c . connect ( b , allh [ a1 ] , flip ( b ) , false ) ;
2020-04-05 08:53:34 +00:00
transmatrix T = cgi . adjmoves [ b ] ;
2020-01-06 19:53:09 +00:00
hyperpoint p = tC0 ( T ) ;
tmatrices [ a ] [ b ] = rspintox ( p ) * xpush ( hdist0 ( p ) ) * cspin ( 2 , 1 , 108 * degree ) * spintox ( p ) ;
}
}
2021-08-07 09:32:54 +00:00
make_subconnections ( ) ;
2020-01-06 19:53:09 +00:00
}
} ;
}
2019-03-15 12:46:23 +00:00
2022-07-11 14:04:07 +00:00
EX bool minimize_quotient_maps = false ;
2022-07-13 17:30:36 +00:00
EX bool subrule = false ;
2022-07-11 14:04:07 +00:00
2022-07-11 15:30:47 +00:00
EX bool strafe_test = false ;
2022-07-11 14:04:07 +00:00
hrmap_quotient3 * gen_quotient_map ( bool minimized , fieldpattern : : fpattern & fp ) {
# if CAP_FIELD
# if CAP_CRYSTAL
if ( geometry = = gSpace344 ) {
return new hrmap_from_crystal ( minimized ? 1 : 2 ) ;
}
else
# endif
if ( geometry = = gSpace535 & & minimized ) {
return new seifert_weber : : hrmap_singlecell ( 108 * degree ) ;
}
else if ( geometry = = gSpace535 )
return new seifert_weber : : hrmap_seifert_cover ;
else if ( hyperbolic ) {
return new hrmap_field3 ( & fp ) ;
}
# endif
return nullptr ;
}
2022-07-11 14:14:48 +00:00
struct hrmap_h3_abstract : hrmap {
reg3 : : hrmap_quotient3 * quotient_map ;
transmatrix adj ( heptagon * h , int d ) override {
throw hr_exception ( " any adj " ) ;
}
transmatrix relative_matrixc ( cell * c2 , cell * c1 , const hyperpoint & hint ) override {
if ( PURE ) return relative_matrix ( c2 - > master , c1 - > master , hint ) ;
return relative_matrix_via_masters ( c2 , c1 , hint ) ;
}
transmatrix master_relative ( cell * c , bool get_inverse ) override {
if ( PURE ) return Id ;
int aid = cell_id . at ( c ) ;
return quotient_map - > master_relative ( quotient_map - > acells [ aid ] , get_inverse ) ;
}
int shvid ( cell * c ) override {
if ( PURE ) return 0 ;
if ( ! cell_id . count ( c ) ) return quotient_map - > shvid ( c ) ;
int aid = cell_id . at ( c ) ;
return quotient_map - > shvid ( quotient_map - > acells [ aid ] ) ;
}
int wall_offset ( cell * c ) override {
if ( PURE ) return 0 ;
if ( ! cell_id . count ( c ) ) return quotient_map - > wall_offset ( c ) ; /* necessary because ray samples are from quotient_map */
int aid = cell_id . at ( c ) ;
return quotient_map - > wall_offset ( quotient_map - > acells [ aid ] ) ;
}
transmatrix adj ( cell * c , int d ) override {
if ( PURE ) return adj ( c - > master , d ) ;
if ( ! cell_id . count ( c ) ) return quotient_map - > adj ( c , d ) ; /* necessary because ray samples are from quotient_map */
int aid = cell_id . at ( c ) ;
return quotient_map - > tmatrices_cell [ aid ] [ d ] ;
}
subcellshape & get_cellshape ( cell * c ) override {
if ( PURE ) return * cgi . heptshape ;
int aid = cell_id . at ( c ) ;
return quotient_map - > get_cellshape ( quotient_map - > acells [ aid ] ) ;
}
map < cell * , int > cell_id ;
map < pair < heptagon * , int > , cell * > cell_at ;
cell * get_cell_at ( heptagon * h , int acell_id ) {
pair < heptagon * , int > p ( h , acell_id ) ;
auto & ca = cell_at [ p ] ;
if ( ! ca ) {
ca = newCell ( quotient_map - > acells [ acell_id ] - > type , h ) ;
cell_id [ ca ] = acell_id ;
if ( ! h - > c7 ) h - > c7 = ca ;
}
return ca ;
}
void find_cell_connection ( cell * c , int d ) override {
if ( PURE ) {
auto h = c - > master - > cmove ( d ) ;
c - > c . connect ( d , h - > c7 , c - > master - > c . spin ( d ) , false ) ;
return ;
}
int id = cell_id . at ( c ) ;
heptagon * h = c - > master ;
for ( int dir : quotient_map - > move_sequences [ id ] [ d ] )
h = h - > cmove ( dir ) ;
auto ac = quotient_map - > acells [ id ] ;
cell * c1 = get_cell_at ( h , quotient_map - > local_id [ ac - > move ( d ) ] . first ) ;
c - > c . connect ( d , c1 , ac - > c . spin ( d ) , false ) ;
}
transmatrix ray_iadj ( cell * c , int i ) override {
if ( PURE ) return iadj ( c , i ) ;
if ( ! cell_id . count ( c ) ) return quotient_map - > ray_iadj ( c , i ) ; /* necessary because ray samples are from quotient_map */
int aid = cell_id . at ( c ) ;
return quotient_map - > ray_iadj ( quotient_map - > acells [ aid ] , i ) ;
}
const vector < int > & get_move_seq ( cell * c , int i ) override {
int aid = cell_id . at ( c ) ;
return quotient_map - > get_move_seq ( quotient_map - > acells [ aid ] , i ) ;
}
cellwalker strafe ( cellwalker cw , int j ) override {
int aid = PURE ? cw . at - > master - > fieldval : cell_id . at ( cw . at ) ;
2022-07-11 15:30:47 +00:00
auto ress = quotient_map - > strafe ( cellwalker ( quotient_map - > acells [ aid ] , cw . spin ) , j ) ;
cellwalker res = cellwalker ( cw . at - > cmove ( j ) , ress . spin ) ;
if ( PURE & & strafe_test ) {
hyperpoint hfront = tC0 ( cgi . adjmoves [ cw . spin ] ) ;
cw . at - > cmove ( j ) ;
transmatrix T = currentmap - > adj ( cw . at , j ) ;
for ( int i = 0 ; i < S7 ; i + + ) if ( i ! = cw . at - > c . spin ( j ) )
if ( hdist ( hfront , T * tC0 ( cgi . adjmoves [ i ] ) ) < cgi . strafedist + .01 ) {
auto resx = cellwalker ( cw . at - > cmove ( j ) , i ) ;
if ( res = = resx ) return res ;
if ( PURE & & res ! = resx ) println ( hlog , " h3: " , res , " vs " , resx ) ;
}
throw hr_exception ( " incorrect strafe " ) ;
}
2022-07-11 14:14:48 +00:00
2022-07-11 15:30:47 +00:00
return res ;
2022-07-11 14:14:48 +00:00
}
} ;
struct hrmap_h3 : hrmap_h3_abstract {
2019-03-02 23:43:31 +00:00
heptagon * origin ;
hrmap * binary_map ;
2022-07-11 14:16:23 +00:00
vector < heptagon * > extra_origins ;
2019-03-02 23:43:31 +00:00
Remove USE_UNORDERED_MAP because it has bit-rotted.
Trying to compile with `-DUSE_UNORDERED_MAP` produces lots of compiler errors
like these, because of missing `std::hash` specializations.
Also, `#define unordered_map map` is just evil!
```
./nonisotropic.cpp:875:36: note: in instantiation of template class 'std::__1::unordered_map<hr::nilv::mvec, hr::heptagon *,
std::__1::hash<hr::nilv::mvec>, std::__1::equal_to<hr::nilv::mvec>, std::__1::allocator<std::__1::pair<const hr::nilv::mvec, hr::heptagon
*> > >' requested here
unordered_map<mvec, heptagon*> at;
^
./nonisotropic.cpp:239:58: note: in instantiation of template class 'std::__1::unordered_map<std::__1::pair<hr::heptagon *, hr::heptagon *>,
hr::heptagon *, std::__1::hash<std::__1::pair<hr::heptagon *, hr::heptagon *> >, std::__1::equal_to<std::__1::pair<hr::heptagon *,
hr::heptagon *> >, std::__1::allocator<std::__1::pair<const std::__1::pair<hr::heptagon *, hr::heptagon *>, hr::heptagon *> > >'
requested here
unordered_map<pair<heptagon*, heptagon*>, heptagon*> at;
^
./nonisotropic.cpp:457:49: error: no matching member function for call to 'iadj'
while(h1->distance < h2->distance) back = iadj(h2, down) * back, h2 = h2->cmove(down);
^~~~
cell.cpp:42:15: note: candidate function not viable: no known conversion from 'hr::sn::hrmap_solnih' to 'hr::hrmap' for object argument
transmatrix iadj(heptagon *h, int d) {
^
cell.cpp:41:22: note: candidate function not viable: no known conversion from 'hr::sn::hrmap_solnih' to 'hr::hrmap' for object argument
struct transmatrix iadj(cell *c, int i) { cell *c1 = c->cmove(i); return adj(c1, c->c.spin(i)); }
^
```
2020-09-25 03:15:19 +00:00
map < heptagon * , pair < heptagon * , transmatrix > > reg_gmatrix ;
map < heptagon * , vector < pair < heptagon * , transmatrix > > > altmap ;
2019-03-02 23:43:31 +00:00
2019-04-03 18:34:22 +00:00
vector < cell * > & allcells ( ) override {
return hrmap : : allcells ( ) ;
}
2021-07-06 23:48:20 +00:00
hrmap_h3 ( ) {
2021-07-04 08:36:16 +00:00
origin = init_heptagon ( S7 ) ;
2019-03-02 23:43:31 +00:00
heptagon & h = * origin ;
h . s = hsOrigin ;
2022-07-11 14:14:48 +00:00
if ( PURE ) h . c7 = newCell ( S7 , origin ) ;
2019-03-03 00:11:37 +00:00
worst_error1 = 0 , worst_error2 = 0 ;
2019-03-02 23:43:31 +00:00
dynamicval < hrmap * > cr ( currentmap , this ) ;
heptagon * alt = NULL ;
transmatrix T = Id ;
2019-10-10 11:15:08 +00:00
binary_map = nullptr ;
2022-07-11 14:04:07 +00:00
quotient_map = gen_quotient_map ( minimize_quotient_maps , currfp ) ;
2019-10-10 11:15:08 +00:00
2020-02-07 18:45:20 +00:00
h . zebraval = quotient_map ? quotient_map - > allh [ 0 ] - > zebraval : 0 ;
2019-10-10 11:15:08 +00:00
2020-10-15 14:33:52 +00:00
# if CAP_BT
2019-10-10 11:15:08 +00:00
if ( hyperbolic ) {
2019-03-02 23:43:31 +00:00
dynamicval < eGeometry > g ( geometry , gBinary3 ) ;
2019-12-14 11:05:01 +00:00
bt : : build_tmatrix ( ) ;
2021-07-04 08:36:16 +00:00
alt = init_heptagon ( S7 ) ;
2019-03-02 23:43:31 +00:00
alt - > s = hsOrigin ;
alt - > alt = alt ;
2019-12-14 11:05:01 +00:00
binary_map = bt : : new_alt_map ( alt ) ;
2019-03-02 23:43:31 +00:00
T = xpush ( .01241 ) * spin ( 1.4117 ) * xpush ( 0.1241 ) * cspin ( 0 , 2 , 1.1249 ) * xpush ( 0.07 ) * Id ;
}
2020-10-15 14:33:52 +00:00
# endif
2019-03-02 23:43:31 +00:00
reg_gmatrix [ origin ] = make_pair ( alt , T ) ;
altmap [ alt ] . emplace_back ( origin , T ) ;
2022-07-11 14:14:48 +00:00
if ( PURE ) {
celllister cl ( origin - > c7 , 4 , 100000 , NULL ) ;
for ( cell * c : cl . lst ) {
hyperpoint h = tC0 ( relative_matrix ( c - > master , origin , C0 ) ) ;
cgi . close_distances [ bucketer ( h ) ] = cl . getdist ( c ) ;
}
2019-03-04 17:03:16 +00:00
}
2022-07-11 14:14:48 +00:00
if ( ! PURE ) get_cell_at ( origin , 0 ) ;
2019-03-02 23:43:31 +00:00
}
2019-03-03 00:11:37 +00:00
ld worst_error1 , worst_error2 ;
2019-03-02 23:43:31 +00:00
2019-05-13 15:17:05 +00:00
heptagon * getOrigin ( ) override {
2019-03-02 23:43:31 +00:00
return origin ;
}
2019-03-09 00:00:46 +00:00
void fix_distances ( heptagon * h , heptagon * h2 ) {
vector < heptagon * > to_fix ;
auto fix_pair = [ & ] ( heptagon * h , heptagon * h2 ) {
if ( ! h2 ) return ;
if ( h - > distance > h2 - > distance + 1 ) {
h - > distance = h2 - > distance + 1 ;
to_fix . push_back ( h ) ;
}
else if ( h2 - > distance > h - > distance + 1 ) {
h2 - > distance = h - > distance + 1 ;
to_fix . push_back ( h2 ) ;
}
if ( h - > alt & & h - > alt = = h2 - > alt ) {
if ( altdist ( h ) > altdist ( h2 ) + 1 ) {
altdist ( h ) = altdist ( h2 ) + 1 ;
to_fix . push_back ( h ) ;
}
else if ( altdist ( h2 ) > altdist ( h ) + 1 ) {
altdist ( h2 ) = altdist ( h ) + 1 ;
to_fix . push_back ( h2 ) ;
}
}
} ;
if ( ! h2 ) to_fix = { h } ;
else fix_pair ( h , h2 ) ;
for ( int i = 0 ; i < isize ( to_fix ) ; i + + ) {
h = to_fix [ i ] ;
for ( int j = 0 ; j < S7 ; j + + ) fix_pair ( h , h - > move ( j ) ) ;
}
}
2019-03-02 23:43:31 +00:00
# define DEB 0
2019-03-15 13:26:24 +00:00
heptagon * counterpart ( heptagon * h ) {
return quotient_map - > allh [ h - > fieldval ] ;
}
2019-03-02 23:43:31 +00:00
2020-07-04 22:45:25 +00:00
void verify_neighbors ( heptagon * alt , int steps , const hyperpoint & hT ) {
ld err ;
for ( auto & p2 : altmap [ alt ] ) if ( ( err = intval ( tC0 ( p2 . second ) , hT ) ) < 1e-3 ) {
println ( hlog , " FAIL " ) ;
exit ( 3 ) ;
}
2020-10-15 14:33:52 +00:00
# if CAP_BT
2020-07-04 22:45:25 +00:00
if ( steps ) {
dynamicval < eGeometry > g ( geometry , gBinary3 ) ;
dynamicval < hrmap * > cm ( currentmap , binary_map ) ;
for ( int i = 0 ; i < alt - > type ; i + + )
verify_neighbors ( alt - > cmove ( i ) , steps - 1 , currentmap - > iadj ( alt , i ) * hT ) ;
}
2020-10-15 14:33:52 +00:00
# endif
2020-07-04 22:45:25 +00:00
}
2019-05-13 15:17:05 +00:00
heptagon * create_step ( heptagon * parent , int d ) override {
2019-03-02 23:43:31 +00:00
auto & p1 = reg_gmatrix [ parent ] ;
if ( DEB ) println ( hlog , " creating step " , parent , " : " , d , " , at " , p1 . first , tC0 ( p1 . second ) ) ;
heptagon * alt = p1 . first ;
2019-03-15 13:26:24 +00:00
# if CAP_FIELD
2020-04-05 08:53:34 +00:00
transmatrix T = p1 . second * ( quotient_map ? quotient_map - > tmatrices [ parent - > fieldval ] [ d ] : cgi . adjmoves [ d ] ) ;
2019-03-15 13:26:24 +00:00
# else
2020-04-05 08:53:34 +00:00
transmatrix T = p1 . second * cgi . adjmoves [ d ] ;
2019-03-15 13:26:24 +00:00
# endif
2020-10-15 14:33:52 +00:00
# if CAP_BT
2019-03-02 23:43:31 +00:00
if ( hyperbolic ) {
dynamicval < eGeometry > g ( geometry , gBinary3 ) ;
2019-03-08 21:38:44 +00:00
dynamicval < hrmap * > cm ( currentmap , binary_map ) ;
2019-11-14 15:51:50 +00:00
binary_map - > virtualRebase ( alt , T ) ;
2019-03-02 23:43:31 +00:00
}
2020-10-15 14:33:52 +00:00
# endif
2020-05-09 08:41:15 +00:00
2019-03-02 23:43:31 +00:00
fixmatrix ( T ) ;
auto hT = tC0 ( T ) ;
if ( DEB ) println ( hlog , " searching at " , alt , " : " , hT ) ;
if ( DEB ) for ( auto & p2 : altmap [ alt ] ) println ( hlog , " for " , tC0 ( p2 . second ) , " intval is " , intval ( tC0 ( p2 . second ) , hT ) ) ;
ld err ;
for ( auto & p2 : altmap [ alt ] ) if ( ( err = intval ( tC0 ( p2 . second ) , hT ) ) < 1e-3 ) {
if ( err > worst_error1 ) println ( hlog , format ( " worst_error1 = %lg " , double ( worst_error1 = err ) ) ) ;
// println(hlog, "YES found in ", isize(altmap[alt]));
if ( DEB ) println ( hlog , " -> found " , p2 . first ) ;
int fb = 0 ;
2020-05-08 19:18:47 +00:00
hyperpoint old = tC0 ( p1 . second ) ; ;
2019-03-15 13:26:24 +00:00
# if CAP_FIELD
2019-10-10 11:15:08 +00:00
if ( quotient_map ) {
2019-03-15 13:26:24 +00:00
p2 . first - > c . connect ( counterpart ( parent ) - > c . spin ( d ) , parent , d , false ) ;
2019-05-05 16:14:47 +00:00
fix_distances ( p2 . first , parent ) ;
2019-03-15 13:26:24 +00:00
return p2 . first ;
}
# endif
2019-03-02 23:43:31 +00:00
for ( int d2 = 0 ; d2 < S7 ; d2 + + ) {
2020-04-05 08:53:34 +00:00
hyperpoint back = p2 . second * tC0 ( cgi . adjmoves [ d2 ] ) ;
2019-03-02 23:43:31 +00:00
if ( ( err = intval ( back , old ) ) < 1e-3 ) {
if ( err > worst_error2 ) println ( hlog , format ( " worst_error2 = %lg " , double ( worst_error2 = err ) ) ) ;
if ( p2 . first - > move ( d2 ) ) println ( hlog , " error: repeated edge " ) ;
p2 . first - > c . connect ( d2 , parent , d , false ) ;
2019-03-09 00:00:46 +00:00
fix_distances ( p2 . first , parent ) ;
2019-03-02 23:43:31 +00:00
fb + + ;
}
}
if ( fb ! = 1 ) {
println ( hlog , " found fb = " , fb ) ;
println ( hlog , old ) ;
for ( int d2 = 0 ; d2 < S7 ; d2 + + ) {
2020-04-05 08:53:34 +00:00
println ( hlog , p2 . second * tC0 ( cgi . adjmoves [ d2 ] ) , " in distance " , intval ( p2 . second * tC0 ( cgi . adjmoves [ d2 ] ) , old ) ) ;
2019-03-02 23:43:31 +00:00
}
parent - > c . connect ( d , parent , d , false ) ;
return parent ;
}
return p2 . first ;
}
2020-07-04 22:45:25 +00:00
if ( extra_verification ) verify_neighbors ( alt , extra_verification , hT ) ;
2019-03-02 23:43:31 +00:00
if ( DEB ) println ( hlog , " -> not found " ) ;
2019-03-16 21:18:41 +00:00
int d2 = 0 , fv = isize ( reg_gmatrix ) ;
2019-03-15 13:26:24 +00:00
# if CAP_FIELD
2019-10-10 11:15:08 +00:00
if ( quotient_map ) {
2019-03-15 13:26:24 +00:00
auto cp = counterpart ( parent ) ;
d2 = cp - > c . spin ( d ) ;
fv = cp - > c . move ( d ) - > fieldval ;
}
# endif
2021-07-04 08:36:16 +00:00
heptagon * created = init_heptagon ( S7 ) ;
2022-07-11 15:31:03 +00:00
if ( PURE & & parent - > c7 ) created - > c7 = newCell ( S7 , created ) ;
2019-03-15 15:42:14 +00:00
# if CAP_FIELD
2019-10-10 11:15:08 +00:00
if ( quotient_map ) {
2020-01-28 14:17:33 +00:00
created - > emeraldval = fv ;
2019-03-15 15:42:14 +00:00
created - > zebraval = quotient_map - > allh [ fv ] - > zebraval ;
}
else
# endif
2019-03-02 23:43:31 +00:00
created - > zebraval = hrand ( 10 ) ;
2019-03-15 13:26:24 +00:00
created - > fieldval = fv ;
2019-03-09 00:00:46 +00:00
created - > distance = parent - > distance + 1 ;
2020-01-26 00:22:04 +00:00
created - > fiftyval = 9999 ;
2019-03-02 23:43:31 +00:00
fixmatrix ( T ) ;
reg_gmatrix [ created ] = make_pair ( alt , T ) ;
altmap [ alt ] . emplace_back ( created , T ) ;
2019-03-15 13:26:24 +00:00
created - > c . connect ( d2 , parent , d , false ) ;
2019-03-02 23:43:31 +00:00
return created ;
}
2021-07-06 23:48:20 +00:00
~ hrmap_h3 ( ) {
2020-10-15 14:33:52 +00:00
# if CAP_BT
2019-03-09 00:00:46 +00:00
if ( binary_map ) {
dynamicval < eGeometry > g ( geometry , gBinary3 ) ;
2019-03-09 00:18:47 +00:00
delete binary_map ;
2019-03-09 00:00:46 +00:00
}
2020-10-15 14:33:52 +00:00
# endif
2019-03-15 13:26:24 +00:00
if ( quotient_map ) delete quotient_map ;
2019-03-08 21:38:44 +00:00
clearfrom ( origin ) ;
2022-07-11 14:16:23 +00:00
for ( auto e : extra_origins ) clearfrom ( e ) ;
2019-03-08 21:38:44 +00:00
}
2019-03-09 00:00:46 +00:00
map < heptagon * , int > reducers ;
2021-07-29 10:02:14 +00:00
bool link_alt ( heptagon * h , heptagon * alt , hstate firststate , int dir ) override {
2019-03-09 00:00:46 +00:00
altdist ( h ) = 0 ;
2021-07-29 10:02:14 +00:00
if ( firststate ! = hsOrigin ) reducers [ h ] = dir ;
return true ;
2019-03-09 00:00:46 +00:00
}
2021-07-29 12:51:49 +00:00
void extend_altmap ( heptagon * h , int levs , bool link_cdata ) override {
2019-03-09 00:00:46 +00:00
if ( reducers . count ( h ) ) {
heptspin hs ( h , reducers [ h ] ) ;
reducers . erase ( h ) ;
hs + = wstep ;
hs + = rev ;
altdist ( hs . at ) = altdist ( h ) - 1 ;
hs . at - > alt = h - > alt ;
reducers [ hs . at ] = hs . spin ;
2019-05-05 16:14:47 +00:00
fix_distances ( hs . at , NULL ) ;
2019-03-09 00:00:46 +00:00
}
for ( int i = 0 ; i < S7 ; i + + ) {
auto h2 = h - > cmove ( i ) ;
if ( h2 - > alt = = NULL ) {
h2 - > alt = h - > alt ;
altdist ( h2 ) = altdist ( h ) + 1 ;
fix_distances ( h2 , NULL ) ;
}
}
2019-03-08 21:38:44 +00:00
}
2019-11-30 17:47:04 +00:00
transmatrix adj ( heptagon * h , int d ) override {
2019-11-14 15:51:50 +00:00
# if CAP_FIELD
if ( quotient_map ) return quotient_map - > adj ( h , d ) ;
else
# endif
2019-11-26 23:39:41 +00:00
return relative_matrix ( h - > cmove ( d ) , h , C0 ) ;
2019-11-14 15:51:50 +00:00
}
2021-07-12 13:20:04 +00:00
transmatrix relative_matrixh ( heptagon * h2 , heptagon * h1 , const hyperpoint & hint ) override {
2019-03-08 21:38:44 +00:00
auto p1 = reg_gmatrix [ h1 ] ;
auto p2 = reg_gmatrix [ h2 ] ;
transmatrix T = Id ;
2020-10-15 14:33:52 +00:00
# if CAP_BT
2019-03-08 21:38:44 +00:00
if ( hyperbolic ) {
dynamicval < eGeometry > g ( geometry , gBinary3 ) ;
dynamicval < hrmap * > cm ( currentmap , binary_map ) ;
2019-11-26 23:39:41 +00:00
T = binary_map - > relative_matrix ( p2 . first , p1 . first , hint ) ;
2019-03-08 21:38:44 +00:00
}
2020-10-15 14:33:52 +00:00
# endif
T = inverse ( p1 . second ) * T * p2 . second ;
2019-10-26 22:45:34 +00:00
if ( elliptic & & T [ LDIM ] [ LDIM ] < 0 ) T = centralsym * T ;
return T ;
2019-03-08 21:38:44 +00:00
}
2022-07-11 14:16:23 +00:00
cell * gen_extra_origin ( int fv ) override {
auto orig = isize ( extra_origins ) ? extra_origins . back ( ) : origin ;
auto & p1 = reg_gmatrix [ orig ] ;
heptagon * alt = p1 . first ;
2022-07-13 18:56:49 +00:00
transmatrix T = p1 . second ;
for ( int a = 0 ; a < 10 ; a + + ) {
T = T * xpush ( 10 ) ;
# if CAP_BT
if ( hyperbolic ) {
dynamicval < eGeometry > g ( geometry , gBinary3 ) ;
dynamicval < hrmap * > cm ( currentmap , binary_map ) ;
binary_map - > virtualRebase ( alt , T ) ;
fixmatrix ( T ) ;
}
# endif
2022-07-11 14:16:23 +00:00
}
heptagon * created = init_heptagon ( S7 ) ;
2022-07-11 15:31:24 +00:00
2022-07-11 14:16:23 +00:00
created - > s = hsOrigin ;
2022-07-11 15:31:24 +00:00
created - > fieldval = quotient_map - > acells [ fv ] - > master - > fieldval ;
2022-07-11 14:16:23 +00:00
reg_gmatrix [ created ] = make_pair ( alt , T ) ;
altmap [ alt ] . emplace_back ( created , T ) ;
extra_origins . push_back ( created ) ;
2022-07-11 15:31:24 +00:00
return get_cell_at ( created , fv ) ;
2022-07-11 14:16:23 +00:00
}
2022-07-11 14:14:48 +00:00
} ;
2021-07-11 09:48:33 +00:00
2022-07-11 15:32:27 +00:00
EX int get_aid ( cell * c ) {
auto m = dynamic_cast < hrmap_h3 * > ( currentmap ) ;
if ( ! m ) throw hr_exception ( " get_aid incorrect " ) ;
2022-07-12 10:16:28 +00:00
if ( PURE ) return c - > master - > fieldval ;
2022-07-11 15:32:27 +00:00
return m - > cell_id [ c ] ;
}
EX int get_size_of_aid ( int aid ) {
auto m = dynamic_cast < hrmap_h3 * > ( currentmap ) ;
if ( ! m ) throw hr_exception ( " get_size_of_fv incorrect " ) ;
return m - > quotient_map - > acells [ aid ] - > type ;
2019-03-02 23:43:31 +00:00
} ;
2020-01-26 00:23:10 +00:00
2021-07-06 23:48:20 +00:00
struct hrmap_sphere3 : hrmap_closed3 {
vector < transmatrix > locations ;
hrmap_sphere3 ( ) {
heptagon * h = init_heptagon ( S7 ) ;
h - > s = hsOrigin ;
locations . push_back ( Id ) ;
allh . push_back ( h ) ;
for ( int i = 0 ; i < isize ( allh ) ; i + + ) {
tmatrices . emplace_back ( ) ;
auto & tmi = tmatrices . back ( ) ;
transmatrix T1 = locations [ i ] ;
hyperpoint old = tC0 ( T1 ) ;
for ( int d = 0 ; d < S7 ; d + + ) {
transmatrix T = T1 * cgi . adjmoves [ d ] ;
fixmatrix ( T ) ;
auto hT = tC0 ( T ) ;
bool hopf = stretch : : applicable ( ) ;
if ( hopf )
T = stretch : : translate ( hT ) ;
for ( int i1 = 0 ; i1 < isize ( allh ) ; i1 + + )
if ( intval ( tC0 ( locations [ i1 ] ) , hT ) < 1e-3 ) {
int fb = 0 ;
for ( int d2 = 0 ; d2 < S7 ; d2 + + ) {
hyperpoint back = locations [ i1 ] * tC0 ( cgi . adjmoves [ d2 ] ) ;
if ( intval ( back , old ) < 1e-3 ) {
allh [ i ] - > c . connect ( d , allh [ i1 ] , d2 , false ) ;
fb + + ;
tmi . push_back ( inverse ( T1 ) * locations [ i1 ] ) ;
}
}
if ( fb ! = 1 ) throw hr_exception ( " friend not found " ) ;
goto next_d ;
}
if ( 1 ) {
int d2 = 0 ;
if ( hopf ) {
for ( d2 = 0 ; d2 < S7 ; d2 + + ) {
hyperpoint back = T * tC0 ( cgi . adjmoves [ d2 ] ) ;
if ( intval ( back , old ) < 1e-3 )
break ;
}
if ( d2 = = S7 )
throw hr_exception ( " Hopf connection failed " ) ;
}
heptagon * h = init_heptagon ( S7 ) ;
h - > zebraval = hrand ( 10 ) ;
h - > fieldval = isize ( allh ) ;
h - > fiftyval = 9999 ;
allh . push_back ( h ) ;
locations . push_back ( T ) ;
if ( isnan ( T [ 0 ] [ 0 ] ) ) exit ( 1 ) ;
allh [ i ] - > c . connect ( d , h , d2 , false ) ;
tmi . push_back ( inverse ( T1 ) * T ) ;
2021-08-04 13:28:17 +00:00
if ( elliptic ) fixelliptic ( tmi . back ( ) ) ;
2021-07-06 23:48:20 +00:00
}
next_d : ;
}
}
make_subconnections ( ) ;
}
~ hrmap_sphere3 ( ) {
clearfrom ( allh [ 0 ] ) ;
}
2021-07-12 13:20:04 +00:00
transmatrix relative_matrixh ( heptagon * h2 , heptagon * h1 , const hyperpoint & hint ) override {
2021-07-06 23:48:20 +00:00
return iso_inverse ( locations [ h1 - > fieldval ] ) * locations [ h2 - > fieldval ] ;
}
} ;
2021-07-12 08:01:16 +00:00
EX const transmatrix & get_sphere_loc ( int v ) {
return ( ( hrmap_sphere3 * ) currentmap ) - > locations [ v ] ;
}
2022-07-13 15:34:29 +00:00
struct ruleset {
2020-01-26 00:23:10 +00:00
fieldpattern : : fpattern fp ;
2020-01-28 10:58:34 +00:00
vector < int > root ;
2020-01-26 00:23:10 +00:00
string other ;
vector < short > children ;
2022-07-13 16:51:31 +00:00
vector < int > childpos ;
2022-07-13 15:34:29 +00:00
2020-01-26 00:23:10 +00:00
vector < int > otherpos ;
2022-07-13 15:34:29 +00:00
virtual hrmap_quotient3 * qmap ( ) = 0 ;
ruleset ( ) : fp ( 0 ) { }
2020-01-26 00:23:10 +00:00
void load_ruleset ( string fname ) {
2022-07-13 17:30:36 +00:00
shstream ins ( decompress_string ( read_file_as_string ( fname ) ) ) ;
2021-05-20 21:06:02 +00:00
dynamicval < bool > q ( fieldpattern : : use_quotient_fp , true ) ;
2020-01-26 00:23:10 +00:00
hread_fpattern ( ins , fp ) ;
2022-07-13 17:30:36 +00:00
2020-01-26 00:23:10 +00:00
hread ( ins , root ) ;
hread ( ins , children ) ;
hread ( ins , other ) ;
2022-07-13 17:30:36 +00:00
// hread(ins, childpos);
2022-07-13 16:51:31 +00:00
2022-07-13 17:30:36 +00:00
int t = S7 ;
2022-07-13 16:51:31 +00:00
int qty = isize ( children ) / t ;
for ( int i = 0 ; i < = qty ; i + + ) childpos . push_back ( i * t ) ;
}
2022-07-13 17:30:36 +00:00
void load_ruleset_new ( string fname ) {
shstream ins ( decompress_string ( read_file_as_string ( fname ) ) ) ;
ins . read ( ins . vernum ) ;
mapstream : : load_geometry ( ins ) ;
ins . read ( fieldpattern : : use_rule_fp ) ;
ins . read ( fieldpattern : : use_quotient_fp ) ;
ins . read ( reg3 : : minimize_quotient_maps ) ;
hread_fpattern ( ins , fp ) ;
hread ( ins , root ) ;
hread ( ins , children ) ;
hread ( ins , other ) ;
hread ( ins , childpos ) ;
}
2020-03-27 20:47:09 +00:00
/** \brief address = (fieldvalue, state) */
2020-01-28 09:35:41 +00:00
typedef pair < int , int > address ;
/** nles[x] lists the addresses from which we can reach address x
* without ever ending in the starting point */
map < address , set < address > > nonlooping_earlier_states ;
2020-01-29 18:23:31 +00:00
vector < vector < int > > possible_states ;
2022-07-13 16:51:31 +00:00
virtual int connection ( int fv , int d ) = 0 ;
2020-01-28 09:35:41 +00:00
void find_mappings ( ) {
2022-07-13 16:51:31 +00:00
int opos = 0 ;
for ( int c : children ) {
if ( c < - 1 ) c + = ( 1 < < 16 ) ;
if ( c > = 0 )
otherpos . push_back ( - 1 ) ;
else {
otherpos . push_back ( opos ) ;
while ( other [ opos ] ! = ' , ' ) opos + + ;
opos + + ;
}
}
2022-07-13 18:58:42 +00:00
/* find all back paths */
2020-01-28 09:35:41 +00:00
auto & nles = nonlooping_earlier_states ;
nles . clear ( ) ;
2020-01-28 10:58:34 +00:00
vector < address > bfs ;
2022-07-13 16:51:31 +00:00
int qty = isize ( root ) ;
2020-01-29 17:20:14 +00:00
for ( int i = 0 ; i < qty ; i + + )
2020-01-28 10:58:34 +00:00
bfs . emplace_back ( i , root [ i ] ) ;
2022-07-13 16:51:31 +00:00
int qstate = isize ( childpos ) - 1 ;
2020-01-28 09:35:41 +00:00
DEBB ( DF_GEOM , ( " qstate = " , qstate ) ) ;
for ( int i = 0 ; i < isize ( bfs ) ; i + + ) {
address last = bfs [ i ] ;
int state = last . second ;
int fv = last . first ;
2022-07-13 17:56:32 +00:00
for ( int d = 0 ; d < childpos [ state + 1 ] - childpos [ state ] ; d + + ) {
2022-07-13 16:51:31 +00:00
int nstate = children [ childpos [ state ] + d ] ;
2021-05-21 23:25:41 +00:00
if ( nstate < - 1 ) nstate + = ( 1 < < 16 ) ;
2020-01-28 09:35:41 +00:00
if ( nstate > = 0 ) {
2022-07-13 16:51:31 +00:00
address next = { connection ( fv , d ) , nstate } ;
2020-01-28 09:35:41 +00:00
if ( ! nles . count ( next ) ) bfs . push_back ( next ) ;
nles [ next ] . insert ( last ) ;
}
}
}
vector < int > q ( qstate , 0 ) ;
for ( auto p : bfs ) q [ p . second ] + + ;
2022-07-13 15:34:29 +00:00
vector < int > q2 ( isize ( qmap ( ) - > allh ) + 1 , 0 ) ;
2020-01-28 09:35:41 +00:00
for ( auto p : q ) q2 [ p ] + + ;
DEBB ( DF_GEOM , ( " q2 = " , q2 ) ) ;
2022-07-13 18:58:42 +00:00
/* remove BFS roots, and addresses that lead only there */
2020-01-28 10:58:34 +00:00
bfs = { } ;
2022-07-13 17:56:32 +00:00
for ( int i = 0 ; i < isize ( root ) ; i + + )
2020-01-28 10:58:34 +00:00
bfs . emplace_back ( i , root [ i ] ) ;
2020-01-28 09:35:41 +00:00
for ( int i = 0 ; i < isize ( bfs ) ; i + + ) {
address last = bfs [ i ] ;
int state = last . second ;
int fv = last . first ;
2022-07-13 17:56:32 +00:00
for ( int d = 0 ; d < childpos [ state + 1 ] - childpos [ state ] ; d + + ) {
2022-07-13 16:51:31 +00:00
int nstate = children [ childpos [ state ] + d ] ;
2021-05-21 23:25:41 +00:00
if ( nstate < - 1 ) nstate + = ( 1 < < 16 ) ;
2020-01-28 09:35:41 +00:00
if ( nstate > = 0 ) {
2022-07-13 16:51:31 +00:00
address next = { connection ( fv , d ) , nstate } ;
2020-01-28 09:35:41 +00:00
if ( ! nles . count ( next ) ) continue ;
int c = isize ( nles [ next ] ) ;
nles [ next ] . erase ( last ) ;
if ( nles [ next ] . empty ( ) & & c ) {
nles . erase ( next ) ;
bfs . push_back ( next ) ;
}
}
}
}
DEBB ( DF_GEOM , ( " removed cases = " , isize ( bfs ) ) ) ;
2022-07-13 18:58:42 +00:00
/* remove non-branching states */
set < address > good ;
bfs = { } ;
auto visit = [ & ] ( address a ) { if ( good . count ( a ) ) return ; good . insert ( a ) ; bfs . push_back ( a ) ; } ;
for ( auto & a : nonlooping_earlier_states ) if ( isize ( a . second ) > 1 ) visit ( a . first ) ;
for ( int i = 0 ; i < isize ( bfs ) ; i + + ) {
address last = bfs [ i ] ;
int state = last . second ;
int fv = last . first ;
for ( int d = 0 ; d < childpos [ state + 1 ] - childpos [ state ] ; d + + ) {
int nstate = children [ childpos [ state ] + d ] ;
if ( nstate < - 1 ) nstate + = ( 1 < < 16 ) ;
if ( nstate > = 0 ) {
address next = { connection ( fv , d ) , nstate } ;
if ( ! nles . count ( next ) ) continue ;
visit ( next ) ;
}
}
}
set < address > bad ;
for ( auto & a : nonlooping_earlier_states ) if ( ! good . count ( a . first ) ) bad . insert ( a . first ) ;
for ( auto & b : bad ) nonlooping_earlier_states . erase ( b ) ;
int to_cut = 0 ;
for ( auto & a : nonlooping_earlier_states ) {
set < address > goods ;
for ( auto & b : a . second ) if ( good . count ( b ) ) goods . insert ( b ) ; else to_cut + + ;
a . second = goods ;
}
println ( hlog , " to_cut = " , to_cut , " from " , isize ( bad ) , " bad cases " ) ;
2021-05-21 23:26:31 +00:00
// just the number of FV's
int pstable = 0 ;
for ( auto & p : nonlooping_earlier_states )
pstable = max ( pstable , p . first . first + 1 ) ;
println ( hlog , " pstable size = " , pstable , " (states: " , qstate , " ) " ) ;
possible_states . resize ( pstable ) ;
2020-01-29 18:23:31 +00:00
for ( auto & p : nonlooping_earlier_states )
possible_states [ p . first . first ] . push_back ( p . first . second ) ;
2020-01-28 09:35:41 +00:00
}
2022-07-13 16:51:31 +00:00
bool ruleset_link_alt ( heptagon * h , heptagon * alt , hstate firststate , int dir ) {
alt - > fieldval = h - > fieldval ;
if ( firststate = = hsOrigin ) {
2022-07-13 17:33:00 +00:00
alt - > fiftyval = root [ alt - > fieldval % isize ( root ) ] ;
2022-07-13 16:51:31 +00:00
return true ;
}
vector < int > & choices = possible_states [ alt - > fieldval ] ;
vector < int > choices2 ;
for ( auto c : choices ) {
bool ok = true ;
for ( int d = 0 ; d < childpos [ c + 1 ] - childpos [ c ] ; d + + )
if ( h - > cmove ( d ) - > distance < h - > distance )
if ( children [ childpos [ c ] + d ] = = - 1 )
ok = false ;
if ( ok ) choices2 . push_back ( c ) ;
}
alt - > fiftyval = hrand_elt ( choices2 , - 1 ) ;
return alt - > fiftyval ! = - 1 ;
}
2022-07-13 15:34:29 +00:00
} ;
struct hrmap_h3_rule : hrmap_h3_abstract , ruleset {
heptagon * origin ;
reg3 : : hrmap_quotient3 * emerald_map ;
hrmap_quotient3 * qmap ( ) override { return quotient_map ; }
hrmap_h3_rule ( ) {
2020-01-28 09:35:41 +00:00
2021-05-20 21:14:00 +00:00
load_ruleset ( get_rule_filename ( ) ) ;
2022-07-13 16:51:31 +00:00
quotient_map = gen_quotient_map ( is_minimized ( ) , fp ) ;
find_mappings ( ) ;
2020-01-26 00:23:10 +00:00
2021-07-04 08:36:16 +00:00
origin = init_heptagon ( S7 ) ;
2020-01-26 00:23:10 +00:00
heptagon & h = * origin ;
h . s = hsOrigin ;
2020-01-28 10:58:34 +00:00
h . fiftyval = root [ 0 ] ;
2021-07-09 08:26:26 +00:00
if ( PURE ) h . c7 = newCell ( S7 , origin ) ;
2020-01-26 00:23:10 +00:00
2022-07-11 14:04:07 +00:00
emerald_map = gen_quotient_map ( false , currfp ) ;
2022-07-13 16:51:31 +00:00
2020-01-28 14:17:33 +00:00
h . emeraldval = 0 ;
2020-01-28 09:35:41 +00:00
2021-07-09 08:26:26 +00:00
if ( ! PURE ) get_cell_at ( origin , 0 ) ;
2020-01-26 00:23:10 +00:00
}
2022-07-13 16:51:31 +00:00
int connection ( int fv , int d ) override {
return qmap ( ) - > allh [ fv ] - > move ( d ) - > fieldval ;
}
2020-01-26 00:23:10 +00:00
heptagon * getOrigin ( ) override {
return origin ;
}
# define DEB 0
heptagon * counterpart ( heptagon * h ) {
return quotient_map - > allh [ h - > fieldval ] ;
}
2020-01-28 14:17:33 +00:00
2020-01-28 18:47:41 +00:00
vector < short > evmemo ;
2020-01-28 14:17:33 +00:00
void find_emeraldval ( heptagon * target , heptagon * parent , int d ) {
2020-05-31 15:12:45 +00:00
generate_cellrotations ( ) ;
2020-01-28 14:17:33 +00:00
auto & cr = cgi . cellrotations ;
2020-01-28 18:47:41 +00:00
if ( evmemo . empty ( ) ) {
println ( hlog , " starting " ) ;
map < int , int > matrix_hashtable ;
auto matrix_hash = [ ] ( const transmatrix & M ) {
return bucketer ( M [ 0 ] [ 0 ] )
+ bucketer ( M [ 0 ] [ 1 ] ) * 71
+ bucketer ( M [ 0 ] [ 2 ] ) * 113
+ bucketer ( M [ 1 ] [ 0 ] ) * 1301
+ bucketer ( M [ 1 ] [ 1 ] ) * 1703
+ bucketer ( M [ 1 ] [ 2 ] ) * 17031
+ bucketer ( M [ 2 ] [ 2 ] ) * 2307
+ bucketer ( M [ 2 ] [ 0 ] ) * 2311
+ bucketer ( M [ 2 ] [ 1 ] ) * 10311 ;
} ;
for ( int i = 0 ; i < isize ( cr ) ; i + + ) matrix_hashtable [ matrix_hash ( cr [ i ] . M ) ] = cr [ i ] . inverse_id ;
println ( hlog , " ids size = " , isize ( matrix_hashtable ) ) ;
2020-01-28 14:17:33 +00:00
2020-01-28 18:47:41 +00:00
for ( int eid = 0 ; eid < isize ( emerald_map - > allh ) ; eid + + )
for ( int k0 = 0 ; k0 < isize ( cr ) ; k0 + + )
for ( int fv = 0 ; fv < isize ( quotient_map - > allh ) ; fv + + ) {
for ( int d = 0 ; d < S7 ; d + + ) {
int ed = cr [ k0 ] . mapping [ d ] ;
auto cpart = emerald_map - > allh [ eid ] ;
int eid1 = emerald_map - > allh [ eid ] - > move ( ed ) - > fieldval ;
const transmatrix & X = cr [ cr [ k0 ] . inverse_id ] . M ;
transmatrix U = quotient_map - > iadj ( quotient_map - > allh [ fv ] , d ) * X * emerald_map - > adj ( cpart , ed ) ;
int k1 = matrix_hashtable [ matrix_hash ( U ) ] ;
/* for(int ik1=0; ik1<isize(cr); ik1++) {
auto & mX1 = cr [ ik1 ] . M ;
if ( eqmatrix ( mX1 , U ) ) k1 = cr [ ik1 ] . inverse_id ;
} */
evmemo . push_back ( eid1 * isize ( cr ) + k1 ) ;
}
2020-01-28 14:17:33 +00:00
}
2020-01-28 18:47:41 +00:00
println ( hlog , " generated " , isize ( evmemo ) ) ;
2020-01-28 14:17:33 +00:00
}
2020-01-28 18:47:41 +00:00
int memo_id = parent - > emeraldval ;
memo_id = memo_id * isize ( quotient_map - > allh ) + parent - > fieldval ;
memo_id = memo_id * S7 + d ;
target - > emeraldval = evmemo [ memo_id ] ;
target - > zebraval = emerald_map - > allh [ target - > emeraldval / isize ( cr ) ] - > zebraval ;
2020-01-28 14:17:33 +00:00
}
2020-01-26 00:23:10 +00:00
heptagon * create_step ( heptagon * parent , int d ) override {
int id = parent - > fiftyval ;
2021-05-21 23:25:41 +00:00
if ( id < 0 ) id + = ( 1 < < 16 ) ;
2020-01-26 00:23:10 +00:00
auto cp = counterpart ( parent ) ;
int d2 = cp - > c . spin ( d ) ;
int fv = cp - > c . move ( d ) - > fieldval ;
// indenter ind(2);
heptagon * res = nullptr ;
int id1 = children [ S7 * id + d ] ;
int pos = otherpos [ S7 * id + d ] ;
2021-05-21 23:25:41 +00:00
if ( id1 < - 1 ) id1 + = ( 1 < < 16 ) ;
2020-07-04 11:13:37 +00:00
if ( id1 = = - 1 & & false ) {
int kk = pos ;
string s ;
while ( other [ kk ] ! = ' , ' ) s + = other [ kk + + ] ;
println ( hlog , " id= " , id , " d= " , d , " d2= " , d2 , " id1= " , id1 , " pos= " , pos , " s = " , s ) ;
}
2020-01-26 00:23:10 +00:00
if ( id1 ! = - 1 ) {
2021-07-04 08:36:16 +00:00
res = init_heptagon ( S7 ) ;
2021-07-09 08:26:26 +00:00
if ( PURE & & parent - > c7 )
2020-01-26 00:23:10 +00:00
res - > c7 = newCell ( S7 , res ) ;
res - > fieldval = fv ;
res - > distance = parent - > distance + 1 ;
2020-01-28 14:17:33 +00:00
res - > fiftyval = id1 ;
find_emeraldval ( res , parent , d ) ;
2020-01-26 00:23:10 +00:00
// res->c.connect(d2, parent, d, false);
}
else if ( other [ pos ] = = ( ' A ' + d ) & & other [ pos + 1 ] = = ' , ' ) {
2021-07-04 08:36:16 +00:00
res = init_heptagon ( S7 ) ;
2020-01-26 00:23:10 +00:00
res - > alt = parent - > alt ;
res - > fieldval = fv ;
res - > distance = parent - > distance - 1 ;
vector < int > possible ;
2020-01-29 17:20:14 +00:00
int pfv = parent - > fieldval ;
2020-02-14 18:12:04 +00:00
for ( auto s : nonlooping_earlier_states [ address { pfv , id } ] ) possible . push_back ( s . second ) ;
2020-01-26 00:23:10 +00:00
id1 = hrand_elt ( possible , 0 ) ;
res - > fiftyval = id1 ;
2020-01-28 14:17:33 +00:00
find_emeraldval ( res , parent , d ) ;
2020-01-26 00:23:10 +00:00
}
else {
heptagon * at = parent ;
while ( other [ pos ] ! = ' , ' ) {
int dir = ( other [ pos + + ] & 31 ) - 1 ;
// println(hlog, "from ", at, " go dir ", dir);
at = at - > cmove ( dir ) ;
}
res = at ;
}
2021-03-24 19:25:44 +00:00
if ( ! res ) throw hr_exception ( " res missing " ) ;
2020-01-26 00:23:10 +00:00
if ( res - > move ( d2 ) ) println ( hlog , " res conflict " ) ;
res - > c . connect ( d2 , parent , d , false ) ;
return res ;
}
2021-07-06 23:48:20 +00:00
~ hrmap_h3_rule ( ) {
2020-01-26 00:23:10 +00:00
if ( quotient_map ) delete quotient_map ;
clearfrom ( origin ) ;
}
transmatrix adj ( heptagon * h , int d ) override {
return quotient_map - > adj ( h , d ) ;
}
2021-07-12 13:20:04 +00:00
transmatrix relative_matrixh ( heptagon * h2 , heptagon * h1 , const hyperpoint & hint ) override {
2020-01-28 10:22:49 +00:00
return relative_matrix_recursive ( h2 , h1 ) ;
2020-01-26 00:23:10 +00:00
}
2022-07-13 16:51:31 +00:00
virtual bool link_alt ( heptagon * h , heptagon * alt , hstate firststate , int dir ) override {
return ruleset_link_alt ( h , alt , firststate , dir ) ;
}
2020-01-26 00:23:10 +00:00
} ;
2022-07-13 17:30:36 +00:00
int lev ;
2022-07-13 18:59:11 +00:00
int err_on = 500 ;
2022-07-13 17:30:36 +00:00
struct hrmap_h3_subrule : hrmap , ruleset {
heptagon * origin ;
hrmap_quotient3 * quotient_map ;
hrmap_quotient3 * qmap ( ) { return quotient_map ; }
int connection ( int fv , int d ) override {
return quotient_map - > local_id [ quotient_map - > acells [ fv ] - > move ( d ) ] . first ;
}
hrmap_h3_subrule ( ) {
println ( hlog , " loading a subrule ruleset " ) ;
load_ruleset_new ( get_rule_filename ( ) ) ;
quotient_map = gen_quotient_map ( is_minimized ( ) , fp ) ;
int t = quotient_map - > acells [ 0 ] - > type ;
find_mappings ( ) ;
origin = init_heptagon ( t ) ;
heptagon & h = * origin ;
h . s = hsOrigin ;
h . fieldval = 0 ;
h . fiftyval = root [ 0 ] ;
h . c7 = newCell ( t , origin ) ;
}
heptagon * getOrigin ( ) override {
return origin ;
}
heptagon * create_step ( heptagon * parent , int d ) override {
dynamicval < int > rl ( lev , lev + 1 ) ;
2022-07-13 18:59:11 +00:00
if ( lev > err_on ) println ( hlog , " create_step called for " , tie ( parent , d ) , " in distance " , parent - > distance ) ;
indenter ind ( lev > err_on ? 2 : 0 ) ;
2022-07-13 17:30:36 +00:00
int id = parent - > fiftyval ;
if ( id < 0 ) id + = ( 1 < < 16 ) ;
2022-07-13 18:59:11 +00:00
if ( lev > err_on ) throw hr_exception ( " create_step deep recursion " ) ;
2022-07-13 17:30:36 +00:00
int qid = parent - > fieldval ;
int d2 = quotient_map - > acells [ qid ] - > c . spin ( d ) ;
int qid2 = quotient_map - > local_id [ quotient_map - > acells [ qid ] - > move ( d ) ] . first ;
if ( lev > 10 ) println ( hlog , tie ( id , qid , d2 , qid2 ) ) ;
heptagon * res = nullptr ;
int id1 = children [ childpos [ id ] + d ] ;
int pos = otherpos [ childpos [ id ] + d ] ;
if ( id1 < - 1 ) id1 + = ( 1 < < 16 ) ;
if ( id1 ! = - 1 ) {
int t = childpos [ id1 + 1 ] - childpos [ id1 ] ;
res = init_heptagon ( t ) ;
res - > c7 = newCell ( t , res ) ;
res - > fieldval = qid2 ;
res - > distance = parent - > distance + 1 ;
res - > fiftyval = id1 ;
}
else if ( other [ pos ] = = ( ' A ' + d ) & & other [ pos + 1 ] = = ' , ' ) {
vector < int > possible ;
for ( auto s : nonlooping_earlier_states [ address { qid , id } ] ) possible . push_back ( s . second ) ;
if ( possible . empty ( ) ) throw hr_exception ( " impossible " ) ;
id1 = hrand_elt ( possible , 0 ) ;
int t = childpos [ id1 + 1 ] - childpos [ id1 ] ;
res = init_heptagon ( t ) ;
res - > alt = parent - > alt ;
res - > fieldval = qid2 ;
res - > distance = parent - > distance - 1 ;
res - > fiftyval = id1 ;
}
else {
heptagon * at = parent ;
while ( other [ pos ] ! = ' , ' ) {
2022-07-13 18:59:20 +00:00
int dir = other [ pos + + ] - ' a ' ;
2022-07-13 17:30:36 +00:00
at = at - > cmove ( dir ) ;
}
res = at ;
}
if ( ! res ) throw hr_exception ( " res missing " ) ;
if ( res - > move ( d2 ) ) println ( hlog , " res conflict: " , heptspin ( res , d2 ) , " already connected to " , heptspin ( res , d2 ) + wstep , " and should be connected to " , heptspin ( parent , d ) ) ;
res - > c . connect ( d2 , parent , d , false ) ;
return res ;
}
~ hrmap_h3_subrule ( ) {
if ( quotient_map ) delete quotient_map ;
clearfrom ( origin ) ;
}
transmatrix adj ( heptagon * h , int d ) override {
return quotient_map - > adj ( quotient_map - > acells [ h - > fieldval ] , d ) ;
}
transmatrix relative_matrixh ( heptagon * h2 , heptagon * h1 , const hyperpoint & hint ) override {
return relative_matrix_recursive ( h2 , h1 ) ;
}
int shvid ( cell * c ) override {
return quotient_map - > shvid ( quotient_map - > acells [ c - > master - > fieldval ] ) ;
}
int wall_offset ( cell * c ) override {
return quotient_map - > wall_offset ( quotient_map - > acells [ c - > master - > fieldval ] ) ;
}
subcellshape & get_cellshape ( cell * c ) override {
return quotient_map - > get_cellshape ( quotient_map - > acells [ c - > master - > fieldval ] ) ;
}
transmatrix ray_iadj ( cell * c , int i ) override {
return quotient_map - > ray_iadj ( quotient_map - > acells [ c - > master - > fieldval ] , i ) ;
}
cellwalker strafe ( cellwalker cw , int j ) override {
int aid = cw . at - > master - > fieldval ;
auto ress = quotient_map - > strafe ( cellwalker ( quotient_map - > acells [ aid ] , cw . spin ) , j ) ;
return cellwalker ( cw . at - > cmove ( j ) , ress . spin ) ;
}
bool link_alt ( heptagon * h , heptagon * alt , hstate firststate , int dir ) override {
return ruleset_link_alt ( h , alt , firststate , dir ) ;
}
} ;
2021-07-06 23:48:20 +00:00
struct hrmap_h3_rule_alt : hrmap {
2020-01-26 00:23:10 +00:00
heptagon * origin ;
2021-07-06 23:48:20 +00:00
hrmap_h3_rule_alt ( heptagon * o ) {
2020-01-26 00:23:10 +00:00
origin = o ;
}
} ;
EX hrmap * new_alt_map ( heptagon * o ) {
2022-07-13 15:34:29 +00:00
println ( hlog , " new_alt_map called " ) ;
2021-07-06 23:48:20 +00:00
return new hrmap_h3_rule_alt ( o ) ;
2020-01-26 00:23:10 +00:00
}
2020-01-28 09:35:41 +00:00
EX bool reg3_rule_available = true ;
2021-05-20 21:14:00 +00:00
EX string other_rule = " " ;
2022-07-11 14:04:07 +00:00
EX bool is_minimized ( ) {
return geometry = = gSpace535 ;
}
2021-05-20 21:14:00 +00:00
EX string get_rule_filename ( ) {
if ( other_rule ! = " " ) return other_rule ;
switch ( geometry ) {
case gSpace336 : return " honeycomb-rules-336.dat " ;
case gSpace344 : return " honeycomb-rules-344.dat " ;
2022-07-12 10:28:05 +00:00
case gSpace345 : return " honeycomb-rules-345.dat " ;
2021-05-20 21:14:00 +00:00
case gSpace353 : return " honeycomb-rules-353.dat " ;
case gSpace354 : return " honeycomb-rules-354.dat " ;
2022-07-12 10:28:05 +00:00
case gSpace355 : return " honeycomb-rules-355.dat " ;
2021-05-20 21:14:00 +00:00
case gSpace435 : return " honeycomb-rules-435.dat " ;
case gSpace436 : return " honeycomb-rules-436.dat " ;
case gSpace534 : return " honeycomb-rules-534.dat " ;
case gSpace535 : return " honeycomb-rules-535.dat " ;
case gSpace536 : return " honeycomb-rules-536.dat " ;
default : return " " ;
}
}
2020-01-28 09:35:41 +00:00
EX bool in_rule ( ) {
2021-05-20 21:14:00 +00:00
return reg3_rule_available & & get_rule_filename ( ) ! = " " ;
2020-01-26 00:23:10 +00:00
}
2020-07-04 23:02:15 +00:00
2022-07-13 17:30:36 +00:00
ruleset & get_ruleset ( ) {
if ( subrule ) return * ( ( hrmap_h3_subrule * ) currentmap ) ;
if ( in_rule ( ) ) return * ( ( hrmap_h3_rule * ) currentmap ) ;
throw hr_exception ( " get_ruleset called but not in rule " ) ;
}
2020-07-04 23:02:15 +00:00
EX int rule_get_root ( int i ) {
2022-07-13 17:30:36 +00:00
return get_ruleset ( ) . root [ i ] ;
2020-07-04 23:02:15 +00:00
}
EX const vector < short > & rule_get_children ( ) {
2022-07-13 17:30:36 +00:00
return get_ruleset ( ) . children ;
}
EX const vector < int > & rule_get_childpos ( ) {
return get_ruleset ( ) . childpos ;
2020-07-04 23:02:15 +00:00
}
2019-08-09 20:37:11 +00:00
EX hrmap * new_map ( ) {
2020-01-06 19:53:09 +00:00
if ( geometry = = gSeifertCover ) return new seifert_weber : : hrmap_seifert_cover ;
2020-01-06 20:24:21 +00:00
if ( geometry = = gSeifertWeber ) return new seifert_weber : : hrmap_singlecell ( 108 * degree ) ;
if ( geometry = = gHomologySphere ) return new seifert_weber : : hrmap_singlecell ( 36 * degree ) ;
2020-01-26 00:20:42 +00:00
if ( quotient & & ! sphere ) return new hrmap_field3 ( & currfp ) ;
2022-07-13 17:30:36 +00:00
if ( subrule ) return new hrmap_h3_subrule ;
2021-07-06 23:48:20 +00:00
if ( in_rule ( ) ) return new hrmap_h3_rule ;
if ( sphere ) return new hrmap_sphere3 ;
return new hrmap_h3 ;
2019-03-02 23:43:31 +00:00
}
2021-07-06 23:48:20 +00:00
hrmap_h3 * hypmap ( ) {
return ( ( hrmap_h3 * ) currentmap ) ;
2019-03-02 23:43:31 +00:00
}
2020-01-28 10:58:34 +00:00
EX int quotient_count ( ) {
2021-07-06 23:48:20 +00:00
return isize ( hypmap ( ) - > quotient_map - > allh ) ;
2020-01-28 10:58:34 +00:00
}
2022-07-11 15:32:27 +00:00
EX int quotient_count_sub ( ) {
return isize ( hypmap ( ) - > quotient_map - > acells ) ;
}
2020-03-06 01:36:11 +00:00
/** This is a generalization of hyperbolic_celldistance in expansion.cpp to three dimensions.
It still assumes that there are at most 4 cells around every edge , and that distances from
the origin are known , so it works only in { 5 , 3 , 4 } .
*/
int celldistance_534 ( cell * c1 , cell * c2 ) {
int d1 = celldist ( c1 ) ;
int d2 = celldist ( c2 ) ;
vector < cell * > s1 = { c1 } ;
vector < cell * > s2 = { c2 } ;
int best = 99999999 ;
int d0 = 0 ;
auto go_nearer = [ & ] ( vector < cell * > & v , int & d ) {
vector < cell * > w ;
for ( cell * c : v )
forCellEx ( c1 , c )
if ( celldist ( c1 ) < d )
w . push_back ( c1 ) ;
sort ( w . begin ( ) , w . end ( ) ) ;
d - - ; d0 + + ;
auto last = std : : unique ( w . begin ( ) , w . end ( ) ) ;
w . erase ( last , w . end ( ) ) ;
v = w ;
} ;
while ( d0 < best ) {
for ( cell * a1 : s1 ) for ( cell * a2 : s2 ) {
if ( a1 = = a2 ) best = min ( best , d0 ) ;
else if ( isNeighbor ( a1 , a2 ) ) best = min ( best , d0 + 1 ) ;
}
if ( d1 = = 0 & & d2 = = 0 ) break ;
if ( d1 > = d2 ) go_nearer ( s1 , d1 ) ;
if ( d1 < d2 ) go_nearer ( s2 , d2 ) ;
}
return best ;
}
2019-08-09 20:37:11 +00:00
EX int celldistance ( cell * c1 , cell * c2 ) {
2019-03-02 23:43:31 +00:00
if ( c1 = = c2 ) return 0 ;
2019-03-09 00:00:46 +00:00
if ( c1 = = currentmap - > gamestart ( ) ) return c2 - > master - > distance ;
if ( c2 = = currentmap - > gamestart ( ) ) return c1 - > master - > distance ;
2020-03-06 01:36:11 +00:00
2021-07-09 08:26:26 +00:00
if ( geometry = = gSpace534 & & PURE ) return celldistance_534 ( c1 , c2 ) ;
2019-03-04 17:03:16 +00:00
2021-07-06 23:48:20 +00:00
auto r = hypmap ( ) ;
2019-03-04 17:03:16 +00:00
2019-11-26 23:39:41 +00:00
hyperpoint h = tC0 ( r - > relative_matrix ( c1 - > master , c2 - > master , C0 ) ) ;
2019-03-04 17:03:16 +00:00
int b = bucketer ( h ) ;
2020-04-05 08:53:34 +00:00
if ( cgi . close_distances . count ( b ) ) return cgi . close_distances [ b ] ;
2020-01-28 09:35:41 +00:00
if ( in_rule ( ) )
return clueless_celldistance ( c1 , c2 ) ;
2019-03-04 17:03:16 +00:00
2019-03-02 23:43:31 +00:00
dynamicval < eGeometry > g ( geometry , gBinary3 ) ;
2020-10-15 14:33:52 +00:00
# if CAP_BT
2019-12-14 11:05:01 +00:00
return 20 + bt : : celldistance3 ( r - > reg_gmatrix [ c1 - > master ] . first , r - > reg_gmatrix [ c2 - > master ] . first ) ;
2020-10-15 14:33:52 +00:00
# else
return 20 ;
# endif
2019-03-02 23:43:31 +00:00
}
2019-08-09 20:37:11 +00:00
EX bool pseudohept ( cell * c ) {
2019-03-02 23:43:31 +00:00
if ( sphere ) {
2021-07-06 23:48:20 +00:00
auto m = currentmap ;
hyperpoint h = tC0 ( m - > relative_matrix ( c - > master , m - > getOrigin ( ) , C0 ) ) ;
2019-03-02 23:43:31 +00:00
if ( S7 = = 12 ) {
hyperpoint h1 = cspin ( 0 , 1 , atan2 ( 16 , 69 ) + M_PI / 4 ) * h ;
for ( int i = 0 ; i < 4 ; i + + ) if ( abs ( abs ( h1 [ i ] ) - .5 ) > .01 ) return false ;
return true ;
}
if ( S7 = = 8 )
return h [ 3 ] > = .99 | | h [ 3 ] < = - .99 | | abs ( h [ 3 ] ) < .01 ;
2020-04-05 08:53:34 +00:00
if ( cgi . loop = = 3 & & cgi . face = = 3 & & S7 = = 4 )
2019-03-08 21:38:44 +00:00
return c = = m - > gamestart ( ) ;
2020-04-05 08:53:34 +00:00
if ( cgi . loop = = 4 & & cgi . face = = 3 )
2019-03-02 23:43:31 +00:00
return abs ( h [ 3 ] ) > .9 ;
2020-04-05 08:53:34 +00:00
if ( cgi . loop = = 3 & & cgi . face = = 4 )
2019-03-02 23:43:31 +00:00
return abs ( h [ 3 ] ) > .9 ;
2020-04-05 08:53:34 +00:00
if ( cgi . loop = = 5 & & cgi . face = = 3 )
2019-03-02 23:43:31 +00:00
return abs ( h [ 3 ] ) > .99 | | abs ( h [ 0 ] ) > .99 | | abs ( h [ 1 ] ) > .99 | | abs ( h [ 2 ] ) > .99 ;
}
2021-07-06 23:48:20 +00:00
auto m = hypmap ( ) ;
if ( cgflags & qSINGLE ) return true ;
if ( fake : : in ( ) ) return FPIU ( reg3 : : pseudohept ( c ) ) ;
2019-03-15 11:47:37 +00:00
// chessboard pattern in 534
2019-03-21 18:23:27 +00:00
if ( geometry = = gField534 )
return hr : : celldistance ( c , currentmap - > gamestart ( ) ) & 1 ;
2020-01-06 19:53:09 +00:00
if ( geometry = = gCrystal344 | | geometry = = gCrystal534 | | geometry = = gSeifertCover )
2019-10-12 09:24:29 +00:00
return false ;
2020-01-15 16:58:41 +00:00
if ( quotient ) return false ; /* added */
2021-07-06 23:48:20 +00:00
auto mr = dynamic_cast < hrmap_h3_rule * > ( currentmap ) ;
2020-01-26 00:23:10 +00:00
if ( mr ) {
2020-01-28 12:02:39 +00:00
if ( geometry = = gSpace535 )
return c - > master - > fieldval % 31 = = 0 ;
2020-01-26 00:23:10 +00:00
return c - > master - > fieldval = = 0 ;
}
2022-07-13 17:30:36 +00:00
auto ms = dynamic_cast < hrmap_h3_subrule * > ( currentmap ) ;
if ( ms ) return c - > master - > fieldval = = 0 ;
2020-01-26 00:23:10 +00:00
if ( m & & hyperbolic ) {
2019-03-09 00:00:46 +00:00
heptagon * h = m - > reg_gmatrix [ c - > master ] . first ;
2019-03-02 23:43:31 +00:00
return ( h - > zebraval = = 1 ) & & ( h - > distance & 1 ) ;
}
2020-01-26 00:23:10 +00:00
2019-03-02 23:43:31 +00:00
return false ;
}
2019-10-12 09:22:13 +00:00
EX void generate_cellrotations ( ) {
auto & cr = cgi . cellrotations ;
if ( isize ( cr ) ) return ;
for ( int a = 0 ; a < S7 ; a + + )
for ( int b = 0 ; b < S7 ; b + + )
for ( int c = 0 ; c < S7 ; c + + ) {
2020-04-05 08:53:34 +00:00
transmatrix T = build_matrix ( cgi . adjmoves [ a ] * C0 , cgi . adjmoves [ b ] * C0 , cgi . adjmoves [ c ] * C0 , C0 ) ;
2019-10-12 09:22:13 +00:00
if ( abs ( det ( T ) ) < 0.001 ) continue ;
2020-04-05 08:53:34 +00:00
transmatrix U = build_matrix ( cgi . adjmoves [ 0 ] * C0 , cgi . adjmoves [ 1 ] * C0 , cgi . adjmoves [ 2 ] * C0 , C0 ) ;
2019-10-12 09:22:13 +00:00
transmatrix S = U * inverse ( T ) ;
if ( abs ( det ( S ) - 1 ) > 0.01 ) continue ;
vector < int > perm ( S7 ) ;
for ( int x = 0 ; x < S7 ; x + + ) perm [ x ] = - 1 ;
for ( int x = 0 ; x < S7 ; x + + )
for ( int y = 0 ; y < S7 ; y + + )
2020-04-05 08:53:34 +00:00
if ( hdist ( S * cgi . adjmoves [ x ] * C0 , cgi . adjmoves [ y ] * C0 ) < .1 ) perm [ x ] = y ;
2019-10-12 09:22:13 +00:00
bool bad = false ;
for ( int x = 0 ; x < S7 ; x + + ) if ( perm [ x ] = = - 1 ) bad = true ;
if ( bad ) continue ;
2020-01-28 14:15:35 +00:00
cr . emplace_back ( geometry_information : : cellrotation_t { S , perm , 0 } ) ;
2019-10-12 09:22:13 +00:00
}
2020-01-28 14:15:35 +00:00
int rots = isize ( cr ) ;
for ( int i = 0 ; i < rots ; i + + )
for ( int j = 0 ; j < rots ; j + + )
if ( cr [ i ] . mapping [ cr [ j ] . mapping [ 0 ] ] = = 0 & & cr [ i ] . mapping [ cr [ j ] . mapping [ 1 ] ] = = 1 & & cr [ i ] . mapping [ cr [ j ] . mapping [ 2 ] ] = = 2 )
cr [ i ] . inverse_id = j ;
2019-10-12 09:22:13 +00:00
}
2019-10-12 17:09:53 +00:00
# endif
2019-10-12 09:22:13 +00:00
2019-03-02 23:43:31 +00:00
#if 0
/* More precise, but very slow distance. Not used/optimized for now */
ld adistance ( cell * c ) {
hyperpoint h = tC0 ( regmap ( ) - > reg_gmatrix [ c - > master ] . second ) ;
2019-12-14 11:05:01 +00:00
h = bt : : deparabolic3 ( h ) ;
2019-03-02 23:43:31 +00:00
return regmap ( ) - > reg_gmatrix [ c - > master ] . first - > distance * log ( 2 ) - h [ 0 ] ;
}
Remove USE_UNORDERED_MAP because it has bit-rotted.
Trying to compile with `-DUSE_UNORDERED_MAP` produces lots of compiler errors
like these, because of missing `std::hash` specializations.
Also, `#define unordered_map map` is just evil!
```
./nonisotropic.cpp:875:36: note: in instantiation of template class 'std::__1::unordered_map<hr::nilv::mvec, hr::heptagon *,
std::__1::hash<hr::nilv::mvec>, std::__1::equal_to<hr::nilv::mvec>, std::__1::allocator<std::__1::pair<const hr::nilv::mvec, hr::heptagon
*> > >' requested here
unordered_map<mvec, heptagon*> at;
^
./nonisotropic.cpp:239:58: note: in instantiation of template class 'std::__1::unordered_map<std::__1::pair<hr::heptagon *, hr::heptagon *>,
hr::heptagon *, std::__1::hash<std::__1::pair<hr::heptagon *, hr::heptagon *> >, std::__1::equal_to<std::__1::pair<hr::heptagon *,
hr::heptagon *> >, std::__1::allocator<std::__1::pair<const std::__1::pair<hr::heptagon *, hr::heptagon *>, hr::heptagon *> > >'
requested here
unordered_map<pair<heptagon*, heptagon*>, heptagon*> at;
^
./nonisotropic.cpp:457:49: error: no matching member function for call to 'iadj'
while(h1->distance < h2->distance) back = iadj(h2, down) * back, h2 = h2->cmove(down);
^~~~
cell.cpp:42:15: note: candidate function not viable: no known conversion from 'hr::sn::hrmap_solnih' to 'hr::hrmap' for object argument
transmatrix iadj(heptagon *h, int d) {
^
cell.cpp:41:22: note: candidate function not viable: no known conversion from 'hr::sn::hrmap_solnih' to 'hr::hrmap' for object argument
struct transmatrix iadj(cell *c, int i) { cell *c1 = c->cmove(i); return adj(c1, c->c.spin(i)); }
^
```
2020-09-25 03:15:19 +00:00
map < pair < cell * , cell * > , int > memo ;
2019-03-02 23:43:31 +00:00
bool cdd ;
int celldistance ( cell * c1 , cell * c2 ) {
if ( memo . count ( make_pair ( c1 , c2 ) ) ) return memo [ make_pair ( c1 , c2 ) ] ;
if ( c1 = = c2 ) return 0 ;
vector < cell * > v [ 2 ] ;
v [ 0 ] . push_back ( c1 ) ;
v [ 1 ] . push_back ( c2 ) ;
int steps = 0 ;
map < cell * , int > visited ;
visited [ c1 ] = 1 ;
visited [ c2 ] = 2 ;
while ( true ) {
if ( cdd ) {
println ( hlog , " state " , steps , " / " , isize ( v [ 0 ] ) , " / " , isize ( v [ 1 ] ) ) ;
println ( hlog , " A: " , v [ 0 ] ) ;
println ( hlog , " B: " , v [ 1 ] ) ;
}
for ( int i : { 0 , 1 } ) {
vector < cell * > new_v ;
for ( cell * c : v [ i ] ) forCellCM ( cn , c ) if ( adistance ( cn ) < adistance ( c ) ) {
auto & vi = visited [ cn ] ;
if ( ( vi & 3 ) = = 0 ) {
vi = 4 * ( steps + 1 ) ;
vi | = ( 1 < < i ) ;
new_v . push_back ( cn ) ;
}
else if ( ( vi & 3 ) = = 2 - i ) {
vector < pair < cell * , int > > ca1 , ca2 ;
int b1 = 4 * steps - 4 ;
int b2 = ( ( vi > > 2 ) < < 2 ) - 4 ;
for ( auto p : visited ) {
if ( cdd ) println ( hlog , p ) ;
int ps = p . second & 3 ;
if ( ps = = 1 + i & & p . second > = b1 )
ca1 . emplace_back ( p . first , p . second / 4 ) ;
if ( ps = = 2 - i & & p . second > = b2 & & p . second < = b2 + 8 )
ca2 . emplace_back ( p . first , p . second / 4 ) ;
}
int bound = 1 < < 16 ;
for ( auto p1 : ca1 ) for ( auto p2 : ca2 ) {
hyperpoint h = tC0 ( relative_matrix ( p1 . first - > master , p2 . first - > master ) ) ;
int b = bucketer ( h ) ;
if ( close_distances . count ( b ) ) {
int d = close_distances [ b ] + p1 . second + p2 . second ;
if ( cdd ) println ( hlog , " candidate: close= " , close_distances [ b ] , p1 , p2 , " ; h = " , h ) ;
if ( d < bound ) bound = d ;
}
else if ( cdd ) println ( hlog , " bucket missing " ) ;
}
return memo [ make_pair ( c1 , c2 ) ] = bound ;
return bound ;
}
}
v [ i ] = std : : move ( new_v ) ;
}
steps + + ;
}
}
cellwalker target ;
int tsteps ;
int dist_alt ( cell * c ) {
if ( ! target . at ) {
target = cellwalker ( currentmap - > gamestart ( ) , 0 ) ;
tsteps = 0 ;
for ( int i = 0 ; i < 30 ; i + + ) target + = wstep , target + = rev , tsteps + + ;
}
if ( specialland = = laCamelot ) return reg3 : : celldistance ( c , target . at ) ;
else {
int d = reg3 : : celldistance ( c , target . at ) - tsteps ;
if ( d < 10 ) target + = wstep , target + = rev , tsteps + + ;
return d ;
}
}
# endif
2019-03-10 17:37:09 +00:00
// Construct a cellwalker in direction j from cw.at, such that its direction is as close
// as possible to cw.spin. Assume that j and cw.spin are adjacent
2019-05-06 23:08:49 +00:00
# if MAXMDIM >= 4
2020-01-15 16:58:41 +00:00
EX int matrix_order ( const transmatrix A ) {
transmatrix T = A ;
int res = 1 ;
while ( ! eqmatrix ( T , Id ) ) {
res + + ; T = T * A ;
}
return res ;
}
2020-01-26 00:18:30 +00:00
EX void generate_fulls ( ) {
reg3 : : generate_cellrotations ( ) ;
auto cons = [ & ] ( int i0 , int i1 , int i2 ) {
2020-04-05 08:53:34 +00:00
transmatrix T = build_matrix ( cgi . adjmoves [ 0 ] * C0 , cgi . adjmoves [ 1 ] * C0 , cgi . adjmoves [ 2 ] * C0 , C0 ) ;
transmatrix U = build_matrix ( cgi . adjmoves [ i0 ] * C0 , cgi . adjmoves [ i1 ] * C0 , cgi . adjmoves [ i2 ] * C0 , C0 ) ;
2020-01-26 00:18:30 +00:00
return U * inverse ( T ) ;
} ;
2020-04-05 08:53:34 +00:00
cgi . full_P = cgi . adjmoves [ 0 ] ;
2020-05-26 22:54:15 +00:00
cgi . full_R = S7 = = 8 ? cons ( 1 , 7 , 0 ) : S7 = = 20 ? cons ( 1 , 2 , 6 ) : cons ( 1 , 2 , 0 ) ;
cgi . full_X = S7 = = 8 ? cons ( 1 , 0 , 6 ) : S7 = = 6 ? cons ( 1 , 0 , 5 ) : S7 = = 20 ? cons ( 1 , 0 , 7 ) : cons ( 1 , 0 , cgi . face ) ;
2020-01-26 00:18:30 +00:00
2020-04-05 08:53:34 +00:00
cgi . xp_order = matrix_order ( cgi . full_X * cgi . full_P ) ;
cgi . r_order = matrix_order ( cgi . full_R ) ;
cgi . rx_order = matrix_order ( cgi . full_R * cgi . full_X ) ;
println ( hlog , " orders = " , tie ( cgi . rx_order , cgi . r_order , cgi . xp_order ) ) ;
2020-01-26 00:18:30 +00:00
}
2020-01-15 16:58:41 +00:00
EX void construct_relations ( ) {
2020-04-05 08:53:34 +00:00
auto & rels = cgi . rels ;
if ( ! rels . empty ( ) ) return ;
2020-01-15 16:58:41 +00:00
rels . clear ( ) ;
reg3 : : generate_cellrotations ( ) ;
2020-01-26 00:18:30 +00:00
reg3 : : generate_fulls ( ) ;
2020-01-15 16:58:41 +00:00
vector < transmatrix > all ;
vector < string > formulas ;
formulas . push_back ( " " ) ;
all . push_back ( Id ) ;
2021-07-12 09:07:22 +00:00
auto & faces = cgi . heptshape - > faces ;
hyperpoint v = faces [ 0 ] [ 0 ] ;
2020-01-15 16:58:41 +00:00
auto add = [ & ] ( transmatrix T ) {
for ( int i = 0 ; i < isize ( all ) ; i + + ) if ( eqmatrix ( all [ i ] , T ) ) return i ;
int S = isize ( all ) ;
all . push_back ( T ) ;
return S ;
} ;
2021-07-12 09:07:22 +00:00
println ( hlog , faces ) ;
2020-01-15 16:58:41 +00:00
2021-07-12 09:07:22 +00:00
println ( hlog , " cellshape = " , isize ( faces ) ) ;
2020-01-15 16:58:41 +00:00
bool ok = true ;
int last_i = - 1 ;
2021-07-12 09:07:22 +00:00
for ( auto & v : faces ) for ( hyperpoint h : v ) {
2020-01-15 16:58:41 +00:00
int i = 0 , j = 0 ;
2021-07-12 09:07:22 +00:00
for ( auto & uv : faces ) for ( hyperpoint u : uv ) {
2021-03-25 10:12:58 +00:00
if ( hdist ( h , cgi . full_X * u ) < 5e-2 ) i + + ;
if ( hdist ( h , cgi . full_R * u ) < 5e-2 ) j + + ;
}
2020-01-15 16:58:41 +00:00
if ( last_i = = - 1 ) last_i = i ;
if ( i ! = j | | i ! = last_i ) ok = false ;
}
if ( ! ok ) { println ( hlog , " something wrong " ) ; exit ( 1 ) ; }
add ( Id ) ;
auto work = [ & ] ( transmatrix T , int p , char c ) {
if ( hdist0 ( tC0 ( T ) ) > 5 ) return ;
2021-07-12 09:07:22 +00:00
for ( auto & hv : faces ) for ( hyperpoint h : hv ) if ( hdist ( T * h , v ) < 1e-4 ) goto ok ;
2020-01-15 16:58:41 +00:00
return ;
ok :
int id = add ( T ) ;
// println(hlog, p, " x ", (s0+c), " = ", id);
if ( id > = isize ( formulas ) ) formulas . push_back ( formulas [ p ] + c ) ;
else if ( id = = 0 ) println ( hlog , " reached identity: " , formulas [ p ] + c ) ;
else if ( formulas [ p ] [ 0 ] ! = formulas [ id ] [ 0 ] )
rels . emplace_back ( formulas [ p ] + c , formulas [ id ] ) ;
} ;
for ( int i = 0 ; i < isize ( all ) ; i + + ) {
transmatrix T = all [ i ] ;
2020-04-05 08:53:34 +00:00
work ( T * cgi . full_R , i , ' R ' ) ;
work ( T * cgi . full_X , i , ' X ' ) ;
work ( T * cgi . full_P , i , ' P ' ) ;
2020-01-26 00:18:30 +00:00
}
2020-01-15 16:58:41 +00:00
}
2021-07-09 12:01:55 +00:00
eVariation target_variation ;
flagtype target_coxeter ;
int target_subcube_count ;
EX void edit_variation ( ) {
cmode = sm : : SIDE | sm : : MAYDARK ;
2022-07-05 09:51:06 +00:00
gamescreen ( ) ;
2021-07-09 12:01:55 +00:00
dialog : : init ( XLAT ( " variations " ) ) ;
dialog : : addBoolItem ( XLAT ( " pure " ) , target_variation = = eVariation : : pure , ' p ' ) ;
dialog : : add_action ( [ ] { target_variation = eVariation : : pure ; } ) ;
dialog : : addBoolItem ( XLAT ( " symmetric subdivision " ) , target_variation = = eVariation : : coxeter , ' t ' ) ;
dialog : : add_action ( [ ] { target_variation = eVariation : : coxeter ; } ) ;
if ( S7 = = 6 ) {
dialog : : addBoolItem ( XLAT ( " sub-cubes " ) , target_variation = = eVariation : : subcubes , ' c ' ) ;
dialog : : add_action ( [ ] { target_variation = eVariation : : subcubes ; } ) ;
if ( ! ( cgflags & qIDEAL ) ) {
dialog : : addBoolItem ( XLAT ( " dual sub-cubes " ) , target_variation = = eVariation : : dual_subcubes , ' d ' ) ;
dialog : : add_action ( [ ] { target_variation = eVariation : : dual_subcubes ; } ) ;
dialog : : addBoolItem ( XLAT ( " bitruncated sub-cubes " ) , target_variation = = eVariation : : bch , ' b ' ) ;
dialog : : add_action ( [ ] { target_variation = eVariation : : bch ; } ) ;
}
}
else
dialog : : addInfo ( XLAT ( " note: more choices in cubic honeycombs " ) ) ;
if ( is_subcube_based ( target_variation ) ) {
dialog : : addBreak ( 100 ) ;
dialog : : addSelItem ( XLAT ( " subdivision " ) , its ( target_subcube_count ) , ' z ' ) ;
dialog : : add_action ( [ ] {
dialog : : editNumber ( target_subcube_count , 1 , 8 , 1 , 2 , XLAT ( " subdivision " ) , " " ) ;
dialog : : bound_low ( 1 ) ;
} ) ;
}
if ( target_variation = = eVariation : : coxeter ) {
dialog : : addBreak ( 100 ) ;
dialog : : addBoolItem ( XLAT ( " split by original faces " ) , target_coxeter & cox_othercell , ' f ' ) ;
dialog : : add_action ( [ ] { target_coxeter ^ = cox_othercell ; } ) ;
dialog : : addBoolItem ( XLAT ( " split by vertex axes " ) , target_coxeter & cox_vertices , ' v ' ) ;
dialog : : add_action ( [ ] { target_coxeter ^ = cox_vertices ; } ) ;
dialog : : addBoolItem ( XLAT ( " split by midedges " ) , target_coxeter & cox_midedges , ' m ' ) ;
dialog : : add_action ( [ ] { target_coxeter ^ = cox_midedges ; } ) ;
}
dialog : : addBreak ( 100 ) ;
dialog : : addItem ( XLAT ( " activate " ) , ' x ' ) ;
dialog : : add_action ( [ ] {
stop_game ( ) ;
set_variation ( target_variation ) ;
subcube_count = target_subcube_count ;
coxeter_param = target_coxeter ;
start_game ( ) ;
} ) ;
dialog : : addBack ( ) ;
dialog : : display ( ) ;
}
EX void configure_variation ( ) {
target_variation = variation ;
target_subcube_count = subcube_count ;
target_coxeter = coxeter_param ;
pushScreen ( edit_variation ) ;
}
2019-09-12 22:31:32 +00:00
EX }
2019-05-06 23:08:49 +00:00
# endif
2020-05-22 14:52:46 +00:00
# if MAXMDIM == 3
EX namespace reg3 {
2020-05-22 18:38:13 +00:00
EX bool in ( ) { return false ; }
2020-07-05 12:02:28 +00:00
EX bool in_rule ( ) { return false ; }
2020-05-22 14:52:46 +00:00
EX }
# endif
2019-03-02 23:43:31 +00:00
}