#define PROG_NAME "AutoGluing" #define PROG_DESC "???" #define PROG_VERS "1.0" /* Last edited on 2023-02-12 07:45:30 by stolfi */ #define AutoGluing_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program implements the automatic gluing of cells (tetrahedra, triangulated octahedra) for the 4D regular and convex polytopes: 5cell, 16cell and 24cell. */ #include #include #define _GNU_SOURCE #include #include #include #include #define _GNU_SOURCE #include #include #include #include #include TYPE double Shape_t = {cell5, cell16, cell24}; typedef struct Options_t { char *inFile; Shape_t shape; char *shapeName; bool_t draw; bool_t detail; bool_t fixed; } double Row2I = ARRAY[0..1] OF uint; double z4_t = ARRAY[0..3] OF uint; double Row6I = ARRAY[0..5] OF uint; double CARDI = uint; double Geom = RECORD uint DER; /* Degree @{Edge->?} Ring */ uint nV; /* Number of node */ uint nE; /* Number of @{edge->?}s */ uint nF; /* Number of walls */ c : REF Coords_t; @{edge->?}: REF ARRAY OF uint_vec_t; wall: REF ARRAY OF uint_vec_t; } CONST double AlphaChars = Mis.AlphaChars; double INIT_STACK_SIZE = 700; VAR Stack4 = NEW(REF ARRAY OF z4_t, INIT_STACK_SIZE); /* stack of z4_t.*/ Stack6 = NEW(REF ARRAY OF Row6I, INIT_STACK_SIZE); /* stack of Row6I.*/ Stack = NEW(REF ARRAY OF CARDI, INIT_STACK_SIZE); /* stack of cardinal.*/ cellnum, tpst : uint = 0; /* tops for the stacks above. */ cell4 = NEW(REF ARRAY OF z4_t, INIT_STACK_SIZE); cell6 = NEW(REF ARRAY OF Row6I, INIT_STACK_SIZE); tetra : REF ARRAY OF ARRAY [0..3] OF Place_t; octa : REF ARRAY OF EightPlaces_t; Geom ReadWire4(char *name) <* FATAL Rd.Failure, Thread.Alerted, FloatMode.Trap, Lex.Error, OSError.E); VAR Geom geom; char *cmt; { FILE *rw = open_read(fileName, TRUE); /* {name}.{w4} */ { cmt = filefmt_read_comment(rw, '#'); /* Element counts: */ Lex.Skip(rw, cs = AlphaChars); geom.DER = fget_int32(rw); Lex.Skip(rw); cmt = filefmt_read_comment(rw, '#'); Lex.Skip(rw, cs = AlphaChars); geom.NV = fget_int32(rw); geom.c = NEW(REF Coords_t, geom.NV); /* Read node data coordinates: */ for (j = 0; j < geom.NV; j++) { Lex.Skip(rw); ??? cv = geom.c[j]; { cv[0] = Lex.LongReal(rw); Lex.Skip(rw); cv[1] = Lex.LongReal(rw); Lex.Skip(rw); cv[2] = Lex.LongReal(rw); Lex.Skip(rw); cv[3] = Lex.LongReal(rw); } } Lex.Skip(rw, cs = AlphaChars); geom.NE = fget_int32(rw); Lex.Skip(rw); /* Create @{edge->?} records */ geom.edge = NEW(REF ARRAY OF uint_vec_t , geom.NE,2); /* Read @{edge->?} extremus */ for (j = 0; j < geom.NE; j++) { Lex.Skip(rw); ??? ee = geom.edge[j]; { ee[0] = fget_int32(rw); Lex.Skip(rw); ee[1] = fget_int32(rw); } } Lex.Skip(rw, cs = AlphaChars); geom.NF = fget_int32(rw); Lex.Skip(rw); /* Create wall records */ geom.wall = NEW(REF ARRAY OF uint_vec_t , geom.NF,geom.DER); /* Read wall extremus */ for (j = 0; j < geom.NF; j++) { Lex.Skip(rw); ??? ff = geom.wall[j]; { for (k = 0; k < geom.DER; k++) { ff[k] = fget_int32(rw); Lex.Skip(rw); } } } fclose(rw); return geom; } } /* END ReadWire4 */ void DoIt() REF ARRAY OF ARRAY OF uint_vec_t cells ; e1 : REF ARRAY OF INTEGER; { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? g = ReadWire4(o->shapeName); { uint ComputeTips(x,y,z,w: uint) REF uint_vec_t p ; k: uint = 0; { p = NEW(REF uint_vec_t ,3); ??? O = x; ??? D = z; { for (j = 0; j < g.NF; j++) { ??? f = g.wall[j]; ??? a = f[0]; ??? b = f[1]; ??? c = f[2]; { if (( (O == a)) && (D == b)){ p[k] = c; k++; } else if ((O == a) && (D == c)){ p[k] = b; k++; } else if ((O == b) && (D == a)){ p[k] = c; k++; } else if ((O == b) && (D == c)){ p[k] = a; k++; } else if ((O == c) && (D == a)){ p[k] = b; k++; } else if ((O == c) && (D == b)){ p[k] = a; k++; } } } for (m = 0; m < 3; m++) { if ((p[m]!=w) && (p[m]!=x)) { if ((AreAdjacents(p[m],y)) && (AreAdjacents(p[m],z))) { return p[m]; } } } } return 1000; } ComputeTips; bool_t AreAdjacents(a,b: uint) /* Decides if exists some @{edge->?} with tips "a" and "b". */ { for (m = 0; m < g.NE; m++) { ??? E = g.edge[m]; ??? EO = E[0]; ??? ED = E[1]; { if ((( (a == EO)) && (b == ED) OR ( (a == ED)) && (b == EO))){ return TRUE; } } } return FALSE; } AreAdjacents; Place_t GlueTetras(Ti,Tj,Ci,Cj: uint) /* Gluing the tetrahedra Ti with Tj through the free walls Ci and Cj respectively. */ void PrintInfo(case: uint;oi,oj,di,dj: uint) /* Prints information about the three possible cases in the gluing procedure. */ { fprintf(stderr, "case " & Fmt.Int(case) & ": "); fprintf(stderr, Fmt.Int(oi) & " " & Fmt.Int(di)&"\n"); fprintf(stderr, " "); fprintf(stderr, Fmt.Int(oj) & " " & Fmt.Int(dj)&"\n\n"); } PrintInfo; void UngluedInfo(ci,cj,ti,tj: uint) /* Prints information about unglued case in the gluing procedure. This procedure cause the halt of the program. */ { fprintf(stderr, "Not glue this case " & Fmt.Int(ci) & " " \ Fmt.Int(cj) & "\n"); fprintf(stderr, " Tetrahedra " & Fmt.Int(ti) & " " \ Fmt.Int(tj) & "\n"); Process.Exit¦(1); } UngluedInfo; { if (o->detail) { fprintf(stderr,"Ci=="&Fmt.Int(Ci)&" Cj=="&Fmt.Int(Cj)&", "); } IF /* 1 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 2 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 3 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 4 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 5 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 6 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 7 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 8 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 9 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3] { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 10 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 11 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 12 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 13 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[3] { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 14 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[2]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 15 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Spin(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Spin(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[0]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Spin(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[0]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Oj) && (Di == Dj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Spin(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Spin(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } ELSIF /* 16 */ double 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)) { if (o->detail){ PrintInfo(1,Oi,Oj,Di,Dj); } Glue(Clock(tetra[Tj].p[Cj]), tetra[Ti].p[Ci], 1); return Clock(tetra[Tj].p[Cj]); } } int Oj = cell4[Tj].ix[3]; int Dj = cell4[Tj].ix[1]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(2,Oi,Oj,Di,Dj); } Glue(Clock(NextE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(NextE(tetra[Tj].p[Cj])); } } int Oj = cell4[Tj].ix[1]; int Dj = cell4[Tj].ix[2]; { if ((Oi == Dj) && (Di == Oj)) { if (o->detail){ PrintInfo(3,Oi,Oj,Di,Dj); } Glue(Clock(PrevE(tetra[Tj].p[Cj])), tetra[Ti].p[Ci], 1); return Clock(PrevE(tetra[Tj].p[Cj])); } } UngluedInfo(Ci,Cj,Ti,Tj); } } return tetra[Ti].p[0]; } GlueTetras; PROCEDURE CorretAttribution(peak: REF uint_vec_t) : REF ARRAY OF Row2I == /* atribui de maneira correta os nodes extremos de um tetraedro */ VAR Stack2 : REF ARRAY OF Row2I; /* stack for peaks */ topo : uint = 0; r : Row2I; Ext : REF ARRAY OF Row2I; guardar: uint; bool_t Present2(array : Row2I) /* Return TRUE if "array" its on the stack, FALSE c.c. */ uint nstack1 = topo; e1 : REF uint_vec_t; st : REF uint_vec_t; { e1 = NEW(REF uint_vec_t ,2); st = NEW(REF uint_vec_t ,2); for (i = 0; i < 2; i++) { e1[i] = array[i]; } Mis.Sort(1,e1); while (nstack1 > 0) { nstack1 = nstack1 - 1; for (i = 0; i < 2; i++) { st[i] = Stack2[nstack1][i]; } Mis.Sort(1,st); if (st^ == e1^){ return TRUE; } } return FALSE; } Present2; void Save2(array : Row2I) /* Saves the "array" on the stack "Stack2". */ { Stack2[topo] = array; topo = topo + 1; } Save2; bool_t Coincide(array : Row2I; chave: uint) { ??? b = array[0]; { if (b == chave){ return TRUE; } return FALSE; } } Coincide; bool_t Candidate(array : Row2I; chave: uint) /* Decides if the array "array" is a possivel candidate to be consider. This is, if any element of the array is equal to the key "chave" then this procedure return TRUE, FALSE c.c. */ { ??? b = array[0]; ??? c = array[1]; { if ((b == chave) || (c == chave)){ return TRUE; } return FALSE; } } Candidate; bool_t Same(a,b: Row2I) /* Decides if the arrays "a" and "b" are the same without consider the order between then. */ { ??? a0 = a[0]; ??? a1 = a[1]; ??? b0 = b[0]; ??? b1 = b[1]; { if (((a0 == b1) && (a1 == b0)) || ((a0 == b0) && (a1 == b1))) { return TRUE; } return FALSE; } } Same; Row2I Report(chave: uint; indice: uint) { for (j = 0; j < topo; j++) { if (indice == 1) { if ((! Same(Stack2[j],Ext[0]))) { ??? r = Stack2[j]; ??? a = r[0]; ??? b = r[1]; { if ((Candidate(r,chave))) { if ((Coincide(r,chave))){ return Row2I{a,b}; } return Row2I{b,a}; } } } } else if (indice == 2){ if ((! Same(Stack2[j],Ext[0])) && (NOT Same(Stack2[j],Ext[1]) )){ ??? r = Stack2[j]; ??? a = r[0]; ??? b = r[1]; { if ((Candidate(r,chave))) { if ((Coincide(r,chave))){ return Row2I{a,b}; } return Row2I{b,a}; } } } } else if (indice == 3){ if ((! Same(Stack2[j],Ext[0])) && (NOT Same(Stack2[j],Ext[1]) ) && (NOT Same(Stack2[j],Ext[2]))){ ??? r = Stack2[j]; ??? a = r[0]; ??? b = r[1]; { if ((Candidate(r,chave))) { if ((Coincide(r,chave))){ return Row2I{a,b}; } return Row2I{b,a}; } } } } else if (indice == 4){ if ((! Same(Stack2[j],Ext[0])) && (NOT Same(Stack2[j],Ext[1]) ) && (NOT Same(Stack2[j],Ext[2]) AND NOT Same(Stack2[j],Ext[3]))) { ??? r = Stack2[j]; ??? a = r[0]; ??? b = r[1]; { if ((Candidate(r,chave))) { if ((Coincide(r,chave))){ return Row2I{a,b}; } return Row2I{b,a}; } } } } } return Row2I{0,0}; } Report; { Stack2 = NEW(REF ARRAY OF Row2I, LAST(peak^)+1); Ext = NEW(REF ARRAY OF Row2I, LAST(peak^)+1); for(i = 0; i < peak.nel; i++) { for(j = 0; j < peak.nel; j++) { if ((i!=j) && (AreAdjacents(peak[i],peak[j]))) { r[0] = peak[i]; r[1] = peak[j]; if ((! Present2(r))){ Save2(r); } } } }; /* Correct assigment of labels for each cell. */ Ext[0] = Stack2[0]; guardar = Ext[0][1]; for(i = 1; i < peak.nel; i++) { Ext[i] = Report(guardar,i); guardar = Ext[i][1]; } return Ext; } CorretAttribution; { /* allocating space for the cell informations to be compute. */ if (o->shape == Shape_cell5) { cells = NEW(REF ARRAY OF ARRAY OF uint_vec_t , g.NE, 3, 4); } else if (o->shape == Shape_cell16){ cells = NEW(REF ARRAY OF ARRAY OF uint_vec_t , g.NE, 4, 4); } else if (o->shape == Shape_cell24){ cells = NEW(REF ARRAY OF ARRAY OF uint_vec_t , g.NE, 3, 6); } /* computing the cells information */ for (i = 0; i < g.NE; i++) { VAR p: REF uint_vec_t; /* the tips of each @{edge->?} "e". */ k,l: uint = 0; { if (o->shape == Shape_cell5) { p = NEW(REF uint_vec_t ,3); } else if (o->shape == Shape_cell16){ p = NEW(REF uint_vec_t ,4); } else if (o->shape == Shape_cell24){ p = NEW(REF uint_vec_t ,3); } ??? e = g.edge[i]; ??? O = e[0]; ??? d = e[1]; { for (j = 0; j < g.NF; j++) { ??? f = g.wall[j]; ??? a = f[0]; ??? b = f[1]; ??? c = f[2]; { if (( (O == a)) && (d == b)){ p[k] = c; k++; } else if ((O == a) && (d == c)){ p[k] = b; k++; } else if ((O == b) && (d == a)){ p[k] = c; k++; } else if ((O == b) && (d == c)){ p[k] = a; k++; } else if ((O == c) && (d == a)){ p[k] = b; k++; } else if ((O == c) && (d == b)){ p[k] = a; k++; } } } /* Create the cells */ if (o->shape == Shape_cell5) { for (m = 0; m < 3; m++) { e1 = NEW(REF ARRAY OF INTEGER,4); e1[0] = O; e1[1] = d; e1[2] = p[m]; e1[3] = p[(m+1) % 3]; cells[i][m][0] = e1[0]; cells[i][m][1] = e1[1]; cells[i][m][2] = e1[2]; cells[i][m][3] = e1[3]; if (o->detail) { PrintRow4I(cells[i][l]); } } } else if (o->shape == Shape_cell16){ ??? ext = CorretAttribution(p); { for (j = 0; j < 4; j++) { cells[i][l][0] = O; cells[i][l][1] = d; cells[i][l][2] = ext[j][0]; cells[i][l][3] = ext[j][1]; if (o->detail) { PrintRow4I(cells[i][l]); } l++; } } } else if (o->shape == Shape_cell24){ for (m = 0; m < 3; m++) { e1 = NEW(REF ARRAY OF INTEGER,4); e1[0] = O; e1[1] = d; e1[2] = p[m]; e1[3] = p[(m+1) % 3]; cells[i][m][0] = e1[0]; cells[i][m][1] = e1[1]; cells[i][m][2] = e1[2]; cells[i][m][3] = e1[3]; cells[i][m][4] = ComputeTips(cells[i][m][0],cells[i][m][2], cells[i][m][3],cells[i][m][1]); cells[i][m][5] = ComputeTips(cells[i][m][1],cells[i][m][2], cells[i][m][3],cells[i][m][0]); assert(! AreAdjacents(cells[i][m][2],cells[i][m][3])); assert(! AreAdjacents(cells[i][m][4],cells[i][m][1])); assert(! AreAdjacents(cells[i][m][5],cells[i][m][0])); assert( AreAdjacents(cells[i][m][4],cells[i][m][5])); } } } } } if (o->shape == Shape_cell5) { for (i = 0; i < g.NE; i++) { for (j = 0; j < 3; j++) { if ((! Present4(cells[i][j]))) { Save4(cells[i][j]); } } }; } else if (o->shape == Shape_cell16){ for (i = 0; i < g.NE; i++) { for (j = 0; j < 4; j++) { if ((! Present4(cells[i][j]))) { Save4(cells[i][j]) } } }; } else if (o->shape == Shape_cell24){ for (i = 0; i < g.NE; i++) { for (j = 0; j < 3; j++) { if ((! Present6(cells[i][j]))) { Save6(cells[i][j]); } } } } if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { for (i = 0; i < cellnum; i++) { for (j = 0; j < 4; j++) { cell4[i][j] = Stack4[i][j]; } } } else if (o->shape == Shape_cell24){ for (i = 0; i < cellnum; i++) { for (j = 0; j < 6; j++) { cell6[i][j] = Stack6[i][j]; } } } if (o->detail) { fprintf(stderr, o->shapeName & "\n"); fprintf(stderr, "cells " & Fmt.Int(cellnum) & "\n"); for (i = 0; i < cellnum; i++) { fprintf(stderr, Fmt.Pad(Fmt.Int(i),3) & ": "); if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { for (j = 0; j < 4; j++) { fprintf(stderr, Fmt.Pad(Fmt.Int(cell4[i][j]), 5) & " "); } fprintf(stderr, "\n"); } else if (o->shape == Shape_cell24){ for (j = 0; j < 6; j++) { fprintf(stderr, Fmt.Pad(Fmt.Int(cell6[i][j]), 5) & " "); } fprintf(stderr, "\n"); } } } void SetCornersTetra(uint Ti, z4_t row) /* Set the labels "row" in the tetrahedron Ti. */ { 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[0]; b->num = row[1]; c->num = row[2]; d->num = row[3]; } } SetCornersTetra; /* UNUSED */ bool_t Same4(a,b: z4_t) /* Decides if the arrays "a" and "b" are the same without consider the order between then. */ { ??? a0 = a[0]; ??? a1 = a[1]; ??? a2 = a[2]; ??? a3 = a[3]; ??? b0 = b[0]; ??? b1 = b[1]; ??? b2 = b[2]; ??? b3 = b[3]; { if (((a0 == b0) && (a1 == b1) && (a2 == b2) && (a3 == b3))) { return TRUE; } return FALSE; } } Same4; void DrawTetra(uint Ti, z4_t row) /* Draw the tetrahedron "Ti" with the labels "row". */ <* FATAL OSError.E); { ??? File = Fmt.Int(Ti); ??? wr = FileWr.Open("Tetrahedron-" & File & ".inc"); frgb_t color = (frgb_t){0.0,0.0,0.0}; double transp = 0.0; ?? x = (r3_t){0.0,0.0,0.0}; ?? y = (r3_t){0.0,-0.7071,-0.7071}; ?? z = (r3_t){-0.7071,-0.7071,0.0}; ?? w = (r3_t){-0.7071,0.0,-0.7071}; { fprintf(wr, "// Include File: \n"); WritePOVCylinder(wr,x,y,0.004,color,transp,TRUE); WritePOVCylinder(wr,x,z,0.004,color,transp,TRUE); WritePOVCylinder(wr,x,w,0.004,color,transp,TRUE); WritePOVCylinder(wr,y,z,0.004,color,transp,TRUE); WritePOVCylinder(wr,y,w,0.004,color,transp,TRUE); WritePOVCylinder(wr,z,w,0.004,color,transp,TRUE); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[0]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.085\n"); fprintf(wr, " translate <-0.025,-0.12500,-1.0000>\n"); fprintf(wr, " translate 0.275*x\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[1]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.125\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.550000,-0.0000,-1.0000>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[3]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.085\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <0.1350000,-0.6500,-1.0000>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[2]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.095\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.2750000,-0.5000,-1.0000>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(Ti) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.1250000,-0.25000,-1.0000>\n"); fprintf(wr, " }\n"); fclose(wr); } } DrawTetra; void DrawOcta(Ouint i; row: Row6I) /* Draw the octahedron "Oi" with the labels "row". */ <* FATAL OSError.E); { ??? File = Fmt.Int(Oi); ??? wr = FileWr.Open("Octahedron-" & File & ".inc"); frgb_t color == (frgb_t){0.0,0.0,0.0}; double transp = 0.0; ??? x = (r3_t){-0.4367, 0.3938, 0.8087}; ??? y = (r3_t){ 0.6782, 0.7325, 0.0134}; ??? z = (r3_t){-0.5818, 0.5558,-0.5931}; ??? w = (r3_t){ 0.5882,-0.5574, 0.5852}; ??? r = (r3_t){-0.6862,-0.7250,-0.0091}; ??? s = (r3_t){ 0.4383,-0.3997,-0.8051}; { fprintf(wr, "// Include File: \n"); WritePOVCylinder(wr,x,y,0.008,color,transp,TRUE); WritePOVCylinder(wr,x,z,0.008,color,transp,TRUE); WritePOVCylinder(wr,y,z,0.008,color,transp,TRUE); WritePOVCylinder(wr,x,w,0.008,color,transp,TRUE); WritePOVCylinder(wr,y,w,0.008,color,transp,TRUE); WritePOVCylinder(wr,r,z,0.008,color,transp,TRUE); WritePOVCylinder(wr,x,r,0.008,color,transp,TRUE); WritePOVCylinder(wr,r,w,0.008,color,transp,TRUE); WritePOVCylinder(wr,s,r,0.008,color,transp,TRUE); WritePOVCylinder(wr,z,s,0.008,color,transp,TRUE); WritePOVCylinder(wr,s,y,0.008,color,transp,TRUE); WritePOVCylinder(wr,w,s,0.008,color,transp,TRUE); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[0]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.4367,0.3938,0.8087>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[1]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <0.6782,0.7325,0.0134>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[3]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.5818,0.5558,-0.5931>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[2]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.6862,-0.7250,-0.0091>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[4]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <0.5882,-0.5574,0.5852>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(row[5]) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <-0.2750000,-0.5000,-1.0000>\n"); fprintf(wr, " }\n"); fprintf(wr, " text { ttf \"timrom.ttf\" \"" & Fmt.Int(Oi) & "\""); fprintf(wr, " 0.125, 0\n"); fprintf(wr, " scale 0.1\n"); fprintf(wr, " translate 0*x\n"); fprintf(wr, " translate <0.4383,-0.3997,-0.8051>\n"); fprintf(wr, " }\n"); fclose(wr); } } DrawOcta; void SetCornersOcta(Ouint i; row: Row6I) /* Set the labels "row" in the octahedron Oi. */ { Node_t a = OrgV(octa[Oi,0]); Node_t b = OrgV(octa[Oi,7]); Node_t c = OrgV(PrevE(octa[Oi,7])); Node_t d = OrgV(PrevE(octa[Oi,0])); Node_t e = OrgV(octa[Oi,1]); Node_t f = OrgV(Clock(octa[Oi,1])) { a->num = row[0]; b->num = row[1]; c->num = row[2]; d->num = row[3]; e->num = row[4]; f->num = row[5]; } } SetCornersOcta; bool_t MustBeGlued(Ti,Tj: Place_t) /* Return TRUE if the walls "PWall(Ti)" and "PWall(Tj)" have coherent orientations and must be glued. */ { Node_t a = OrgV(Ti)->num; Node_t ae = OrgV(NextE(Ti))->num; ??? ae_1 = OrgV(PrevE(Ti))->num; Node_t b = OrgV(Tj)->num; Node_t be = OrgV(NextE(Tj))->num; ??? be_1 = OrgV(PrevE(Tj))->num; { if (((a == b) && (ae == be) && (ae_1 == be_1) OR (a == b) && (ae == be_1) && (ae_1 == be))){ return TRUE; } return FALSE } } MustBeGlued; bool_t BadAttribution(Ti,Tj: Place_t) /* Return TRUE if the walls "PWall(Ti)" and "PWall(Tj)" have incoherent orientations. */ { Node_t i0 = OrgV(Ti)->num; ??? i1 = OrgV(NextE(Ti))->num; ??? i2 = OrgV(PrevE(Ti))->num; Node_t j0 = OrgV(Tj)->num; ??? j1 = OrgV(NextE(Tj))->num; ??? j2 = OrgV(PrevE(Tj))->num; { if ((SpinBit(Ti)!=SpinBit(Tj))) { if (((i0 == j0) && (i1 == j2) && (i2 == j1) OR (i0 == j2) && (i1 == j1) && (i2 == j0) OR (i0 == j1) && (i1 == j0) && (i2 == j2) )){ return TRUE; } } if ((SpinBit(Ti) == SpinBit(Tj))) { if (((i0 == j0) && (i1 == j1) && (i2 == j2) OR (i0 == j2) && (i0 == j0) && (i2 == j1) OR (i0 == j1) && (i1 == j2) && (i2 == j0) )){ return TRUE; } } return FALSE } } BadAttribution; void PrintCorners(Tuint i) /* Print the corners of the triangular wall "Ti". */ { Node_t a = OrgV(walls[Ti])->num; Node_t ae = OrgV(NextE(walls[Ti]))->num; ??? ae_1 = OrgV(PrevE(walls[Ti]))->num; { fprintf(stderr, Fmt.Pad(Fmt.Int(a),3) & " " \ Fmt.Pad(Fmt.Int(ae),3) \ " " & Fmt.Pad(Fmt.Int(ae_1),3) & " "); } } PrintCorners; REF ARRAY OF EightPlaces_t poly ; id : uint = 0; count : uint = 1; walls : REF Place_vec_t; glues : REF ARRAY OF z4_t; c = NEW(REF Triangulation.Coords_t, 48); void SetCoorOcta(Ouint i; row: Row6I) /* Set the coord "row" in the octahedron Oi. */ void SetCoords(Place_t e, r4_t *cv) /* set the origin node od the @place "e" with "cv". */ { c[OrgV(e)->num] = cv; } SetCoords; r4_t BaryOcta() /* Return the barycenter of the octahedron.*/ r4_t b = (r4_t){0.0, ..}; { for (i = 0; i < 6; i++) { b = r4_Add(b, g.c[row[i]]); } return r4_Scale(1.0/6.0, b); } BaryOcta; { SetCoords(octa[Oi,0], g.c[row[0]]); SetCoords(octa[Oi,7], g.c[row[1]]); SetCoords(PrevE(octa[Oi,7]),g.c[row[2]]); SetCoords(PrevE(octa[Oi,0]),g.c[row[3]]); SetCoords(octa[Oi,1], g.c[row[4]]); SetCoords(Clock(octa[Oi,1]), g.c[row[5]]); SetCoords(PrevE(PrevF(octa[Oi,4])), BaryOcta()); Mis.WritePoint(stderr, BaryOcta()); fprintf(stderr,"\n"); } SetCoorOcta; { poly = NEW(REF ARRAY OF EightPlaces_t,cellnum); tetra = NEW(REF ARRAY OF ARRAY [0..3] OF Place_t,cellnum); octa = NEW(REF ARRAY OF EightPlaces_t,cellnum); if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { Place_vec_t walls = Place_vec_new( 4*cellnum); glues = NEW(REF ARRAY OF z4_t, 2*cellnum); /* Create topological tetrahedra */ for (i = 0; i < cellnum; i++) { poly[i] = MakeTetraTopo(1,1); } /* Create the tetrahedra */ for (i = 0; i < cellnum; i++) { for (j = 0; j < 4; j++) { tetra[i].p[j] = poly[i,j]; assert(PposP(tetra[i].p[j]) == NULL); } } } else if (o->shape == Shape_cell24){ Place_vec_t walls = Place_vec_new( 8*cellnum); glues = NEW(REF ARRAY OF z4_t, 4*cellnum); /* Create the octahedra */ for (i = 0; i < cellnum; i++) { for (j = 0; j < 8; j++) { octa[i] = MakeOctahedronTriang(TRUE); assert(PposP(octa[i,j]) == NULL); } } } /* cells with corners perfectly assigments */ if (o->shape == Shape_cell5) { cell4[0] = (z4_t){{2,3,4,1}}; cell4[1] = (z4_t){{2,3,1,0}}; cell4[2] = (z4_t){{2,3,0,4}}; cell4[3] = (z4_t){{3,4,1,0}}; cell4[4] = (z4_t){{4,2,1,0}}; } else if (o->shape == Shape_cell16){ cell4[0] = (z4_t){{5,6,7,4}}; cell4[1] = (z4_t){{5,6,4,3}}; cell4[2] = (z4_t){{5,6,3,0}}; cell4[3] = (z4_t){{5,6,0,7}}; cell4[4] = (z4_t){{6,7,4,1}}; cell4[5] = (z4_t){{6,7,1,0}}; cell4[6] = (z4_t){{7,5,4,2}}; cell4[7] = (z4_t){{7,5,2,0}}; cell4[8] = (z4_t){{4,6,1,3}}; cell4[9] = (z4_t){{7,4,1,2}}; cell4[10] = (z4_t){{4,5,3,2}}; cell4[11] = (z4_t){{0,6,3,1}}; cell4[12] = (z4_t){{7,0,2,1}}; cell4[13] = (z4_t){{0,5,2,3}}; cell4[14] = (z4_t){{1,4,3,2}}; cell4[15] = (z4_t){{0,1,3,2}}; } else if (o->shape == Shape_cell24){ cell6[0] = Row6I{ 0, 8, 9,10,11, 1}; cell6[1] = Row6I{ 0, 8,10,12,14, 3}; cell6[2] = Row6I{ 0, 8,12, 9,13, 2}; cell6[3] = Row6I{ 8, 9, 1, 2,16,17}; cell6[4] = Row6I{ 9, 0,11,13, 7,15}; cell6[5] = Row6I{10, 8, 1, 3,18,16}; cell6[6] = Row6I{ 0,10,11,14,15, 6}; cell6[7] = Row6I{ 1, 9,11,17,19, 7}; cell6[8] = Row6I{10, 1,11,18, 6,19}; cell6[9] = Row6I{ 8,12, 2, 3,16,20}; cell6[10] = Row6I{12, 0,13,14, 5,15}; cell6[11] = Row6I{ 9, 2,13,17, 7,21}; cell6[12] = Row6I{ 2,12,13,20,21, 5}; cell6[13] = Row6I{ 3,10,14,18,22, 6}; cell6[14] = Row6I{12, 3,14,20, 5,22}; cell6[15] = Row6I{ 1,16,17,18,19, 4}; cell6[16] = Row6I{16, 2,17,20, 4,21}; cell6[17] = Row6I{ 3,16,18,20,22, 4}; cell6[18] = Row6I{14,15, 5, 6,22,23}; cell6[19] = Row6I{15,13, 5, 7,23,21}; cell6[20] = Row6I{11,15, 6, 7,19,23}; cell6[21] = Row6I{18,19, 6, 4,22,23}; cell6[22] = Row6I{17, 7,19,21, 4,23}; cell6[23] = Row6I{ 5,23,21,22,20, 4}; }; if (o->draw) { if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { for (i = 0; i < cellnum; i++) { fprintf(stderr, "Drawing tetrahedron :" & Fmt.Int(i) & "\n"); DrawTetra(i,cell4[i]); } } else if (o->shape == Shape_cell24){ for (i = 0; i < cellnum; i++) { fprintf(stderr,"Drawing octahedron :"&Fmt.Int(i) & "\n"); DrawOcta(i,cell6[i]); } } }; if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { /* set the labels for each tetrahedra */ for (i = 0; i < cellnum; i++) { SetCornersTetra(i,cell4[i]); } } else if (o->shape == Shape_cell24){ /* set the labels for each octahedra */ for (i = 0; i < cellnum; i++) { SetCornersOcta(i,cell6[i]); } if (o->fixed) { for (i = 0; i < cellnum; i++) { SetCoorOcta(i,cell6[i]); } } }; /* builds the table of walls for choose which tetrahedra must be gluing. */ if (o->detail) { fprintf(stderr, "C id table wall\n"); fprintf(stderr, "-------------------------\n"); }; for (i = 0; i < cellnum; i++) { if (o->detail) { fprintf(stderr, Fmt.Int(i) & "\n"); } if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { for (k = 0; k < 4; k++) { walls[(4*i)+k] = tetra[i].p[k]; if (o->detail) { fprintf(stderr," "& Fmt.Pad(Fmt.Int(id),4)&" "); id++; PrintCorners((4*i)+k); fprintf(stderr, " " & Fmt.Int(k) & "\n"); } } } else if (o->shape == Shape_cell24){ for (k = 0; k < 8; k++) { walls[(8*i)+k] = octa[i,k]; if (o->detail) { fprintf(stderr," "&Fmt.Pad(Fmt.Int(id),4)& " "); id++; PrintCorners((8*i)+k); fprintf(stderr, " " & Fmt.Int(k) & "\n"); } } } } /* computing which cells must be gluing. */ for(k = 0; k < walls.nel; k++) { for (l = k+1 TO LAST(walls^)) { for (m = 0; m < 3; m++) { ??? e = NextEK(walls[l], m); { if ((MustBeGlued(walls[k],e))) { if (o->detail) { fprintf(stderr, Fmt.Int(count) & "\n"); fprintf(stderr, "must be gluing: walls[" & Fmt.Int(k) \ "] with "); fprintf(stderr, "walls[" & Fmt.Int(l) &"]\n"); } if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { ??? kc = k % 4; ??? kt = k DIV 4; ??? lc = l % 4; ??? lt = l DIV 4; { if (o->detail) { fprintf(stderr, " tetra["&Fmt.Int(kt) & "," \ Fmt.Int(kc) & "] and tetra[" & Fmt.Int(lt) & "," \ Fmt.Int(lc) & "]\n\n"); } glues[count-1] = (z4_t){{kt,lt,kc,lc}}; count++; if ((BadAttribution(walls[k],e))) { fprintf(stderr, "Bad Attribution " & " tetra["& Fmt.Int(kt) &"and tetra[" & Fmt.Int(lt) & "]\n"); } } } else if (o->shape == Shape_cell24){ ??? kc = k % 8; ??? kt = k DIV 8; ??? lc = l % 8; ??? lt = l DIV 8; { if (o->detail) { fprintf(stderr, " octa["&Fmt.Int(kt) & "," \ Fmt.Int(kc) & "] and octa[" & Fmt.Int(lt) & "," \ Fmt.Int(lc) & "]\n\n"); } glues[count-1] = (z4_t){{kt,lt,kc,lc}}; } count++; } } } } } } if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { /* Do the automatic gluing of tetrahedra */ for (i = 0; i < 2*cellnum; i++) { ??? c = glues[i]; { EVAL GlueTetras(c[0],c[1],c[2],c[3]); } } } else if (o->shape == Shape_cell24){ /* Gluing the triangulated octahedra. */ /* 1-5 */ Glue(Spin(PrevE(octa[0,0])), octa[6,7], 1); Glue(Spin(NextE(octa[0,1])), octa[8,7], 1); Glue(Spin(NextE(octa[0,2])), octa[5,7], 1); Glue(Spin(octa[0,3]), octa[1,7], 1); Glue(Clock(PrevE(octa[0,4])), octa[4,7], 1); /* 6-10 */ Glue(Clock(NextE(octa[0,5])), octa[7,7], 1); Glue(Clock(NextE(octa[0,6])), octa[3,7], 1); Glue(Spin(octa[0,7]), octa[2,3], 1); Glue(Clock(PrevE(octa[1,0])), octa[10,3],1); Glue(Spin(NextE(octa[1,1])), octa[14,7],1); /* 10-15 */ Glue(Clock(NextE(octa[1,2])), octa[9,3], 1); Glue(Spin(octa[1,3]), octa[2,7], 1); Glue(Spin(PrevE(octa[1,4])), octa[6,3], 1); Glue(Clock(NextE(octa[1,5])), octa[13,7],1); Glue(Spin(NextE(octa[1,6])), octa[5,3], 1); /* 16-20 */ Glue(Clock(PrevE(octa[2,0])), octa[4,3], 1); Glue(Spin(NextE(octa[2,1])), octa[11,7],1); Glue(Clock(NextE(octa[2,2])), octa[3,3], 1); Glue(Clock(PrevE(octa[2,4])), octa[10,7],1); Glue(Clock(NextE(octa[2,5])), octa[12,7],1); /* 21- 25 */ Glue(Clock(NextE(octa[2,6])), octa[9,7], 1); Glue(Spin(octa[3,0]), octa[9,4], 1); Glue(Spin(PrevE(octa[3,1])), octa[16,7],1); Glue(Clock(NextE(octa[3,2])), octa[11,3],1); Glue(Clock(octa[3,4]), octa[5,6], 1); /* 26-30 */ Glue(Clock(PrevE(octa[3,5])), octa[15,7],1); Glue(Spin(NextE(octa[3,6])), octa[7,3], 1); Glue(Spin(octa[4,0]), octa[11,4],1); Glue(Clock(NextE(octa[4,1])), octa[19,3],1); Glue(Spin(octa[4,2]), octa[10,6],1); /* 31-35 */ Glue(Clock(octa[4,4]), octa[7,6], 1); Glue(Spin(NextE(octa[4,5])), octa[20,3],1); Glue(Clock(octa[4,6]), octa[6,4], 1); Glue(Clock(PrevE(octa[5,0])), octa[13,3],1); Glue(Spin(NextE(octa[5,1])), octa[17,7],1); /* 36-39 */ Glue(Clock(octa[5,2]), octa[9,0], 1); Glue(Spin(PrevE(octa[5,4])), octa[8,3], 1); Glue(Spin(NextE(octa[5,5])), octa[15,3],1); Glue(Clock(octa[6,0]), octa[10,2],1); /* 40-44 */ Glue(Clock(PrevE(octa[6,1])), octa[18,3],1); Glue(Spin(octa[6,2]), octa[13,6],1); Glue(Clock(PrevE(octa[6,5])), octa[20,7],1); Glue(Clock(octa[6,6]), octa[8,4], 1); Glue(Spin(octa[7,0]), octa[15,4],1); /* 45-50 */ Glue(Spin(NextE(octa[7,1])), octa[22,7],1); Glue(Clock(octa[7,2]), octa[11,0],1); Glue(Clock(octa[7,4]), octa[8,6], 1); Glue(Spin(PrevE(octa[7,5])), octa[20,0],1); Glue(Clock(octa[8,0]), octa[13,2],1); /* 50-54 */ Glue(Spin(NextE(octa[8,1])), octa[21,7],1); Glue(Clock(octa[8,2]), octa[15,0],1); Glue(Clock(NextE(octa[8,5])), octa[20,4],1); Glue(Clock(PrevE(octa[9,1])), octa[17,3],1); Glue(Clock(NextE(octa[9,2])), octa[14,3],1); /* 55-60 */ Glue(Spin(PrevE(octa[9,5])), octa[16,3],1); Glue(Spin(NextE(octa[9,6])), octa[12,3],1); Glue(Spin(octa[10,0]), octa[14,4],1); Glue(Spin(NextE(octa[10,1])), octa[18,7],1); Glue(Clock(octa[10,4]), octa[12,6],1); Glue(Clock(NextE(octa[10,5])), octa[19,7],1); /* 61-65 */ Glue(Clock(PrevE(octa[11,1])),octa[22,3],1); Glue(Spin(octa[11,2]), octa[16,6],1); Glue(Spin(NextE(octa[11,5])), octa[19,2],1); Glue(Clock(octa[11,6]), octa[12,4],1); Glue(Clock(octa[12,0]), octa[16,2],1); /* 66-71 */ Glue(Spin(NextE(octa[12,1])), octa[23,4],1); Glue(Clock(octa[12,2]), octa[14,0],1); Glue(Clock(PrevE(octa[12,5])),octa[19,6],1); Glue(Spin(octa[13,0]), octa[17,4],1); Glue(Spin(PrevE(octa[13,1])), octa[21,4],1); Glue(Clock(octa[13,4]), octa[14,6],1); /* 72-77 */ Glue(Spin(PrevE(octa[13,5])), octa[18,0],1); Glue(Clock(PrevE(octa[14,1])),octa[23,0],1); Glue(Clock(octa[14,2]), octa[17,0],1); Glue(Clock(NextE(octa[14,5])), octa[18,4],1); Glue(Clock(PrevE(octa[15,1])),octa[21,3],1); Glue(Spin(octa[15,2]), octa[17,6],1); /* 78-82 */ Glue(Clock(NextE(octa[15,5])), octa[22,4],1); Glue(Clock(octa[15,6]), octa[16,4],1); Glue(Clock(octa[16,0]), octa[17,2],1); Glue(Spin(PrevE(octa[16,1])), octa[23,5],1); Glue(Spin(PrevE(octa[16,5])), octa[22,0],1); /* 83-88 */ Glue(Clock(NextE(octa[17,1])), octa[23,1],1); Glue(Spin(PrevE(octa[17,5])), octa[21,0],1); Glue(Spin(octa[18,1]), octa[21,5],1); Glue(Spin(octa[18,2]), octa[20,6],1); Glue(Spin(NextE(octa[18,5])), octa[23,3],1); Glue(Clock(octa[18,6]), octa[19,4],1); /* 89-93 */ Glue(Clock(octa[19,0]), octa[20,2],1); Glue(Clock(PrevE(octa[19,1])),octa[22,2],1); Glue(Clock(PrevE(octa[19,5])),octa[23,7],1); Glue(Spin(NextE(octa[20,1])), octa[22,6],1); Glue(Clock(octa[20,5]), octa[21,6],1); /* 94-96 */ Glue(Clock(NextE(octa[21,1])), octa[23,2],1); Glue(Spin(PrevE(octa[21,2])), octa[22,5],1); Glue(Spin(octa[22,1]), octa[23,6],1); } /* Builds and writes the topology. */ fprintf(stderr, "Building the topology of " & o->shapeName & ":\n"); if ((o->shape == Shape_cell5) || (o->shape == Shape_cell16)) { ??? a = tetra[1].p[1]; ??? top = MakeElemTable(a,0); Coords_t c = GenCoords(&top);; { /* seting the elements root for edges and walls.*/ for (i = 0; i < top.wall.nel; i++) { ??? f = top.wall[i]; { f->root = f->num; } } for (i = 0; i < top.edge.nel; i++) { ??? e = top.edge[i]; { e->root = e->num; } } WriteTopology(o->shapeName, top, "Created by AutoGluing: " & o->shapeName & ".tp on " \ Today()); WriteTable(o->shapeName, top, "Created by AutoGluing: " & o->shapeName & ".tb on " \ Today()); WriteMaterials(o->shapeName, top, "Created by AutoGluing: " & o->shapeName& ".ma on " \ Today()); WriteState(o->shapeName, top, c, "Created by AutoGluing: " & o->shapeName & ".st on " \ Today() &"\nRandom Geometry"); } } else if (o->shape == Shape_cell24){ ??? a = octa[21,1]; ??? top = MakeElemTable(a,0); ??? ca = GenCoords(top)^; { /* seting the elements root for edges and walls.*/ for (i = 0; i < top.wall.nel; i++) { ??? f = top.wall[i]; { f->root = f->num; f->exists = TRUE; } } for (i = 0; i < top.edge.nel; i++) { ??? e = top.edge[i]; { e->root = e->num; e->exists = TRUE; } } WriteTopology(o->shapeName, top, "Created by AutoGluing: " & o->shapeName & ".tp on " \ Today()); WriteMaterials(o->shapeName, top, "Created by AutoGluing: " & o->shapeName& ".ma on " \ Today()); if (! o->fixed) { WriteState(o->shapeName, top, ca, "Created by AutoGluing: " & o->shapeName & ".st on " \ Today() &"\nRandom Geometry"); } else if ( o->fixed){ WriteState(o->shapeName, top, c^, "Created by AutoGluing: " & o->shapeName & ".st on " \ Today() &"\nFixed Geometry"); } } } } } } } DoIt; /* Procedures for stacking */ bool_t Present4(array : z4_t) /* Return TRUE if "array" its on the stack, FALSE c.c. */ uint nstack = cellnum; e1 : REF uint_vec_t; st : REF uint_vec_t; { e1 = NEW(REF uint_vec_t ,4); st = NEW(REF uint_vec_t ,4); for (i = 0; i < 4; i++) { e1[i] = array[i]; } Mis.Sort(3,e1); while (nstack > 0) { nstack--; for (i = 0; i < 4; i++) { st[i] = Stack4[nstack][i]; } Mis.Sort(3,st); if (st^ == e1^){ return TRUE; } } return FALSE; } Present4; void Save4(VAR array : z4_t) /* Saves the array "array" on the stack "Stack4". */ { Stack4[cellnum] = array; cellnum = cellnum + 1; } /* END Save4 */ bool_t Present6(array : Row6I) /* Return TRUE if "array" its on the stack "Stack6", FALSE c.c. */ uint nstack = cellnum; e1 : REF uint_vec_t; st : REF uint_vec_t; { e1 = NEW(REF uint_vec_t ,6); st = NEW(REF uint_vec_t ,6); for (i = 0; i < 6; i++) { e1[i] = array[i]; } Mis.Sort(5,e1); while (nstack > 0) { nstack--; for (i = 0; i < 6; i++) { st[i] = Stack6[nstack][i]; } Mis.Sort(5,st); if (st^ == e1^){ return TRUE; } } return FALSE; } Present6; void Save6(VAR array : Row6I) /* Saves the array "array" on the stack "Stack6". */ { Stack6[cellnum] = array; cellnum = cellnum + 1; } /* END Save6 */ /* UNUSED */ bool_t Present(card : CARDI) /* Return TRUE if "card" its on the stack "STACK", FALSE c.c. */ uint nstack = tpst; { while (nstack > 0){ nstack = nstack-1; if (Stack.El[nstack] == card){ return TRUE; } } return FALSE; } Present; /* UNUSED */ void Save(card : CARDI) /* Saves the cardinal value "card" on the stack "Stack". */ { Stack.El[tpst] = card; tpst = tpst + 1; } /* END Save */ /* Procedures for printing */ void PrintRow4I(m: z4_t) /* Print an array of four integer values. */ { fprintf(stderr,Fmt.Int(m[0]) & " " & Fmt.Int(m[1]) & " " \ Fmt.Int(m[2]) & " " & Fmt.Int(m[3]) & "\n"); } /* END PrintRow4I */ /* UNUSED */ void PrintRow6I(m: Row6I) /* Print an array of six integer values. */ { fprintf(stderr,Fmt.Int(m[0]) & " " & Fmt.Int(m[1]) & " " \ Fmt.Int(m[2]) & " " & Fmt.Int(m[3]) & " " & Fmt.Int(m[4]) \ " " & Fmt.Int(m[5]) & "\n"); } /* END PrintRow6I */ /* UNUSED */ void PrintRow2I(m: Row2I) /* Print an array of two integer values. */ { fprintf(stderr,Fmt.Int(m[0]) & " " & Fmt.Int(m[1]) & "\n"); } /* END PrintRow2I */ Options_t GetOptions () { Options_t *o = (Options_t *)malloc(sizeof(Options_t)); argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); if (0 == strcmp(o->shapeName, "5cell"))) { o->shape = Shape_cell5 } else if (0 == strcmp(o->shapeName, "16cell"))){ o->shape = Shape_cell16 } else if (0 == strcmp(o->shapeName, "24cell"))){ o->shape = Shape_cell24 } else { argparser_error(pp, "Bad shape \"" & argparser_get_next(pp) & "\"\n"); } o->draw = argparser_keyword_present(pp, "-draw"); o->detail = argparser_keyword_present(pp, "-detail"); o->fixed = argparser_keyword_present(pp, "-fixed"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: AutoGluing \\\n" \ " -shape { 5cell | 16cell | 24cell }\\\n" \ " [ -draw ] [ -detail ] [ -fixed ]\n"); END¦ } } return o; } /* END GetOptions */ { DoIt() } AutoGluing. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */