#define PROG_NAME "TriangToGeom" #define PROG_DESC "???" #define PROG_VERS "1.0" /* Last edited on 2024-12-21 11:41:35 by stolfi */ #define TriangToGeom_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Writes an arbitrary topology (triangulation or not) in the OOGL formats "skel" (collections of points and polylines) or "off" (collections of planar polygons with possibly shared nodes. If "all" is present, then writes all walls, else writes only walls with the attribute "exists==TRUE". Revisions: 08-07-2000: Added the silhouette walls. 21-07-2000: More color and opacity index for the silhouette walls. 08-10-2000: Standarized the WriteWall procedures equal to the TriangToX3D module, such don't more use the OrgV()->num information for compute the extremum nodes of the wall. */ #include #include #include #include #include #include #include #include #include // #include #include TYPE double Format = {Skel, Off}; /* [[!!! DOES THIS COMMENT FROM Octf.h APPLY HERE ??? */ /* A '@{chip->?}' is a group of four @places, consisting of two mutually dual wedges. */ double FourNodes_t = RECORD u, v, w, x: uint; } typedef struct Options_t { char *inFileTp; inFileSt3 : char *; char *outFile; bool_t all; Format format; char *formatName; bool_t silhouette; /*TRUE draws the silhouette walls */ color: frgb_t; /*attributes of color and opacity for silhouette */ REAL opacity; /*walls,Transparent (opacity==1) Opaque (opacity==0)*/ } bool_t Sign(d: double) /* Return TRUE iff the longreal value is positive, FALSE c.c. */ { assert(d!=0.0); if (d < 0.0){ return FALSE }else{ return TRUE; }; } /* END Sign */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? tc = Triangulation.ReadToMa(o->inFileTp); ??? rc3 = Tridimensional.ReadState3D(o->inFileSt3); ??? top = tc.top; ??? c3 = rc3^; { if (o->format == Format.Skel) { WriteSkelFile(top, c3, o); } else if (o->format == Format.Off){ WriteOffFile(top, c3, o); } return 0; } void WriteSkelFile(ElemTableRec_t *top, *c3 : Tridimensional.Coords3D_t; Options_t *o = (Options_t *)malloc(sizeof(Options_t)); ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? wr = FileWr.Open(o->outFile & ".skel"); { fprintf(wr, "appearance {shading csmooth linewidth 1}\n"); fprintf(wr, "nSKEL 3\n"); WriteSkel(wr, top, c3, o); fclose(wr) } } /* END WriteSkelFile */ void WriteOffFile(ElemTableRec_t *top, *c3 : Tridimensional.Coords3D_t; Options_t *o = (Options_t *)malloc(sizeof(Options_t)); ) <* FATAL Wr.Failure, Thread.Alerted, OSError.E); { ??? wr = FileWr.Open(o->outFile & ".off"); { fprintf(wr, "appearance {shading csmooth linewidth 1}\n"); fprintf(wr, "OFF\n"); WriteOff(wr, top, c3, o); fclose(wr) } } /* END WriteOffFile */ void WriteSkel ( FILE *wr, *ElemTableRec_t *top; *c3 : Tridimensional.Coords3D_t; Options_t *o = (Options_t *)malloc(sizeof(Options_t)); ) == double FindOriR3(q: FourNodes_t) /* For each tetrahedron with extremus nodes numbers u,v,w,x compute us its orientation in R^{3} through the 4x4 determinant: _ _ | c3[q.u][0] c3[q.u][1] c3[q.u][2] 1.0 | double B = | c3[q.v][0] c3[q.v][1] c3[q.v][2] 1.0 | | c3[q.w][0] c3[q.w][1] c3[q.w][2] 1.0 | | c3[q.x][0] c3[q.x][1] c3[q.x][2] 1.0 | - - */ { with ( double a = (r4_t){c3[q.u][0], c3[q.u][1], c3[q.u][2], 1.0}; double b = (r4_t){c3[q.v][0], c3[q.v][1], c3[q.v][2], 1.0}; double c = (r4_t){c3[q.w][0], c3[q.w][1], c3[q.w][2], 1.0}; double d = (r4_t){c3[q.x][0], c3[q.x][1], c3[q.x][2], 1.0} ){ return r4_det(a,b,c,d); } } FindOriR3; bool_t SilhouetteWalls(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a silhouette wall, FALSE c.c. */ { ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; with ( double t1 = FourNodes_t{un,vn,wn,xn}; double t2 = FourNodes_t{un,vn,wn,yn}; double d1 = FindOriR3(t1); double d2 = FindOriR3(t2) ){ if (((Sign(d1)) && (Sign(d2))) || (((NOT Sign(d1))) && ((NOT Sign(d2))))) { return TRUE; } else { return FALSE; } } } SilhouetteWalls; void WriteSkelWall( uint *n; *f : Triangulation.Wall; ) /* This procedure writes a n-gon wall */ REF ARRAY OF INTEGER g ; Place_t @p; { ??? vd = digits(top->node.nel-1); { g = NEW(REF ARRAY OF INTEGER, n); fprintf(wr, Fmt.Int(n+1) & " "); a = f.pa; for (i = 0; i < n; i++) { g[i] = OrgV(a)->num; fprintf(wr, Fmt.Pad(Fmt.Int(g[i]), vd) & " "); a = NextE(a); } fprintf(wr, Fmt.Pad(Fmt.Int(g[0]), vd) & " "); fprintf(wr, " 0.00 0.00 0.00 "); /* color */ fprintf(wr, " 1"); /* Index of opacity */ fprintf(wr, "\n"); fflush(wr); } } WriteSkelWall; m: uint = 0; /* number of existing walls */ { for (i = 0; i < top->wall.nel; i++){ if (top->wall[i]->exists){ m++; } } if (o->silhouette) { for (i = 0; i < top->wall.nel; i++) { ??? f = top->wall[i]; ??? a = f.pa; { if ((SilhouetteWalls(a)) && (NOT f->exists)){ m++; } } } } if (o->all) { fprintf(wr, Fmt.Int(top->node.nel) & " " & Fmt.Int(top->wall.nel) & "\n"); fprintf(wr, "\n"); } else if (! o->silhouette){ fprintf(wr, Fmt.Int(top->node.nel) & " " & Fmt.Int(m) & "\n"); fprintf(wr, "\n"); } else if (o->silhouette){ fprintf(wr, Fmt.Int(top->node.nel) & " " & Fmt.Int(m) & "\n"); fprintf(wr, "\n"); } for (i = 0; i < top->node.nel; i++) { Node_t v = OrgV(top->node.el[i]); { Mis.WritePoint3D(wr,c3[v->num]); fprintf(wr, "\n"); } } fprintf(wr, "\n"); for (i = 0; i < top->wall.nel; i++) { ??? f = top->wall[i]; { if ((o->all) || (top->wall[i]->exists)) { WriteSkelWall(((f.node^).nel),f); } } } if (o->silhouette) { for (i = 0; i < top->wall.nel; i++) { ??? f = top->wall[i]; ??? a = f.pa; { if ((SilhouetteWalls(a)) && (NOT f->exists)) { WriteSkelWall(Octf.DegreeOfEdge(a),f); } } } } fclose(wr); } /* END WriteSkel */ void WriteOff ( FILE *wr, *ElemTableRec_t *top; *c3: Tridimensional.Coords3D_t; Options_t *o = (Options_t *)malloc(sizeof(Options_t)); ) == double FindOriR3(q: FourNodes_t) /* For each tetrahedron with extremus nodes numbers u,v,w,x compute us its orientation in R^{3} through the 4x4 determinant: _ _ | c3[q.u][0] c3[q.u][1] c3[q.u][2] 1.0 | double B = | c3[q.v][0] c3[q.v][1] c3[q.v][2] 1.0 | | c3[q.w][0] c3[q.w][1] c3[q.w][2] 1.0 | | c3[q.x][0] c3[q.x][1] c3[q.x][2] 1.0 | - - */ { with ( double a = (r4_t){c3[q.u][0], c3[q.u][1], c3[q.u][2], 1.0}; double b = (r4_t){c3[q.v][0], c3[q.v][1], c3[q.v][2], 1.0}; double c = (r4_t){c3[q.w][0], c3[q.w][1], c3[q.w][2], 1.0}; double d = (r4_t){c3[q.x][0], c3[q.x][1], c3[q.x][2], 1.0} ){ return r4_det(a,b,c,d); } } FindOriR3; bool_t SilhouetteWalls(Place_t @p) /* Return TRUE iff the wall associated to the @place "a" is a silhouette wall, FALSE c.c. */ { ??? t = TetraNegPosNodes(a); ??? un = t[0]->num; ??? vn = t[1]->num; ??? wn = t[2]->num; ??? xn = t[3]->num; ??? yn = t[4]->num; with ( double t1 = FourNodes_t{un,vn,wn,xn}; double t2 = FourNodes_t{un,vn,wn,yn}; double d1 = FindOriR3(t1); double d2 = FindOriR3(t2) ){ if (((Sign(d1)) && (Sign(d2))) || (((NOT Sign(d1))) && ((NOT Sign(d2))))) { return TRUE; } else { return FALSE; } } } SilhouetteWalls; void WriteOffWall( uint *n; *f : Triangulation.Wall; diffuse : frgb_t; REAL transp; ) /* This procedure writes a {n}-gon wall, associated to the @place wall-@{edge->?} "a" with color "diffuse" and transparency "opacity" */ REF ARRAY OF INTEGER g ; { ??? vd = digits(top->node.nel-1); { g = NEW(REF ARRAY OF INTEGER, n); fprintf(wr, Fmt.Int(n) & " "); for (i = 0; i < n; i++) { g[i] = f.node[i]->num; fprintf(wr, Fmt.Pad(Fmt.Int(g[i]), vd) & " "); } Mis.WriteColor(wr,diffuse); fprintf(wr, " "); Mis.WriteIntensity(wr,transp); fprintf(wr, "\n"); fflush(wr); } } WriteOffWall; m: uint = 0; /* number of existing walls */ { for (i = 0; i < top->wall.nel; i++){ if (top->wall[i]->exists){ m++; } } if (o->silhouette) { for (i = 0; i < top->wall.nel; i++) { ??? f = top->wall[i]; ??? a = f.pa; { if ((SilhouetteWalls(a)) && (NOT f->exists)){ m++; } } } } if (o->all) { fprintf(wr, Fmt.Int(top->node.nel) & " " & Fmt.Int(top->wall.nel) & " " \ Fmt.Int(top->NE) & "\n"); fprintf(wr, "\n"); } else if (! o->silhouette){ fprintf(wr, Fmt.Int(top->node.nel) & " " & Fmt.Int(m) & " " \ Fmt.Int(top->NE) & "\n"); fprintf(wr, "\n"); } else if (o->silhouette){ fprintf(wr, Fmt.Int(top->node.nel) & " " & Fmt.Int(m) & " " \ Fmt.Int(top->NE) & "\n"); fprintf(wr, "\n"); } for (i = 0; i < top->node.nel; i++) { Node_t v = OrgV(top->node.el[i]); { Mis.WritePoint3D(wr,c3[v->num]); fprintf(wr,"\n"); } } fprintf(wr, "\n"); for (i = 0; i < top->wall.nel; i++) { ??? f = top->wall[i]; ??? fc = f.color; ??? t3 = f.transp; ??? tp = (t3[0] + t3[1] + t3[2]) / 3.0; { if ((o->all) || (top->wall[i]->exists)) { WriteOffWall(((f.node^).nel),f,fc,tp); } } } if (o->silhouette) { for (i = 0; i < top->wall.nel; i++) { ??? f = top->wall[i]; ??? a = f.pa; ??? c = o->color; ??? t = o->opacity; { if ((SilhouetteWalls(a)) && (NOT f->exists)) { WriteOffWall(((f.node^).nel),f,c,t); } } } } fclose(wr); } /* END WriteOff */ Options_t *GetOptions(int argc, char **argv) { 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, "-inFileTp"); o->inFileTp = argparser_get_next(pp); argparser_get_keyword(pp, "-inFileSt3"); o->inFileSt3 = argparser_get_next(pp); if ((argparser_keyword_present(pp, "-outFile"))) { o->outFile = argparser_get_next(pp) } else { o->outFile = o->inFileTp } o->all = argparser_keyword_present(pp, "-all"); argparser_get_keyword(pp, "-format"); o->formatName = argparser_get_next(pp); if (0 == strcmp(o->formatName, "skel"))) { o->format = Format.Skel } else if (0 == strcmp(o->formatName, "off"))){ o->format = Format.Off } else { argparser_error(pp, "Bad format \"" & argparser_get_next(pp) & "\"\n") } if ((argparser_keyword_present(pp, "-silhouette"))) { o->silhouette = TRUE; if ((argparser_keyword_present(pp, "-color"))) { for (j = 0; j < 3; j++) { o->color[j] = pp.getNextReal(0.0,1.0); } } else { o->color = (frgb_t){1.0,1.0,0.75}; } if ((argparser_keyword_present(pp, "-opacity"))) { o->opacity = pp.getNextReal(0.0,1.0); } else { o->opacity = 0.85; } } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr,"Usage: TriangToGeom \\\n"); fprintf(stderr," -inFileTp -inFileSt3 \\\n"); fprintf(stderr," [-outFile ] [-all] \\\n"); fprintf(stderr," -format { skel | off }\n"); fprintf(stderr," [ -silhouette [ -color | -opacity ] ]\n"); END¦ } } return o; } /* END GetOptions */ /* end TriangToGeom */ /* Copyright © 2000 Universidade Estadual de Campinas (UNICAMP) */