2018-08-17 11:29:00 +00:00
namespace hr {
namespace synt {
int indent ;
struct indenter {
indenter ( ) { indent + = 2 ; }
~ indenter ( ) { indent - = 2 ; }
} ;
void doindent ( ) { fflush ( stdout ) ; for ( int i = 0 ; i < indent ; i + + ) printf ( " " ) ; }
bool do_sdebug = false ;
# define SDEBUG(x) if(do_sdebug) { doindent(); x; fflush(stdout); }
// Marek-snub
vector < int > faces = { 3 , 6 , 6 , 6 } ;
vector < int > adj = { 1 , 0 , 2 , 3 } ;
vector < bool > invert = { false , false , true , false } ;
/*
vector < int > faces = { 3 , 6 , 6 , 6 } ;
vector < int > adj = { 1 , 0 , 2 , 3 } ;
vector < bool > invert = { false , false , false , false } ;
*/
/*
vector < int > faces = { 7 , 6 , 6 } ;
vector < int > adj = { 1 , 0 , 2 } ;
vector < bool > invert = { false , false , false } ;
*/
/*
vector < int > faces = { 8 , 8 , 8 } ;
vector < int > adj = { 0 , 1 , 2 } ;
vector < bool > invert = { false , false , false } ;
*/
int repetition = 1 ;
int N ;
vector < vector < pair < int , int > > > adjacent ;
vector < vector < pair < ld , ld > > > triangles ;
// id of vertex in the syntetic tiling
// odd numbers = reflected tiles
// 0, 2, ..., 2(N-1) = as in the symbol
// 2N = bitruncated tile
2018-08-18 15:46:02 +00:00
map < heptagon * , int > create_order ;
map < heptagon * , transmatrix > syntetic_gmatrix ;
int nextorder = 1 ;
static const int PRUNED = 100 ;
2018-08-17 11:29:00 +00:00
short & id_of ( heptagon * h ) {
return h - > zebraval ;
}
// which index in id_of's neighbor list does h->move[0] have
short & parent_index_of ( heptagon * h ) {
return h - > emeraldval ;
}
// total number of neighbors
int neighbors_of ( heptagon * h ) {
return isize ( triangles [ id_of ( h ) ] ) ;
}
// right_sibling_of(h) has the same distance ('right sibling'), then we have some at smaller or equal distance,
// parents_of(h) has the same distance again ('left sibling'), and then we have vertices at bigger distance,
// who are our 'children' except the rightmost one which is typically a child of the right sibling
short & right_sibling_of ( heptagon * h ) {
return h - > fiftyval ;
}
int parents_of ( heptagon * h ) {
return h - > s ;
}
int children_of ( heptagon * h ) {
return right_sibling_of ( h ) - 1 - parents_of ( h ) ;
}
ld edgelength ;
vector < ld > inradius , circumradius , alphas ;
2018-08-18 15:46:02 +00:00
extern void draw_debug_map ( heptagon * h ) ;
void draw_debug_map_exit ( heptagon * h ) { draw_debug_map ( h ) ; exit ( 1 ) ; }
2018-08-17 11:29:00 +00:00
void prepare ( ) {
/* build the 'adjacent' table */
N = isize ( faces ) ;
adjacent . clear ( ) ;
adjacent . resize ( 2 * N + 2 ) ;
for ( int i = 0 ; i < N ; i + + ) {
for ( int oi = 0 ; oi < 1 ; oi + + ) {
int at = ( i + oi ) % N ;
int inv = oi ;
printf ( " vertex " ) ;
for ( int z = 0 ; z < faces [ i ] ; z + + ) {
printf ( " [%d %d] " , at , inv ) ;
adjacent [ 2 * i + oi ] . emplace_back ( 2 * N + int ( inv ) , inv ? ( 2 * at + 2 * N - 2 ) % ( 2 * N ) : 2 * at ) ;
if ( invert [ at ] ) inv ^ = 1 ;
at = adj [ at ] ;
if ( inv ) at = ( at + 1 ) % N ;
else at = ( at + N - 1 ) % N ;
}
printf ( " -> [%d %d] \n " , at , inv ) ;
if ( faces [ at ] ! = faces [ i ] ) printf ( " error! \n " ) ;
}
}
for ( int i = 0 ; i < N ; i + + ) {
adjacent [ 2 * N ] . emplace_back ( 2 * i , 0 ) ;
int ai = ( i + 1 ) % N ;
adjacent [ 2 * N ] . emplace_back ( 2 * N + int ( invert [ ai ] ) , ( 2 * adj [ ai ] + 2 * N - 1 ) % ( 2 * N ) ) ;
}
for ( int i = 0 ; i < 2 * N + 2 ; i + + ) {
printf ( " prelim adjacent %2d: " , i ) ;
for ( int j = 0 ; j < isize ( adjacent [ i ] ) ; j + + ) {
auto p = adjacent [ i ] [ j ] ;
printf ( " (%d,%d) " , p . first , p . second ) ;
}
printf ( " \n " ) ;
}
for ( int d = 0 ; d < = 2 * N ; d + = 2 ) {
int s = isize ( adjacent [ d ] ) ;
for ( int i = 0 ; i < s ; i + + ) {
auto & orig = adjacent [ d ] [ s - 1 - i ] ;
adjacent [ d + 1 ] . emplace_back ( orig . first ^ 1 , orig . second ) ;
}
}
for ( int d = 0 ; d < 2 * N + 2 ; d + + ) {
int s = isize ( adjacent [ d ] ) ;
for ( int i = 0 ; i < s ; i + + ) {
auto & orig = adjacent [ d ] [ i ] ;
if ( orig . first & 1 ) orig . second = isize ( adjacent [ orig . first ] ) - 1 - orig . second ;
}
}
for ( int i = 0 ; i < 2 * N + 2 ; i + + ) {
printf ( " adjacent %2d: " , i ) ;
for ( int j = 0 ; j < isize ( adjacent [ i ] ) ; j + + ) {
auto p = adjacent [ i ] [ j ] ;
printf ( " (%d,%d) " , p . first , p . second ) ;
auto q = adjacent [ p . first ] [ p . second ] ;
printf ( " <%d,%d> " , q . first , q . second ) ;
if ( isize ( adjacent [ q . first ] ) ! = isize ( adjacent [ i ] ) ) printf ( " {error} " ) ;
}
printf ( " \n " ) ;
}
/* verify all the triangles */
for ( int i = 0 ; i < 2 * N + 2 ; i + + ) {
for ( int j = 0 ; j < isize ( adjacent [ i ] ) ; j + + ) {
int ai = i , aj = j ;
printf ( " triangle " ) ;
for ( int s = 0 ; s < 3 ; s + + ) {
printf ( " [%d %d] " , ai , aj ) ; fflush ( stdout ) ;
tie ( ai , aj ) = adjacent [ ai ] [ aj ] ;
aj + + ; if ( aj > = isize ( adjacent [ ai ] ) ) aj = 0 ;
}
printf ( " -> [%d %d] \n " , ai , aj ) ;
if ( isize ( adjacent [ ai ] ) ! = isize ( adjacent [ i ] ) ) printf ( " error! \n " ) ;
}
}
ld sum = 0 ;
for ( int f : faces ) sum + = ( f - 2. ) / f ;
if ( sum < 1.999999 ) ginf [ gSyntetic ] . cclass = gcSphere ;
else if ( sum > 2.000001 ) ginf [ gSyntetic ] . cclass = gcHyperbolic ;
else ginf [ gSyntetic ] . cclass = gcEuclid ;
printf ( " sum = %lf \n " , double ( sum ) ) ;
dynamicval < eGeometry > dv ( geometry , gSyntetic ) ;
/* compute the geometry */
inradius . resize ( N ) ;
circumradius . resize ( N ) ;
alphas . resize ( N ) ;
ld elmin = 0 , elmax = hyperbolic ? 10 : sphere ? M_PI : 1 ;
for ( int p = 0 ; p < 100 ; p + + ) {
edgelength = ( elmin + elmax ) / 2 ;
ld alpha_total = 0 ;
for ( int i = 0 ; i < N ; i + + ) {
ld crmin = 0 , crmax = sphere ? M_PI : 10 ;
for ( int q = 0 ; q < 100 ; q + + ) {
circumradius [ i ] = ( crmin + crmax ) / 2 ;
hyperpoint p1 = xpush ( circumradius [ i ] ) * C0 ;
hyperpoint p2 = spin ( 2 * M_PI / faces [ i ] ) * p1 ;
inradius [ i ] = hdist0 ( mid ( p1 , p2 ) ) ;
if ( hdist ( p1 , p2 ) > edgelength ) crmax = circumradius [ i ] ;
else crmin = circumradius [ i ] ;
}
hyperpoint h = xpush ( edgelength / 2 ) * spin ( M_PI / 2 ) * xpush ( inradius [ i ] ) * C0 ;
alphas [ i ] = atan2 ( - h [ 1 ] , h [ 0 ] ) ;
alpha_total + = alphas [ i ] ;
}
// printf("el = %lf alpha = %lf\n", double(edgelength), double(alpha_total));
if ( sphere ^ ( alpha_total > M_PI ) ) elmin = edgelength ;
else elmax = edgelength ;
if ( euclid ) break ;
}
printf ( " computed edgelength = %lf \n " , double ( edgelength ) ) ;
triangles . clear ( ) ;
triangles . resize ( 2 * N + 2 ) ;
for ( int i = 0 ; i < N ; i + + ) for ( int j = 0 ; j < 2 ; j + + )
for ( int k = 0 ; k < faces [ i ] ; k + + )
triangles [ 2 * i + j ] . emplace_back ( 2 * M_PI / faces [ i ] , circumradius [ i ] ) ;
for ( int k = 0 ; k < N ; k + + ) {
triangles [ 2 * N ] . emplace_back ( alphas [ k ] , circumradius [ k ] ) ;
triangles [ 2 * N ] . emplace_back ( alphas [ ( k + 1 ) % N ] , edgelength ) ;
triangles [ 2 * N + 1 ] . emplace_back ( alphas [ N - 1 - k ] , edgelength ) ;
triangles [ 2 * N + 1 ] . emplace_back ( alphas [ N - 1 - k ] , circumradius [ N - 1 - k ] ) ;
}
for ( auto & ts : triangles ) {
ld total = 0 ;
for ( auto & t : ts ) tie ( t . first , total ) = make_pair ( total , total + t . first ) ;
// printf("total = %lf\n", double(total));
}
for ( auto & ts : triangles ) {
printf ( " T " ) ;
for ( auto & t : ts ) printf ( " %lf@%lf " , double ( t . first ) , double ( t . second ) ) ;
printf ( " \n " ) ;
}
}
void initialize ( heptagon * h ) {
/* initialize the root */
parent_index_of ( h ) = 0 ;
id_of ( h ) = 0 ;
h - > c7 = newCell ( isize ( adjacent [ 0 ] ) , h ) ;
2018-08-18 15:46:02 +00:00
if ( ! hyperbolic ) syntetic_gmatrix [ h ] = Id ;
2018-08-17 11:29:00 +00:00
if ( sphere ) celllister cl ( h - > c7 , 1000 , 1000000 , NULL ) ;
} ;
void verify_distance_delta ( heptagon * h , int d , int delta ) {
2018-08-17 22:46:45 +00:00
if ( ! h - > move ( d ) ) return ;
if ( h - > move ( d ) - > distance ! = h - > distance + delta ) {
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " ERROR: delta H%d.%d (%d/%d) \n " , create_order [ h ] , d , h - > move ( d ) - > distance , h - > distance + delta ) ; )
2018-08-17 11:29:00 +00:00
// exit(1);
}
}
void debug ( heptagon * h ) {
2018-08-18 15:46:02 +00:00
if ( id_of ( h ) = = PRUNED ) return ;
2018-08-17 11:29:00 +00:00
auto & p = adjacent [ id_of ( h ) ] ;
if ( h - > s = = hsOrigin ) {
for ( int i = 0 ; i < isize ( p ) ; i + + ) verify_distance_delta ( h , i , 1 ) ;
}
else {
int first = h - > s + 1 ;
verify_distance_delta ( h , 0 , - 1 ) ;
verify_distance_delta ( h , first - 2 , - 1 ) ;
verify_distance_delta ( h , first - 1 , 0 ) ;
verify_distance_delta ( h , isize ( p ) - 1 , 0 ) ;
for ( int d = first ; d < isize ( p ) - 1 ; d + + ) verify_distance_delta ( h , d , 1 ) ;
2018-08-17 22:46:45 +00:00
for ( int d = 0 ; d < isize ( p ) ; d + + ) if ( h - > move ( d ) ) {
2018-08-17 11:29:00 +00:00
auto & p = adjacent [ id_of ( h ) ] ;
auto uv = p [ ( parent_index_of ( h ) + d ) % isize ( p ) ] ;
2018-08-17 22:46:45 +00:00
if ( neighbors_of ( h - > move ( d ) ) ! = isize ( adjacent [ uv . first ] ) ) {
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " neighbors mismatch at H%d.%d->H%d: is %d expected %d \n " , create_order [ h ] , d , create_order [ h - > move ( d ) ] , neighbors_of ( h - > move ( d ) ) , isize ( adjacent [ uv . first ] ) ) ; )
draw_debug_map_exit ( h ) ;
}
2018-08-17 11:29:00 +00:00
}
}
}
2018-08-18 15:46:02 +00:00
transmatrix adjcell_matrix ( heptagon * h , int d ) ;
2018-08-17 11:29:00 +00:00
heptagon * build_child ( heptagon * parent , int d , int id , int pindex ) {
indenter ind ;
2018-08-18 15:43:54 +00:00
auto h = buildHeptagon1 ( new heptagon , parent , d , hstate ( 1 ) , 0 ) ;
2018-08-18 15:53:06 +00:00
create_order [ h ] = nextorder + + ;
2018-08-17 11:29:00 +00:00
id_of ( h ) = id ;
parent_index_of ( h ) = pindex ;
int nei = neighbors_of ( h ) ;
right_sibling_of ( h ) = nei - 1 ;
h - > distance = parent - > distance + 1 ;
h - > c7 = newCell ( nei , h ) ;
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " H%d.%d/%d ~ H%d.0/%d (state=1/NEW,id=%d,pindex=%d,distance=%d) \n " , create_order [ parent ] , d , neighbors_of ( parent ) , create_order [ h ] , neighbors_of ( h ) , id , pindex , h - > distance ) ; )
if ( ! hyperbolic ) syntetic_gmatrix [ h ] = syntetic_gmatrix [ parent ] * adjcell_matrix ( parent , d ) ;
else { debug ( h ) ; debug ( parent ) ; }
2018-08-17 11:29:00 +00:00
return h ;
}
void connectHeptagons ( heptagon * h , int i , heptspin hs ) {
2018-08-18 15:46:02 +00:00
if ( id_of ( h ) = = PRUNED ) { h - > move ( i ) = h ; return ; }
if ( id_of ( hs . at ) = = PRUNED ) { hs . at - > move ( i ) = hs . at ; return ; }
2018-08-17 11:29:00 +00:00
indenter ind ;
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " H%d.%d/%d ~ H%d.%d/%d (state=%d,id=%d,pindex=%d,distance=%d) \n " , create_order [ h ] , i , neighbors_of ( h ) , create_order [ hs . at ] , hs . spin , neighbors_of ( hs . at ) ,
2018-08-17 22:46:45 +00:00
hs . at - > s , id_of ( hs . at ) , parent_index_of ( hs . at ) , hs . at - > distance ) ; )
if ( h - > move ( i ) = = hs . at & & h - > c . spin ( i ) = = hs . spin ) {
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " WARNING: already connected \n " ) ; )
return ;
}
2018-08-17 22:46:45 +00:00
if ( h - > move ( i ) ) {
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " ERROR: already connected left to: H%d not H%d \n " , create_order [ h - > move ( i ) ] , create_order [ hs . at ] ) ; )
draw_debug_map_exit ( h ) ;
2018-08-17 11:29:00 +00:00
}
2018-08-17 22:46:45 +00:00
if ( hs . peek ( ) ) {
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " ERROR: already connected right to: H%d not H%d \n " , create_order [ hs . peek ( ) ] , create_order [ h ] ) ; )
draw_debug_map_exit ( h ) ;
2018-08-17 11:29:00 +00:00
// exit(1);
}
2018-08-17 22:46:45 +00:00
h - > c . connect ( i , hs ) ;
2018-08-18 15:46:02 +00:00
if ( hyperbolic ) {
debug ( h ) ;
debug ( hs . at ) ;
}
2018-08-17 11:29:00 +00:00
}
int prune ( heptagon * & h ) {
2018-08-18 15:46:02 +00:00
if ( ! h ) return 0 ;
2018-08-17 11:29:00 +00:00
int result = 1 ;
int n = neighbors_of ( h ) ;
auto h0 = h ;
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " pruning: H%d \n " , create_order [ h0 ] ) ; )
2018-08-17 11:29:00 +00:00
for ( int i = 0 ; i < n ; i + + )
2018-08-17 22:46:45 +00:00
if ( h0 - > move ( i ) ) {
if ( h0 - > c . spin ( i ) = = 0 )
result + = prune ( h0 - > move ( i ) ) ;
2018-08-17 11:29:00 +00:00
else {
2018-08-17 22:46:45 +00:00
h0 - > move ( i ) - > move ( h0 - > c . spin ( i ) ) = NULL ;
h0 - > move ( i ) = NULL ;
2018-08-17 11:29:00 +00:00
}
}
2018-08-18 15:46:02 +00:00
id_of ( h0 ) = PRUNED ;
/*
2018-08-17 11:29:00 +00:00
delete h0 - > c7 ;
delete h0 ;
2018-08-18 15:46:02 +00:00
*/
2018-08-17 11:29:00 +00:00
return result ;
}
2018-08-18 15:46:02 +00:00
void mayprune ( heptagon * hleft , heptagon * hright ) {
if ( children_of ( hleft ) > = 1 & & children_of ( hright ) > = 1 )
if ( hleft - > move ( right_sibling_of ( hleft ) - 1 ) ! = hright - > move ( parents_of ( hright ) + 1 ) ) {
SDEBUG ( printf ( " pruning extra children after contraction \n " ) ; )
prune ( hleft - > move ( right_sibling_of ( hleft ) - 1 ) ) ;
prune ( hright - > move ( parents_of ( hright ) + 1 ) ) ;
}
}
2018-08-17 11:29:00 +00:00
void contract ( heptagon * h ) {
2018-08-18 15:46:02 +00:00
if ( id_of ( h ) = = PRUNED ) return ;
2018-08-17 11:29:00 +00:00
switch ( children_of ( h ) ) {
case 0 : {
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " handling contraction (0) at H%d \n " , create_order [ h ] ) ; )
2018-08-17 11:29:00 +00:00
heptspin right = heptspin ( h , right_sibling_of ( h ) ) + wstep + 1 ;
heptspin left = heptspin ( h , parents_of ( h ) ) + wstep - 1 ;
2018-08-17 22:46:45 +00:00
connectHeptagons ( right . at , right . spin , left ) ;
right . at - > s + + ;
right_sibling_of ( left . at ) - - ;
2018-08-18 15:46:02 +00:00
mayprune ( left . at , right . at ) ;
2018-08-17 22:46:45 +00:00
contract ( right . at ) ;
contract ( left . at ) ;
2018-08-17 11:29:00 +00:00
break ;
}
case - 1 : {
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " handling contraction (-1) at H%d \n " , create_order [ h ] ) ; )
2018-08-17 11:29:00 +00:00
indenter ind2 ;
heptspin hs0 ( h , neighbors_of ( h ) - 1 ) ;
heptspin hs = hs0 ;
hs = hs + 1 + wstep + 1 ;
2018-08-17 22:46:45 +00:00
while ( hs . spin = = neighbors_of ( hs . at ) - 1 ) {
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " hsr at H%d.%d/%d (%d parents) \n " , create_order [ hs . at ] , hs . spin , neighbors_of ( hs . at ) , parents_of ( hs . at ) ) ; )
2018-08-17 11:29:00 +00:00
hs = hs + wstep + 1 ;
}
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " hsr at H%d.%d/%d (%d parents) \n " , create_order [ hs . at ] , hs . spin , neighbors_of ( hs . at ) , parents_of ( hs . at ) ) ; )
2018-08-17 11:29:00 +00:00
heptspin correct = hs + wstep ;
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " correct is: H%d.%d/%d (%d parents) \n " , create_order [ correct . at ] , correct . spin , neighbors_of ( correct . at ) , parents_of ( correct . at ) ) ; )
2018-08-17 11:29:00 +00:00
heptspin hsl = hs0 ;
2018-08-17 22:46:45 +00:00
correct = correct + 1 ; correct . at - > s + + ;
connectHeptagons ( hsl . at , hsl . spin , correct ) ;
2018-08-17 11:29:00 +00:00
hsl = hsl - 1 + wstep - 1 ;
while ( true ) {
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " hsl at %d.%d/%d (%d parents) \n " , create_order [ hsl . at ] , hsl . spin , neighbors_of ( hsl . at ) , parents_of ( hsl . at ) ) ; )
2018-08-17 22:46:45 +00:00
if ( hsl . spin = = parents_of ( hsl . at ) ) {
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " go left \n " ) )
hsl = hsl + wstep - 1 ;
}
2018-08-17 22:46:45 +00:00
else if ( hsl . peek ( ) & & hsl . peek ( ) ! = correct . at ) {
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " prune \n " ) ; )
2018-08-17 22:46:45 +00:00
if ( neighbors_of ( hsl . peek ( ) ) ! = neighbors_of ( correct . at ) ) {
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " neighbors mismatch while pruning %d -> %d \n " ,
2018-08-17 22:46:45 +00:00
neighbors_of ( hsl . peek ( ) ) ,
neighbors_of ( correct . at )
2018-08-17 11:29:00 +00:00
) ; )
2018-08-18 15:46:02 +00:00
draw_debug_map_exit ( correct . at ) ;
2018-08-17 11:29:00 +00:00
}
2018-08-17 22:46:45 +00:00
prune ( hsl . peek ( ) ) ;
2018-08-17 11:29:00 +00:00
}
2018-08-17 22:46:45 +00:00
else if ( hsl . peek ( ) = = NULL ) {
correct = correct + 1 ; correct . at - > s + + ;
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " connect \n " ) )
2018-08-17 22:46:45 +00:00
connectHeptagons ( hsl . at , hsl . spin , correct ) ;
2018-08-17 11:29:00 +00:00
}
2018-08-17 22:46:45 +00:00
else if ( hsl . spin = = parents_of ( hsl . at ) + 1 ) {
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " single child so go left \n " ) )
hsl = hsl - 1 + wstep - 1 ;
}
else { SDEBUG ( printf ( " ready \n " ) ; ) break ; }
}
2018-08-17 22:46:45 +00:00
contract ( correct . at ) ;
2018-08-17 11:29:00 +00:00
break ;
}
case - 2 : {
SDEBUG ( printf ( " ERROR: contraction (-2) not handled \n " ) ; )
break ;
}
}
2018-08-17 22:46:45 +00:00
if ( ! sphere ) for ( int i = 0 ; i < neighbors_of ( h ) ; i + + ) if ( ! h - > move ( i ) ) {
2018-08-17 11:29:00 +00:00
auto uv = adjacent [ id_of ( h ) ] [ ( parent_index_of ( h ) + i ) % neighbors_of ( h ) ] ;
2018-08-18 15:46:02 +00:00
if ( isize ( adjacent [ uv . first ] ) < 5 & & hyperbolic ) {
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " prebuilding weak neighbor \n " ) )
createStep ( h , i ) ;
}
}
}
void build_siblings ( heptagon * h , int x ) {
for ( int i = right_sibling_of ( h ) ; i < neighbors_of ( h ) ; i + + ) createStep ( h , i ) ;
for ( int i = 0 ; i < = parents_of ( h ) ; i + + ) createStep ( h , i ) ;
}
2018-08-18 15:46:02 +00:00
pair < int , int > & get_adj ( heptagon * h , int cid ) ;
pair < ld , ld > & get_triangle ( heptagon * h , int cid ) ;
2018-08-17 11:29:00 +00:00
void create_adjacent ( heptagon * h , int d ) {
2018-08-18 15:46:02 +00:00
if ( ! hyperbolic ) {
SDEBUG ( printf ( " h=%d dist=%d d=%d/%d s=%d id=%d pindex=%d \n " ,
create_order [ h ] , h - > distance , d , neighbors_of ( h ) , h - > s , id_of ( h ) , parent_index_of ( h ) ) ; )
indenter ind2 ;
auto & t1 = get_triangle ( h , d ) ;
// * spin(-tri[id][pi+i].first) * xpush(t.second) * pispin * spin(tri[id'][p'+d'].first)
transmatrix T = syntetic_gmatrix [ h ] * spin ( - t1 . first ) * xpush ( t1 . second ) ;
for ( auto gm : syntetic_gmatrix ) if ( intval ( gm . second * C0 , T * C0 ) < 1e-6 ) {
SDEBUG ( printf ( " cell found \n " ) ; )
for ( int d2 = 0 ; d2 < gm . first - > c7 - > type ; d2 + + ) {
auto & t2 = get_triangle ( gm . first , d2 ) ;
transmatrix T1 = T * spin ( M_PI + t2 . first ) ;
if ( intval ( T1 * xpush ( 1 ) * C0 , gm . second * xpush ( 1 ) * C0 ) < 1e-6 ) {
connectHeptagons ( h , d , heptspin ( gm . first , d2 ) ) ;
return ;
}
}
SDEBUG ( printf ( " but rotation not found \n " ) ) ;
}
build_child ( h , d , get_adj ( h , d ) . first , get_adj ( h , d ) . second ) ;
return ;
}
if ( id_of ( h ) = = PRUNED ) { h - > move ( d ) = h ; return ; }
if ( indent > = 200 ) draw_debug_map_exit ( h ) ;
2018-08-17 11:29:00 +00:00
indenter ind ;
int nei = neighbors_of ( h ) ;
if ( h - > s = = 0 ) {
auto & p = adjacent [ id_of ( h ) ] ;
for ( int i = 0 ; i < nei ; i + + )
build_child ( h , i , p [ i ] . first , p [ i ] . second ) ;
for ( int i = 0 ; i < nei ; i + + ) {
2018-08-17 22:46:45 +00:00
heptagon * h1 = h - > move ( i ) ;
heptagon * h2 = h - > move ( ( i + nei - 1 ) % nei ) ;
2018-08-17 11:29:00 +00:00
connectHeptagons ( h1 , 1 , heptspin ( h2 , isize ( adjacent [ id_of ( h2 ) ] ) - 1 ) ) ;
}
}
else {
int first = h - > s + 1 ;
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " h=%d dist=%d d=%d/%d s=%d id=%d pindex=%d \n " ,
create_order [ h ] , h - > distance , d , nei , h - > s , id_of ( h ) , parent_index_of ( h ) ) ; )
2018-08-17 11:29:00 +00:00
indenter ind2 ;
// these vertices are not children (or possibly contractions)
if ( d < first | | d > right_sibling_of ( h ) )
connectHeptagons ( h , d , heptspin ( h , d - 1 ) + wstep - 1 + wstep - 1 ) ;
else if ( d = = right_sibling_of ( h ) ) {
connectHeptagons ( h , d , heptspin ( h , 0 ) + wstep + 1 + wstep + 1 ) ;
}
else {
build_siblings ( h , 10 ) ;
build_siblings ( h , - 10 ) ;
2018-08-17 22:46:45 +00:00
if ( h - > move ( d ) ) return ;
2018-08-17 11:29:00 +00:00
heptspin hs ( h , d ) ;
// make sure no contractions on the left
heptspin hsl ( h , d ) ;
int steps = 0 ;
2018-08-17 22:46:45 +00:00
while ( hsl . spin = = parents_of ( hsl . at ) + 1 & & steps < 100 ) {
2018-08-17 11:29:00 +00:00
hsl = hsl - 1 + wstep - 1 ;
steps + + ;
}
if ( steps = = 100 ) {
SDEBUG ( printf ( " generating top \n " ) ; )
2018-08-17 22:46:45 +00:00
auto uv = adjacent [ id_of ( hs . at ) ] [ ( parent_index_of ( hs . at ) + hs . spin ) % neighbors_of ( hs . at ) ] ;
heptagon * newchild = build_child ( hs . at , hs . spin , uv . first , uv . second ) ;
2018-08-17 11:29:00 +00:00
hs = hs - 1 + wstep - 1 ;
2018-08-17 22:46:45 +00:00
while ( hs . at ! = h ) {
2018-08-17 11:29:00 +00:00
newchild - > s + + ;
2018-08-17 22:46:45 +00:00
connectHeptagons ( hs . at , hs . spin , heptspin ( newchild , newchild - > s - 1 ) ) ;
2018-08-17 11:29:00 +00:00
hs = hs - 1 + wstep - 1 ;
}
return ;
}
// while trying to generate the last child, go right
while ( true ) {
2018-08-17 22:46:45 +00:00
if ( h - > move ( d ) ) {
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " solved itself \n " ) ; )
return ;
}
2018-08-18 15:46:02 +00:00
SDEBUG ( printf ( " going right at H%d.%d/%d parents = %d \n " , create_order [ hs . at ] , hs . spin , neighbors_of ( hs . at ) , parents_of ( hs . at ) ) ; )
if ( id_of ( hs . at ) = = PRUNED ) { create_adjacent ( h , d ) ; return ; }
2018-08-17 11:29:00 +00:00
// rightmost child
2018-08-17 22:46:45 +00:00
if ( hs . spin = = right_sibling_of ( hs . at ) - 1 )
2018-08-17 11:29:00 +00:00
hs = hs + 1 + wstep + 1 ;
2018-08-17 22:46:45 +00:00
else if ( children_of ( hs . at ) < = 0 ) {
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " unexpected situation \n " ) ; )
2018-08-18 15:46:02 +00:00
create_adjacent ( h , d ) ;
2018-08-17 11:29:00 +00:00
return ;
}
else break ;
}
2018-08-17 22:46:45 +00:00
auto uv = adjacent [ id_of ( hs . at ) ] [ ( parent_index_of ( hs . at ) + hs . spin ) % neighbors_of ( hs . at ) ] ;
heptagon * newchild = build_child ( hs . at , hs . spin , uv . first , uv . second ) ;
2018-08-17 11:29:00 +00:00
bool add_parent = false ;
while ( true ) {
2018-08-18 15:46:02 +00:00
if ( id_of ( hs . at ) = = PRUNED ) { create_adjacent ( h , d ) ; return ; }
SDEBUG ( printf ( " going left at H%d.%d/%d parents = %d \n " , create_order [ hs . at ] , hs . spin , neighbors_of ( hs . at ) , parents_of ( hs . at ) ) ; )
2018-08-17 11:29:00 +00:00
// add parent
2018-08-17 22:46:45 +00:00
if ( hs . spin > parents_of ( hs . at ) & & add_parent ) {
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " add parent \n " ) ; )
newchild - > s + + ;
2018-08-17 22:46:45 +00:00
connectHeptagons ( hs . at , hs . spin , heptspin ( newchild , newchild - > s - 1 ) ) ;
2018-08-17 11:29:00 +00:00
add_parent = false ;
}
// childless
2018-08-17 22:46:45 +00:00
if ( children_of ( hs . at ) < = 0 ) {
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " unexpected situation v2 \n " ) ; )
2018-08-18 15:46:02 +00:00
create_adjacent ( h , d ) ;
2018-08-17 11:29:00 +00:00
return ;
}
// lefmost child
2018-08-17 22:46:45 +00:00
else if ( hs . spin = = parents_of ( hs . at ) + 1 ) {
2018-08-17 11:29:00 +00:00
SDEBUG ( printf ( " (leftmost child) \n " ) ; )
hs = hs - 1 + wstep - 1 ;
add_parent = true ;
}
// no more parents
else break ;
}
contract ( newchild ) ;
}
}
debug ( h ) ;
}
set < heptagon * > visited ;
queue < pair < heptagon * , transmatrix > > drawqueue ;
void enqueue ( heptagon * h , const transmatrix & T ) {
if ( visited . count ( h ) ) { return ; }
visited . insert ( h ) ;
drawqueue . emplace ( h , T ) ;
}
2018-08-18 15:46:02 +00:00
pair < ld , ld > & get_triangle ( heptagon * h , int cid ) {
return triangles [ id_of ( h ) ] [ ( parent_index_of ( h ) + cid ) % neighbors_of ( h ) ] ;
}
pair < int , int > & get_adj ( heptagon * h , int cid ) {
return adjacent [ id_of ( h ) ] [ ( parent_index_of ( h ) + cid ) % neighbors_of ( h ) ] ;
}
pair < ld , ld > & get_triangle ( const pair < int , int > & p ) {
return triangles [ p . first ] [ p . second ] ;
}
pair < int , int > & get_adj ( const pair < int , int > & p , int delta = 0 ) {
return adjacent [ p . first ] [ ( p . second + delta ) % isize ( adjacent [ p . first ] ) ] ;
}
2018-08-17 11:29:00 +00:00
transmatrix adjcell_matrix ( heptagon * h , int d ) {
2018-08-18 15:46:02 +00:00
auto & t1 = get_triangle ( h , d ) ;
2018-08-17 11:29:00 +00:00
2018-08-17 22:46:45 +00:00
heptagon * h2 = h - > move ( d ) ;
2018-08-17 11:29:00 +00:00
2018-08-17 22:46:45 +00:00
int d2 = h - > c . spin ( d ) ;
2018-08-18 15:46:02 +00:00
auto & t2 = get_triangle ( h2 , d2 ) ;
2018-08-17 11:29:00 +00:00
// * spin(-tri[id][pi+i].first) * xpush(t.second) * pispin * spin(tri[id'][p'+d'].first)
return spin ( - t1 . first ) * xpush ( t1 . second ) * spin ( M_PI + t2 . first ) ;
}
void draw ( ) {
visited . clear ( ) ;
2018-08-17 22:46:45 +00:00
enqueue ( viewctr . at , cview ( ) ) ;
2018-08-17 11:29:00 +00:00
int idx = 0 ;
while ( ! drawqueue . empty ( ) ) {
auto p = drawqueue . front ( ) ;
drawqueue . pop ( ) ;
heptagon * h = p . first ;
transmatrix V = p . second ;
int id = id_of ( h ) ;
int S = isize ( triangles [ id ] ) ;
if ( ! nonbitrunc | | id < 2 * N ) {
if ( ! dodrawcell ( h - > c7 ) ) continue ;
drawcell ( h - > c7 , V , 0 , false ) ;
}
for ( int i = 0 ; i < S ; i + + ) {
2018-08-18 15:46:02 +00:00
h - > cmove ( i ) ;
2018-08-17 22:46:45 +00:00
if ( nonbitrunc & & id > = 2 * N & & h - > move ( i ) & & id_of ( h - > move ( i ) ) > = 2 * N ) continue ;
enqueue ( h - > move ( i ) , V * adjcell_matrix ( h , i ) ) ;
2018-08-17 11:29:00 +00:00
}
idx + + ;
}
}
transmatrix relative_matrix ( heptagon * h2 , heptagon * h1 ) {
if ( gmatrix0 . count ( h2 - > c7 ) & & gmatrix0 . count ( h1 - > c7 ) )
return inverse ( gmatrix0 [ h1 - > c7 ] ) * gmatrix0 [ h2 - > c7 ] ;
transmatrix gm = Id , where = Id ;
while ( h1 ! = h2 ) {
2018-08-17 22:46:45 +00:00
for ( int i = 0 ; i < neighbors_of ( h1 ) ; i + + ) if ( h1 - > move ( i ) = = h2 ) {
2018-08-17 11:29:00 +00:00
return gm * adjcell_matrix ( h1 , i ) * where ;
}
else if ( h1 - > distance > h2 - > distance ) {
gm = gm * adjcell_matrix ( h1 , 0 ) ;
2018-08-17 22:46:45 +00:00
h1 = h1 - > move ( 0 ) ;
2018-08-17 11:29:00 +00:00
}
else {
where = inverse ( adjcell_matrix ( h2 , 0 ) ) * where ;
2018-08-17 22:46:45 +00:00
h2 = h2 - > move ( 0 ) ;
2018-08-17 11:29:00 +00:00
}
}
return gm * where ;
}
int fix ( heptagon * h , int spin ) {
int type = isize ( adjacent [ id_of ( h ) ] ) ;
spin % = type ;
if ( spin < 0 ) spin + = type ;
return spin ;
}
void parse_symbol ( string s ) {
int at = 0 ;
auto peek = [ & ] ( ) { if ( at = = isize ( s ) ) return char ( 0 ) ; else return s [ at ] ; } ;
auto isnumber = [ & ] ( ) { char p = peek ( ) ; return p > = ' 0 ' & & p < = ' 9 ' ; } ;
auto read_number = [ & ] ( ) { int result = 0 ; while ( isnumber ( ) ) result = 10 * result + peek ( ) - ' 0 ' , at + + ; return result ; } ;
faces . clear ( ) ;
while ( true ) {
if ( peek ( ) = = ' ) ' | | peek ( ) = = ' ^ ' | | ( peek ( ) = = ' ( ' & & isize ( faces ) ) | | peek ( ) = = 0 ) break ;
else if ( isnumber ( ) ) faces . push_back ( read_number ( ) ) ;
else at + + ;
}
repetition = 1 ;
N = isize ( faces ) ;
2018-08-18 15:46:02 +00:00
invert . clear ( ) ; invert . resize ( N , true ) ;
2018-08-17 11:29:00 +00:00
adj . clear ( ) ; adj . resize ( N , 0 ) ; for ( int i = 0 ; i < N ; i + + ) adj [ i ] = i ;
while ( peek ( ) ! = 0 ) {
if ( peek ( ) = = ' ^ ' ) at + + , repetition = read_number ( ) ;
else if ( peek ( ) = = ' ( ' ) {
at + + ; int a = read_number ( ) ; while ( ! isnumber ( ) & & ! among ( peek ( ) , ' ( ' , ' [ ' , ' ) ' , ' ] ' , 0 ) ) at + + ;
2018-08-18 15:46:02 +00:00
if ( isnumber ( ) ) { int b = read_number ( ) ; adj [ a ] = b ; adj [ b ] = a ; invert [ a ] = invert [ b ] = false ; }
else { invert [ a ] = false ; }
2018-08-17 11:29:00 +00:00
}
else if ( peek ( ) = = ' [ ' ) {
at + + ; int a = read_number ( ) ; while ( ! isnumber ( ) & & ! among ( peek ( ) , ' ( ' , ' [ ' , ' ) ' , ' ] ' , 0 ) ) at + + ;
if ( isnumber ( ) ) { int b = read_number ( ) ; adj [ a ] = b ; adj [ b ] = a ; invert [ a ] = invert [ b ] = true ; }
else { invert [ a ] = true ; }
}
else at + + ;
}
prepare ( ) ;
}
# if CAP_COMMANDLINE
int readArgs ( ) {
using namespace arg ;
if ( 0 ) ;
else if ( argis ( " -symbol " ) ) {
targetgeometry = gSyntetic ;
if ( targetgeometry ! = geometry )
stop_game_and_switch_mode ( rg : : geometry ) ;
showstartmenu = false ;
shift ( ) ; parse_symbol ( args ( ) ) ;
}
else if ( argis ( " -sd " ) ) do_sdebug = true ;
2018-08-18 15:46:02 +00:00
else if ( argis ( " -sdeb " ) ) { PHASE ( 3 ) ; draw_debug_map ( cwt . at - > master ) ; }
2018-08-17 11:29:00 +00:00
else return 1 ;
return 0 ;
}
# endif
2018-08-18 15:46:02 +00:00
map < heptagon * , transmatrix > debugmap ;
void add_to_debug ( heptagon * h , transmatrix T ) {
debugmap [ h ] = T ;
for ( int i = 0 ; i < neighbors_of ( h ) ; i + + )
if ( h - > move ( i ) & & h - > c . spin ( i ) = = 0 & & h - > move ( i ) - > s ! = hsOrigin )
add_to_debug ( h - > move ( i ) , T * adjcell_matrix ( h , i ) ) ;
}
void draw_debug_map ( heptagon * h ) {
debugmap . clear ( ) ;
while ( h - > s ! = hsOrigin ) h = h - > move ( 0 ) ;
add_to_debug ( h , Id ) ;
svg : : render ( " syntetic-debug.svg " , [ ] ( ) {
ptds . clear ( ) ;
for ( auto p : debugmap ) {
heptagon * h = p . first ;
queuestr ( p . second * C0 , vid . yres / 50 , its ( create_order [ h ] ) + " / " + its ( h - > c7 - > mpdist ) , 0xFF000000 ) ;
for ( int i = 0 ; i < neighbors_of ( h ) ; i + + ) {
if ( h - > move ( i ) )
queueline ( p . second * C0 , debugmap [ h - > move ( i ) ] * C0 ,
i = = parents_of ( h ) ? 0xFF0000FF :
i = = right_sibling_of ( h ) ? 0x800000FF :
i = = 0 ? 0x008000FF :
0x000000FF ) ;
}
}
hr : : drawqueue ( ) ;
} ) ;
exit ( 1 ) ;
}
2018-08-17 11:29:00 +00:00
# if CAP_COMMANDLINE
auto hook =
2018-08-18 15:46:02 +00:00
addHook ( hooks_args , 100 , readArgs ) ;
2018-08-17 11:29:00 +00:00
# endif
2018-08-18 15:46:02 +00:00
2018-08-17 11:29:00 +00:00
}
}