/* See {TriangulatedDodecahedron.h} */ #include /* Last edited on 2007-02-03 23:19:55 by stolfi */ #define TriangulatedDodecahedron_C_COPYRIGHT \ "Copyright © 2000,2007 Universidade Estadual de Campinas (UNICAMP)" #include #include #include #include #include #include #include #include #include FiveByTwoPlaces_t BuildPentaPyramid(void); /* Builds a pentagonal bipyramid as the gluing of five tetrahedra. This procedure is a special case of the procedure MakeBipyramid in the module with the same name. */ TwelveByFivePlaces_t TriangulatedDodecahedron2(void) /* [!!! Return type was {Free_vec_t}.] */ { /* Create the 12 pentagonal pyramids, {ap[0..11]}: */ FiveByTwoPlaces_t ap[12]; int i; for (i = 0; i < 12; i++) { ap[i] = BuildPentaPyramid(); } /* Build the first half-dodecahedron, by gluing the pentagonal pyramids: p[0][0][0] <----> p[1][0][0] p[0][1][0] <----> p[2][0][0] p[0][2][0] <----> p[3][0][0] p[0][3][0] <----> p[4][0][0] p[0][4][0] <----> p[5][0][0] */ for (i = 1; i < 6; i++) { Glue(Clock(ap[0].p[i-1][0]), ap[i].p[0][0], 1, TRUE); } Glue(Clock(ap[ 2].p[1][0]), ap[ 1].p[4][0], 1, TRUE); /* p01-p02 */ Glue(Clock(ap[ 3].p[1][0]), ap[ 2].p[4][0], 1, TRUE); /* p02-p03 */ Glue(Clock(ap[ 4].p[1][0]), ap[ 3].p[4][0], 1, TRUE); /* p03-p04 */ Glue(Clock(ap[ 5].p[1][0]), ap[ 4].p[4][0], 1, TRUE); /* p04-p05 */ Glue(Clock(ap[ 1].p[1][0]), ap[ 5].p[4][0], 1, TRUE); /* p05-p01 */ /* Building the second half-dodecahedron, by gluing the pentagonal pyramids: p[ 6][0][0] <----> p[ 7][0][0] p[ 6][1][0] <----> p[ 8][0][0] p[ 6][2][0] <----> p[ 9][0][0] p[ 6][3][0] <----> p[10][0][0] p[ 6][4][0] <----> p[11][0][0] */ for (i = 7; i < 12; i++) { Glue(Clock(ap[6].p[i-7][0]), ap[i].p[0][0], 1, TRUE); } Glue(Clock(ap[ 8].p[1][0]), ap[ 7].p[4][0], 1, TRUE); /* p08-p07 */ Glue(Clock(ap[ 9].p[1][0]), ap[ 8].p[4][0], 1, TRUE); /* p09-p08 */ Glue(Clock(ap[10].p[1][0]), ap[ 9].p[4][0], 1, TRUE); /* p10-p09 */ Glue(Clock(ap[11].p[1][0]), ap[10].p[4][0], 1, TRUE); /* p11-p10 */ Glue(Clock(ap[ 7].p[1][0]), ap[11].p[4][0], 1, TRUE); /* p07-p11 */ /* Gluing the two half dodecahedra */ Glue(Clock(ap[ 7].p[2][0]), ap[1].p[2][0], 1, TRUE); Glue(Clock(ap[ 7].p[3][0]), ap[5].p[3][0], 1, TRUE); Glue(Clock(ap[ 8].p[2][0]), ap[5].p[2][0], 1, TRUE); Glue(Clock(ap[ 8].p[3][0]), ap[4].p[3][0], 1, TRUE); Glue(Clock(ap[ 9].p[2][0]), ap[4].p[2][0], 1, TRUE); Glue(Clock(ap[ 9].p[3][0]), ap[3].p[3][0], 1, TRUE); Glue(Clock(ap[10].p[2][0]), ap[3].p[2][0], 1, TRUE); Glue(Clock(ap[10].p[3][0]), ap[2].p[3][0], 1, TRUE); Glue(Clock(ap[11].p[2][0]), ap[2].p[2][0], 1, TRUE); Glue(Clock(ap[11].p[3][0]), ap[1].p[3][0], 1, TRUE); TwelveByFivePlaces_t fr; int j, k; for (j = 0; j < 12; j++) { for (k = 0; k < 5; k++) { fr.p[j][k] = ap[j].p[k][1]; } } return fr; } FiveByTwoPlaces_t BuildPentaPyramid(void) { /* Create the five tetrahedra */ EightPlaces_t a[5]; int i, j; for (i = 0; i < 5; i++) { a[i] = MakeTetraTopo(1,1); } /* Glue them together: */ for (i = 0; i < 5; i++) { Glue(Spin(a[i].p[1]), a[(i+1) % 5].p[0], 1, TRUE); } /* Emphasize the original elements: */ SetExWallsOfEdge(a[0].p[1], FALSE); for (i = 0; i < 5; i++) { SetExEdge( a[i].p[1], FALSE); SetExEdge(NextE(a[i].p[1]),FALSE); SetExEdge(PrevE(a[i].p[1]),FALSE); SetExWall( a[i].p[3], FALSE); } SetExNode(a[0].p[1], FALSE); SetExNode(Clock(a[0].p[1]), FALSE); /* Gather the places to be returned: */ FiveByTwoPlaces_t p; for (j = 0; j < 5; j++) { p.p[j][0] = a[j].p[3]; p.p[j][1] = a[j].p[2]; } return p; } typedef struct z4_t { int ix[4]; } z4_t; /* A quadruple of integers. */ TwelveByFivePlaces_t MakeTriangulatedDodecahedron(bool_t original) { uint NP = 60; FourPlaces_t tetra[NP]; z4_t cell4[NP]; Place_t walls[4*NP]; z4_t glues[2*NP]; auto Place_t GlueTetras(uint Ti, uint Tj, uint Ci, uint Cj); /* Glues the tetrahedra {tetra[Ti]} and {tetra[Tj]} through the free walls with cell-relative indices {Ci} and {Cj} respectively. */ auto void SetCornersTetra(uint Ti, z4_t row); /* Sets the labels {row} in the tetrahedron with index {Ti}. */ auto void EffaceNode(uint Ti, uint nn); /* Sets node number {nn} of the tetrahedron with index {Ti} as non-existing.*/ auto void EffaceEdgesOfNode(uint Ti, uint nn); /* Sets all edgess incident on node {nn} as non-existing.*/ auto void EffaceWallsOfNode(uint Ti, uint nn); /* Sets all walls incident on node {nn} as non-existing.*/ auto void SaveFreeCorners(void); /* Saves the free corners on the triangulated dodecahedron, so that the result can be used as a building block to assemble other 3D maps. */ auto bool_t MustBeGlued(Place_t Ti, Place_t Tj); /* Return TRUE if the walls {PWall(Ti)} and {PWall(Tj)} have coherent orientations and must be glued. */ uint count = 1; TwelveByFivePlaces_t dode; /* Create the cells {tetra[0..NP-1]}: */ int i, j, k, l, m; for (i = 0; i < NP; i++) { EightPlaces_t poly = MakeTetraTopo(1,1); for (j = 0; j < 4; j++) { tetra[i].p[j] = poly.p[j]; assert(PposP(tetra[i].p[j]) == NULL); } } /* Set {cell4[i]} to the four indices of corner nodes of {tetra[i]}: */ cell4[ 0] = (z4_t){{100, 500, 0, 1}}; cell4[ 1] = (z4_t){{100, 500, 1, 4}}; cell4[ 2] = (z4_t){{100, 500, 4, 7}}; cell4[ 3] = (z4_t){{100, 500, 7, 2}}; cell4[ 4] = (z4_t){{100, 500, 2, 0}}; cell4[ 5] = (z4_t){{500, 101, 0, 1}}; cell4[ 6] = (z4_t){{500, 101, 1, 5}}; cell4[ 7] = (z4_t){{500, 101, 5, 8}}; cell4[ 8] = (z4_t){{500, 101, 8, 3}}; cell4[ 9] = (z4_t){{500, 101, 3, 0}}; cell4[ 10] = (z4_t){{500, 102, 2, 0}}; cell4[ 11] = (z4_t){{500, 102, 0, 3}}; cell4[ 12] = (z4_t){{500, 102, 3, 9}}; cell4[ 13] = (z4_t){{500, 102, 9, 6}}; cell4[ 14] = (z4_t){{500, 102, 6, 2}}; cell4[ 15] = (z4_t){{103, 500, 6, 2}}; cell4[ 16] = (z4_t){{500, 103, 7, 2}}; cell4[ 17] = (z4_t){{103, 500, 7, 13}}; cell4[ 18] = (z4_t){{103, 500, 13, 12}}; cell4[ 19] = (z4_t){{500, 103, 6, 12}}; cell4[ 20] = (z4_t){{500, 104, 1, 4}}; cell4[ 21] = (z4_t){{500, 104, 4, 10}}; cell4[ 22] = (z4_t){{500, 104, 10, 11}}; cell4[ 23] = (z4_t){{500, 104, 11, 5}}; cell4[ 24] = (z4_t){{500, 104, 5, 1}}; cell4[ 25] = (z4_t){{500, 105, 9, 3}}; cell4[ 26] = (z4_t){{500, 105, 3, 8}}; cell4[ 27] = (z4_t){{500, 105, 8, 14}}; cell4[ 28] = (z4_t){{500, 105, 14, 15}}; cell4[ 29] = (z4_t){{500, 105, 15, 9}}; cell4[ 30] = (z4_t){{500, 106, 12, 6}}; cell4[ 31] = (z4_t){{500, 106, 6, 9}}; cell4[ 32] = (z4_t){{500, 106, 9, 15}}; cell4[ 33] = (z4_t){{500, 106, 15, 18}}; cell4[ 34] = (z4_t){{500, 106, 18, 12}}; cell4[ 35] = (z4_t){{500, 107, 4, 7}}; cell4[ 36] = (z4_t){{500, 107, 7, 13}}; cell4[ 37] = (z4_t){{500, 107, 13, 16}}; cell4[ 38] = (z4_t){{500, 107, 16, 10}}; cell4[ 39] = (z4_t){{500, 107, 10, 4}}; cell4[ 40] = (z4_t){{108, 500, 5, 8}}; cell4[ 41] = (z4_t){{108, 500, 8, 14}}; cell4[ 42] = (z4_t){{108, 500, 14, 17}}; cell4[ 43] = (z4_t){{108, 500, 17, 11}}; cell4[ 44] = (z4_t){{108, 500, 11, 5}}; cell4[ 45] = (z4_t){{109, 500, 18, 12}}; cell4[ 46] = (z4_t){{109, 500, 12, 13}}; cell4[ 47] = (z4_t){{109, 500, 13, 16}}; cell4[ 48] = (z4_t){{109, 500, 16, 19}}; cell4[ 49] = (z4_t){{109, 500, 19, 18}}; cell4[ 50] = (z4_t){{500, 110, 18, 15}}; cell4[ 51] = (z4_t){{500, 110, 15, 14}}; cell4[ 52] = (z4_t){{500, 110, 14, 17}}; cell4[ 53] = (z4_t){{500, 110, 17, 19}}; cell4[ 54] = (z4_t){{500, 110, 19, 18}}; cell4[ 55] = (z4_t){{111, 500, 10, 11}}; cell4[ 56] = (z4_t){{111, 500, 11, 17}}; cell4[ 57] = (z4_t){{111, 500, 17, 19}}; cell4[ 58] = (z4_t){{111, 500, 19, 16}}; cell4[ 59] = (z4_t){{111, 500, 16, 10}}; /* set the labels for each tetrahedra */ for (i = 0; i < NP; i++) { SetCornersTetra(i, cell4[i]); } if (original) { /* Emphasize the original elements */ for (i = 0; i < NP; i++) { EffaceNode(i,500); EffaceEdgesOfNode(i,500); EffaceWallsOfNode(i,500); for (j = 100; j < 112; j++) { EffaceNode(i,j); EffaceEdgesOfNode(i,j); } } } /* Collect the walls of all tetrahedra for gluing: */ for (i = 0; i < NP; i++) { for (k = 0; k < 4; k++) { walls[(4*i)+k] = tetra[i].p[k]; } } /* Figure out which cells must be glued: */ for(k = 0; k < 4*NP; k++) { for (l = k+1; l < 4*NP; l++) { for (m = 0; m < 3; m++) { Place_t e = NextEK(walls[l], m); if (MustBeGlued(walls[k], e)) { uint kc = k % 4; uint kt = k / 4; uint lc = l % 4; uint lt = l / 4; glues[count-1] = (z4_t){{kt, lt, kc, lc}}; count++; } } } } /* Do the automatic gluing of tetrahedra */ for(i = 0; i < 2*NP; i++) { z4_t c = glues[i]; if ((c.ix[0] != 0) || (c.ix[1] != 0) || (c.ix[2] != 0) || (c.ix[3] != 0)) { GlueTetras(c.ix[0],c.ix[1],c.ix[2],c.ix[3]); } } /* Set the origins. */ for (i = 0; i < NP; i++) { for (j = 0; j < 4; j++) { Place_t a = tetra[i].p[j]; Place_t b = NextE(a); Place_t c = PrevE(a); SetOrgAll(a, OrgV(a)); SetOrgAll(b, OrgV(b)); SetOrgAll(c, OrgV(c)); } } SaveFreeCorners(); return dode; /* Implementations of internal procs: */ Place_t GlueTetras(uint Ti, uint Tj, uint Ci, uint Cj) { uint comb = 4*Ci + Cj + 1; switch (comb) { case 1: /* (Ci == 0) && (Cj == 0) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 2: /* (Ci == 0) && (Cj == 1) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 3: /* (Ci == 0) && (Cj == 2) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 4: /* (Ci == 0) && (Cj == 3) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 5: /* (Ci == 1) && (Cj == 0) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 6: /* (Ci == 1) && (Cj == 1) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 7: /* (Ci == 1) && (Cj == 2) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 8: /* (Ci == 1) && (Cj == 3) */ { int Oi = cell4[Ti].ix[0]; int Di = cell4[Ti].ix[1]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 9: /* (Ci == 2) && (Cj == 0) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 10: /* (Ci == 2) && (Cj == 1) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 11: /* (Ci == 2) && (Cj == 2) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 12: /* (Ci == 2) && (Cj == 3) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 13: /* (Ci == 3) && (Cj == 0) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; case 14: /* (Ci == 3) && (Cj == 1) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[1]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 15: /* (Ci == 3) && (Cj == 2) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Oj) && (Di == Dj)) { Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Spin(tetra[Tj].p[Cj]); } } break; case 16: /* (Ci == 3) && (Cj == 3) */ { int Oi = cell4[Ti].ix[2]; int Di = cell4[Ti].ix[3]; int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[3]; if ((Oi == Dj) && (Di == Oj)) { Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1, TRUE); return Clock(tetra[Tj].p[Cj]); } } break; default: assert(FALSE); } return tetra[Ti].p[0]; } void SetCornersTetra(uint Ti, z4_t row) { Node_t a = OrgV(tetra[Ti].p[0]); Node_t b = OrgV(Clock(tetra[Ti].p[0])); Node_t c = OrgV(PrevE(tetra[Ti].p[1])); Node_t d = OrgV(PrevE(tetra[Ti].p[0])); a->num = row.ix[0]; b->num = row.ix[1]; c->num = row.ix[2]; d->num = row.ix[3]; } void EffaceNode(uint Ti, uint nn) { Node_t a = OrgV(tetra[Ti].p[0]); Node_t b = OrgV(Clock(tetra[Ti].p[0])); Node_t c = OrgV(PrevE(tetra[Ti].p[1])); Node_t d = OrgV(PrevE(tetra[Ti].p[0])); if (a->num == nn) { a->exists = FALSE; } if (b->num == nn) { b->exists = FALSE; } if (c->num == nn) { c->exists = FALSE; } if (d->num == nn) { d->exists = FALSE; } } void EffaceEdgesOfNode(uint Ti, uint nn) { uint a = OrgV(tetra[Ti].p[0])->num; uint b = OrgV(Clock(tetra[Ti].p[0]))->num; uint c = OrgV(PrevE(tetra[Ti].p[1]))->num; uint d = OrgV(PrevE(tetra[Ti].p[0]))->num; Edge_t e0 = PEdge(tetra[Ti].p[0]); Edge_t e1 = PEdge(tetra[Ti].p[2]); Edge_t e2 = PEdge(NextE(tetra[Ti].p[2])); Edge_t e3 = PEdge(PrevE(tetra[Ti].p[2])); Edge_t e4 = PEdge(NextE(tetra[Ti].p[0])); Edge_t e5 = PEdge(NextE(tetra[Ti].p[1])); if ((a == nn) || (b == nn)) { e0->exists = FALSE; } if ((c == nn) || (d == nn)) { e1->exists = FALSE; } if ((a == nn) || (d == nn)) { e2->exists = FALSE; } if ((a == nn) || (c == nn)) { e3->exists = FALSE; } if ((b == nn) || (d == nn)) { e4->exists = FALSE; } if ((b == nn) || (c == nn)) { e5->exists = FALSE; } } void SaveFreeCorners(void) { auto void SaveFreeCornersOfWall(Place_t b, uint i); void SaveFreeCornersOfWall(Place_t b, uint i) { if (SpinBit(b) == 0) { dode.p[i][0] = b; for (j = 1; j < 5; j++) { dode.p[i][j] = Clock(NextE(NextF(PrevE(dode.p[i][j-1])))); } } else { dode.p[i][0] = b; for (j = 1; j < 5; j++) { dode.p[i][j] = Clock(PrevE(NextF(NextE(dode.p[i][j-1])))); } } } uint m = 0; uint n = 0; for (i = 0; i < 60; i++) { for (j = 0; j < 4; j++) { Place_t a = tetra[i].p[j]; uint d = DegreeOfWall(a); if ((d!=1) && (PposP(a) == NULL)) { dode.p[m][n] = tetra[i].p[j]; n++; if (n == 5){ m++; n = 0; } } } } SaveFreeCornersOfWall(dode.p[0][0],0); dode.p[ 1][0] = Spin(NextF(dode.p[0][0])); SaveFreeCornersOfWall(dode.p[ 1][0], 1); dode.p[ 2][0] = Spin(NextF(dode.p[0][4])); SaveFreeCornersOfWall(dode.p[ 2][0], 2); dode.p[ 3][0] = Spin(NextF(dode.p[0][3])); SaveFreeCornersOfWall(dode.p[ 3][0], 3); dode.p[ 4][0] = Spin(NextF(dode.p[0][2])); SaveFreeCornersOfWall(dode.p[ 4][0], 4); dode.p[ 5][0] = Spin(NextF(dode.p[0][1])); SaveFreeCornersOfWall(dode.p[ 5][0], 5); dode.p[ 8][0] = Spin(NextF(dode.p[4][2])); SaveFreeCornersOfWall(dode.p[ 8][0], 8); dode.p[ 6][0] = Spin(NextF(dode.p[8][3])); SaveFreeCornersOfWall(dode.p[ 6][0], 6); dode.p[ 7][0] = Spin(NextF(dode.p[6][1])); SaveFreeCornersOfWall(dode.p[ 7][0], 7); dode.p[ 9][0] = Spin(NextF(dode.p[6][4])); SaveFreeCornersOfWall(dode.p[ 9][0], 9); dode.p[10][0] = Spin(NextF(dode.p[6][3])); SaveFreeCornersOfWall(dode.p[10][0], 10); dode.p[11][0] = Spin(NextF(dode.p[6][2])); SaveFreeCornersOfWall(dode.p[11][0], 11); /* the free corners are computed follows the scheme bellow: /|\ /|\ / | \ / | \ / | \ / | \ / 3 | 2 \ / 3 | 2 \ / | \ / | \ /-----|-----\ /-----|-----\ \ 4 / \ 1 / \ 4 / \ 1 / \ / 0 \ / \ / 0 \ / \/_____\/ \/_____\/ <--- ---> SpinBit == 0 SpinBit == 1 */ } void EffaceWallsOfNode(uint Ti, uint nn) { uint a = OrgV(tetra[Ti].p[0])->num; uint b = OrgV(Clock(tetra[Ti].p[0]))->num; uint c = OrgV(PrevE(tetra[Ti].p[1]))->num; uint d = OrgV(PrevE(tetra[Ti].p[0]))->num; Wall_t f0 = PWall(tetra[Ti].p[0]); Wall_t f1 = PWall(tetra[Ti].p[1]); Wall_t f2 = PWall(tetra[Ti].p[2]); Wall_t f3 = PWall(tetra[Ti].p[3]); if ((a == nn) || (b == nn) || (d == nn)) { f0->exists = FALSE; } if ((a == nn) || (b == nn) || (c == nn)) { f1->exists = FALSE; } if ((a == nn) || (c == nn) || (d == nn)) { f2->exists = FALSE; } if ((b == nn) || (c == nn) || (d == nn)) { f3->exists = FALSE; } } bool_t MustBeGlued(Place_t Ti, Place_t Tj) { uint ao = OrgV(Ti)->num; uint an = OrgV(NextE(Ti))->num; uint ap = OrgV(PrevE(Ti))->num; uint bo = OrgV(Tj)->num; uint bn = OrgV(NextE(Tj))->num; uint bp = OrgV(PrevE(Tj))->num; return ( ((ao == bo) && (an == bn) && (ap == bp)) || ((ao == bo) && (an == bp) && (ap == bn)) ); } } #define TriangulatedDodecahedron_C_author \ "Modula-3 version created by L. Lozada in 1999-2000. Revisions:\n" \ " 19-09-2000 : Added the procedure {MakeTriangulatedDodecahedron}.\n" \ " 24-01-2007 : Converted to C by J. Stolfi;\n" \ " got {MakeTriangulatedDodecahedron} from {Squared.c}."