#define PROG_NAME "BarySubdivision" #define PROG_DESC "???" #define PROG_VERS "1.0" #define BarySubdivision_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* This program builds the "barycentric subdivision" of one topology (".tp" file) of any given 3D map (without boundary or with boundary). In the case of maps with boundary, this program only considers 3D maps with Degree Ring Wall (top->drf) equal to two. So, the compute of a second bary- center subdivision for this case isn't contemplating. . Added the option "net" for simulate textures on existing walls with thin cylinders and small spheres. */ #include #include #include #include #include #define _GNU_SOURCE #include #include #include #include #include CONST double order = 2; mid == 1; TYPE typedef struct Options_t { char *inFile; /* Initial guess file name (minus ".tp") */ char *outFile; /* Output file name prefix */ bool_t fixed; /* Retains the previous geometry */ bool_t net; /* Implements the net walls */ } void DoIt() REF Place_vec_t ps ; nvv,nve,nvf,nvp: uint =0; /* number of node of types "VV","VE","VF"*/ /* and "VP" in the new topology. */ { 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->inFile); ??? top = tc.top; ??? rc = Triangulation.ReadState(o->inFile); ??? c = rc^; ??? NFE = top->wall.nelE; ??? vlt = "VP"; ??? vlf = "VF"; { Place_vec_t ps = Place_vec_new(NFE); fprintf(stderr, "Subdividing from: " & o->inFile & ".tp\n"); for (i = 0; i < NFE; i++) { ??? aposp = PposP(top->wedge[i]); ??? apneg = PnegP(top->wedge[i]; { if ((aposp != NULL) && (apneg #NULL)) { /* Make one Topological tetrahedron of 2x2 order, for each wedge in the topology and set the atributes "ca" for each original wedge. */ ps[i] = Bary.MakeWedge(order,order); ??? fes = NARROW(PWedge(ps[i]), Bary.wedge); double fet = PWedge(top->wedge[i]); ??? fn = fet.wall->num; ??? en = fet.edge->num; Node_t on = OrgV(top->wedge[i]); Node_t dn = OrgV(Clock(top->wedge[i])); ??? ovr = on.radius; ??? ovc = on.color; ??? ovt = on.transp; ??? ovl = on.label; ??? ove = on->exists; ??? dvr = dn.radius; ??? dvc = dn.color; ??? dvt = dn.transp; ??? dvl = dn.label; ??? dve = dn->exists; ??? era = top->edge[en].radius; ??? eco = top->edge[en].color; ??? eta = top->edge[en].transp; ??? eex = top->edge[en]->exists; ??? ero = top->edge[en]->root; ??? fco = top->wall[fn].color; ??? fta = top->wall[fn].transp; ??? fex = top->wall[fn]->exists; ??? fro = top->wall[fn]->root { assert(Octf.OrientationBit(top->wedge[i]) == 0); fet.ca = fes.ca; SetDual (fet.ca.el[3],vlt,vlf,FALSE,TRUE); SetPrimal(fet.ca.el[0],ovr,ovc,ovt,ovl,ove,dvr,dvc, dvt,dvl,dve,era,eco,eta,eex,ero,fco,fta, fex,fro,FALSE,TRUE,o->net); } } } } if ((! IsMapWithBorder(top))) { for (i = 0; i < NFE; i++) { ??? pa = top->wedge[i]; { GlueTetra(pa) } } /* Set the origins for all wedges in the triangulation */ ??? newtop = MakeElemTable(PWedge(top->wedge[NFE-1]).ca.el[1]); ??? nc = GenCoords(newtop)^; ??? com = "Subdivided from: " & o->inFile & ".tp\n" &"Created by Barycenter Subdivision: "&o->outFile \ ".tp on " & Today(); { for (i = 0; i < newtop.node.nel; i++) { ??? v = NARROW(newtop.node[i], Node); char *vl = v.label; { if (( Text.Equal(vl,"VV"))){ nvv++; } else if (0 == strcmp(vl,"VE"))){ nve++; } else if (0 == strcmp(vl,"VF"))){ nvf++; } else if (0 == strcmp(vl,"VP"))){ nvp++; } } } assert(newtop.node.nel == nvv + nve + nvf + nvp); assert(newtop.node.nel == top->node.nel + top->NE + top->wall.nel + top->cell.nel); assert(newtop.wall.nel == 8 * top->wall.nelE); assert(newtop.wedge.nel == 24 * top->wall.nelE); assert(newtop.cell.nel == 4 * top->wall.nelE); if (o->net) { /* we compute the number of existing walls in the previus topology. */ VAR nefp: uint = 0; /* existing walls in the previus topology */ neep: uint = 0; /* existing @{edge->?}s in the previus topology */ nevp: uint = 0; /* existing vert. in the previus topology */ neea: uint = 0; /* existing @{edge->?}s in the actual topology */ neva: uint = 0; /* existing vert. in the actual topology */ { for (i = 0; i < top->wall.nel; i++) { ??? f = top->wall[i]; { if (f->exists){ nefp++;} } } for (i = 0; i < top->NE; i++) { ??? e = top->edge[i]; { if (e->exists){ neep++; } } } for (i = 0; i < top->node.nel; i++) { Node_t v = OrgV(top->node.el[i]); { if (v->exists){ nevp++; } } } for (i = 0; i < newtop.edge.nel; i++) { ??? e = newtop.edge[i]; { if (e->exists){ neea++;} } } /*assert(neea == 2 * top->der * nefp + 2 * neep);*/ for (i = 0; i < newtop.node.nel; i++) { ??? v = newtop.node[i]; { if (v->exists){ neva++;} } } /*assert(neva == nevp + neep + nefp);*/ } } if (o->fixed) { /* compute new coordinates for nodes of type "VV" and "VE". */ for (j = 0; j < top->wall.nelE; j++) { ??? a = top->wedge[j]; Node_t ou = OrgV(a)->num; Node_t ov = OrgV(Clock(a))->num; Node_t nu = OrgV(Bary_Bary_Corner(a))->num; Node_t nv = OrgV(Bary_Bary_Corner(Clock(a)))->num; Node_t nx = OrgV(Clock(Bary_Bary_Corner(a)))->num; { nc[nu] = c[ou]; nc[nv] = c[ov]; nc[nx] = r4_Scale(0.5, r4_Add(c[ou], c[ov])); } } /* compute new coordinates for nodes of type "VF". */ for (j = 0; j < top->wall.nel; j++) { ??? a = top->wall[j].pa; Node_t uu = OrgV(Clock(Bary_Bary_Corner(Srot(a))));/* type VF */ ??? un = (Node_t)(uu); ??? ul = un.label; { assert0 == strcmp(ul,"VF")); nc[un->num] = Triangulation.WallBarycenter(a,c); } } /* compute new coordinates for nodes of type "VP". */ for (j = 0; j < top->cell.nel; j++) { ??? a = Srot(top->cell[j]); ??? p = Triangulation.MakeCellTopology(a); Place_t b = Tors(a); Node_t uu = OrgV(Bary_Bary_Corner(Srot(b))); ??? un = (Node_t)(uu); { r4_t ba = (r4_t){0.0,0.0,0.0,0.0}; VAR { for (k = 0; k < p.NV; k++) { ??? ver = p.vRef[k]; Node_t num = OrgV(ver)->num; { ba = r4_Add(ba,c[num]); } } nc[un->num] = r4_Scale(1.0/FLOAT(p.NV,double),ba); } } } } WriteTopology(o->outFile, newtop, com); if (! o->fixed) { WriteState(o->outFile, newtop, nc, com \ "\nRandom Geometry"); } else { WriteState(o->outFile, newtop, nc, com \ "\nFixed Geometry"); } WriteMaterials(o->outFile, newtop, com); /* unmark all the wedges */ for (i = 0; i < NFE; i++) { ??? fet = PWedge(top->wedge[i]); { fet.marks = FALSE; } } }; /***************************************************************** 3D maps with boundary ******************************************************************/ } else if ((IsMapWithBorder(top))){ for (i = 0; i < NFE; i++) { ps[i] = Bary.MakeWedge(mid,order); ??? fes = NARROW(PWedge(ps[i]),Bary.wedge); double fet = PWedge(top->wedge[i]); { fet.ca = fes.ca; } } /* Now, set the attributes for the a topological tetrahedron correspondly to the @place "a", and the tetrahedron correspondly to the adjacent @place "aFnext" */ for (i = 0; i < NFE; i++) { ??? fet = PWedge(top->wedge[i]); ??? fn = fet.wall->num; ??? en = fet.edge->num; Node_t on = OrgV(top->wedge[i]); Node_t dn = OrgV(Clock(top->wedge[i])); ??? ovr = on.radius; ??? ovc = on.color; ??? ovt = on.transp; ??? ovl = on.label; ??? ove = on->exists; ??? dvr = dn.radius; ??? dvc = dn.color; ??? dvt = dn.transp; ??? dvl = dn.label; ??? dve = dn->exists; ??? era = top->edge[en].radius; ??? eco = top->edge[en].color; ??? eta = top->edge[en].transp; ??? eex = top->edge[en]->exists; ??? ero = top->edge[en]->root; ??? fco = top->wall[fn].color; ??? fta = top->wall[fn].transp; ??? fex = top->wall[fn]->exists; ??? fro = top->wall[fn]->root; ??? pa = top->wedge[i]; Place_t paf = NextF(pa); Wedge_t fef = PWedge(NextF(pa)); { if ((! fet.marks) && ((PposP(pa) == PnegP(paf)))) { if ((PposP(pa)!=NULL)) { SetDual (fet.ca.el[3],vlt,vlf,TRUE,FALSE); SetPrimal(fet.ca.el[0],ovr,ovc,ovt,ovl,ove,dvr,dvc, dvt,dvl,dve,era,eco,eta,eex,ero,fco,fta, fex,fro,TRUE,FALSE,o->net); fet.marks = TRUE; } } if (! fef.marks) { SetDual (fet.ca.el[3],vlt,vlf,TRUE,TRUE); SetPrimal(fet.ca.el[0],ovr,ovc,ovt,ovl,ove,dvr,dvc, dvt,dvl,dve,era,eco,eta,eex,ero,fco,fta, fex,fro,TRUE,TRUE,o->net); fef.marks = TRUE; } } }; for (i = 0; i < NFE; i++) { ??? pa = top->wedge[i]; { GlueTetraBr(pa) } } ??? newtop = MakeElemTable(PWedge(top->wedge[NFE-1]).ca.el[1]); ??? nc = GenCoords(newtop)^; char *com = "Subdivided from: " & o->inFile & ".tp\n" &"Created by Barycenter Subdivision: "&o->outFile \ ".tp on " & Today(); { /* checks */ for (i = 0; i < newtop.node.nel; i++) { ??? v = NARROW(newtop.node[i], Node); double vl = v.label; { if (0 == strcmp(vl,"VV"))){ nvv++; } else if (0 == strcmp(vl,"VE"))){ nve++; } else if (0 == strcmp(vl,"VF"))){ nvf++; } else if (0 == strcmp(vl,"VP"))){ nvp++; } } } assert(newtop.node.nel == nvv + nve + nvf + nvp); assert(newtop.node.nel == top->node.nel + top->NE + top->wall.nel + top->cell.nel); if (o->fixed) { for (j = 0; j < top->wall.nelE; j++) { ??? a = top->wedge[j]; Node_t ou = OrgV(a)->num; Node_t ov = OrgV(Clock(a))->num; Node_t nu = OrgV(Bary_Bary_Corner(a))->num; Node_t nv = OrgV(Bary_Bary_Corner(Clock(a)))->num; Node_t nx = OrgV(Clock(Bary_Bary_Corner(a)))->num; Node_t u = OrgV(Bary_Bary_Corner(Srot(a))); ??? un = u->num; Node_t v = OrgV(Bary_Bary_Corner(Tors(a))); ??? vn = v->num; { nc[nu] = c[ou]; nc[nv] = c[ov]; nc[nx] = r4_Scale(0.5, r4_Add(c[ou], c[ov])); ??? u = (Node_t)(u); { double ul = u.label; double v = (Node_t)(v); double vl = v.label DO assert0 == strcmp(ul,"VF")); nc[un] = Triangulation.WallBarycenter(a,c); assert0 == strcmp(vl,"VP")); nc[vn] = Triangulation.Barycenter(top,c, TRUE); } } } } WriteTopology(o->outFile, newtop, com); if (! o->fixed) { WriteState(o->outFile, newtop, nc, com \ "\nRandom Geometry"); } else { WriteState(o->outFile, newtop, nc, com \ "\nFixed Geometry"); } WriteMaterials(o->outFile, newtop, com); /* unmark all the wedges, only for the case (top->bd==1) */ for (i = 0; i < NFE; i++) { ??? fet = PWedge(top->wedge[i]); { fet.marks = FALSE; } } } } return 0; } void GlueTetra(Place_t @p) /* Glues the topological tetrahedra such as the topology. */ { assert(PBits(a) == 0); Place_t b = NextF(a); Place_t c = PrevF(a); Place_t d = NextE(a); Place_t e = PrevE(a); { ??? aa = Bary_Corner(a); ??? bb = Bary_CCorner(b); { if (bb != aa) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(bb, aa, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(a, bb); Bary_SetCorner(Spin(Clock(a)), Bary_CCorner(Spin(Clock(b)))); } } ??? cc = Bary_Corner(c); ??? dd = Bary_CCorner(a); { if (dd != cc) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(dd, cc, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(c, dd); Bary_SetCorner(Spin(Clock(c)), Bary_CCorner(Spin(Clock(a)))); } } ??? ee = Bary_Corner(Srot(d)); ??? ff = Bary_CCorner(Srot(a)); { if (ff != ee) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(ff, ee, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(Srot(d), ff); Bary_SetCorner(Spin(Tors(d)), Bary_CCorner(Spin(Tors(a)))); } } ??? gg = Bary_Corner(Srot(a)); ??? hh = Bary_CCorner(Srot(e)); { if (gg != hh) { EVAL Triangulation.Glue(hh, gg, order, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(Srot(a), hh); Bary_SetCorner(Spin(Tors(a)), Bary_CCorner(Spin(Tors(e)))); } } } } /* END GlueTetra */ void GlueTetraBr(Place_t @p) /* Glueing the topological tetrahedra such as the topology. */ { assert(PBits(a) == 0); Place_t e = PrevE(a); Place_t b = NextF(a); { ??? gg = Bary_Corner(Srot(a)); ??? hh = Bary_CCorner(Srot(e)); { if ((a != e) && (gg != hh)) { EVAL Triangulation.Glue(hh, gg, mid, TRUE); /* Update Corners to mark this places as glued */ Bary_SetCorner(Srot(a), hh); Bary_SetCorner(Spin(Tors(a)), Bary_CCorner(Spin(Tors(e)))); } } ??? aa = Bary_Corner(a); ??? bb = Bary_CCorner(b); { if ((a#b) && (bb != aa) && ((PposP(a) == PnegP(NextF(a))))) { if ((PnegP(a)!=NULL)) { /* Not yet glued, glue it: */ EVAL Triangulation.Glue(bb, aa, order, TRUE); Bary_SetCorner(a,bb); Bary_SetCorner(Spin(Clock(a)), Bary_CCorner(Spin(Clock(b)))); } } } } } /* END GlueTetraBr */ void SetPrimal(Place_t @p, /* @place hanged on topological tetrahedron 2x2 or 1x2 */ REAL ovr; /* origen node radius */ ovc: frgb_t; /* origen node color */ ovt: frgb_t; /* origen node transparency */ char *ovl; /* origen node label */ bool_t ove; REAL dvr; /* destine node radius */ dvc: frgb_t; /* destine node color */ dvt: frgb_t; /* destine node transparency */ char *dvl; /* destine node label */ bool_t dve; REAL era; /* @{edge->?} radius */ eco: frgb_t; /* @{edge->?} color */ eta: frgb_t; /* @{edge->?} transparency */ bool_t eex; /* @{edge->?} exists */ INTEGER ero; /* @{edge->?} root */ fco: frgb_t; /* wall color */ fta: frgb_t; /* wall transparency */ bool_t fex; /* wall exists */ INTEGER fro; /* wall root */ bool_t mid; /* TRUE iff the topological tetrahedron is 1x2 */ bool_t side; /* indicate the side of the topological tetrahedron 1x2 */ bool_t net; /* simulates a grade with thin cylindres and spheres */ ) void SetNode( Node v; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ REAL r; /* radius */ char *l; /* label */ ) { v->exists = e; v.color = c; v.transp = t; v.label = l; v.radius = r; } SetNode; void SetGhostWall(Place_t @p) { Wall_t t = PWall(a) { t->exists = FALSE; } } SetGhostWall; void NewSetTriangle( Place_t b; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ INTEGER r; /* root */ ) { Wall_t f = PWall(b) { f->exists = e; f.color = c; f.transp = t; f->root = r; } } NewSetTriangle; void NewSetEdge( Place_t b; bool_t e; /* exists */ c: frgb_t; /* color */ t: frgb_t; /* transp */ REAL ra; /* radius */ INTEGER ro; /* root */ ) { ??? ee = NARROW(PEdge(b), @{Edge->?}); { ){ ee->exists = e; ee.color = c; ee.transp = t; ee.radius = ra; ee->root = ro; } } NewSetEdge; { /* set the origin of the @place ca.el[0] */ SetNode(OrgV(a), ove, ovc, ovt, ovr, ovl); /* set the origin of the @place Clock(ca.el[0]) */ SetNode(OrgV(Clock(a)), eex, eco, eta, era, "VE"); /* set the edge component of the topological tetrahedron */ NewSetEdge(a, eex, eco, eta, era, ero); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetNode(OrgV(Clock(b)), dve, dvc, dvt, dvr, dvl); NewSetEdge(b, eex, eco, eta, era, ero); } if (! mid) { SetGhostWall(a); SetGhostWall(NextF(a)); NewSetTriangle(PrevF(a), fex, fco, fta, fro); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetGhostWall(b); SetGhostWall(NextF(b)); NewSetTriangle(PrevF(b), fex, fco, fta, fro); } if (net) { Edge_t X = PEdge(PrevE(PrevF(a))); Edge_t Y = PEdge(NextE(PrevF(a))); Place_t Z = Clock(PrevE(NextF(NextE(a)))); Edge_t W = PEdge(NextE(PrevF(Z))); Node_t S = OrgV(PrevE(PrevF(a))); ??? co = (frgb_t){1.00,1.000,0.500}, /* color, transparency and radius */ ??? tp = (frgb_t){0.00,0.000,0.000}, /* of the thin cylinder and sohere*/ double ra = 0.0025 { X->exists = TRUE; Y->exists = TRUE; W->exists = TRUE; S->exists = TRUE; X.color = co; X.radius = ra; X.transp = tp; Y.color = co; Y.radius = ra; Y.transp = tp; W.color = co; W.radius = ra; W.transp = tp; S.color = co; S.radius = ra; S.transp = tp; } } } else if (mid){ if (side) { SetGhostWall(a); NewSetTriangle(PrevF(a), fex, fco, fta, fro); Place_t b = Clock(PrevE(NextF(NextE(a)))); { SetGhostWall(b); NewSetTriangle(PrevF(b), fex, fco, fta, fro); } } else { SetGhostWall(PrevF(a)); NewSetTriangle(a, fex, fco, fta, fro); Place_t an = Clock(PrevE(PrevF(NextE(PrevF(a))))); { SetGhostWall(an); NewSetTriangle(PrevF(an), fex, fco, fta, fro); } } } } /* END SetPrimal */ void SetDual(Place_t @p, char *vlt; char *vlf; bool_t mid; bool_t side; ) void SetNode(Node_t v; char *label) { ??? vv = (Node_t)(v); { ){ vv->exists = FALSE; vv.label = label; } } SetNode; void SetGhostWall(Place_t @p) { Wall_t t = PWall(a) { t->exists = FALSE; } } SetGhostWall; PROCEDURE SetGhostEdge(Place_t @p) == { ??? t = NARROW(PEdge(a), @{Edge->?}); { t->exists = FALSE; } } SetGhostEdge; void SetRowedge(d: Place_t; r: uint) Place_t dn = d; VAR { if (r == 3) { for (j = 0; j < r; j++) { if (j == 0) { for (i = 0; i < r; i++) { SetGhostEdge(dn); dn = NextE(dn); } } dn = PrevF(dn); SetGhostEdge(NextE(dn)); SetGhostEdge(PrevE(dn)); } } else if (r == 2){ for (j = 0; j < r; j++) { if (j == 0) { for (i = 0; i < r; i++) { SetGhostEdge(dn); dn = NextE(dn); } dn = NextE(dn); } dn = PrevF(dn); SetGhostEdge(NextE(dn)); } } } SetRowedge; void SetRowTriangle(b: Place_t) { for (i = 0; i < 3; i++) { SetGhostWall(b); b = PrevF(b); } } SetRowTriangle; { if ((mid) && (side)){ SetNode(OrgV(a), vlf); SetNode(OrgV(Clock(a)), vlt); SetRowTriangle(a); SetRowedge(a,3); } else if ((mid) && (NOT side)){ SetNode(OrgV(a), vlt); SetNode(OrgV(Clock(a)), vlf); SetRowTriangle(a); SetRowedge(a,3); } else if (! mid){ SetNode(OrgV(a), vlt); SetNode(OrgV(Clock(a)), vlf); SetRowTriangle(a); SetRowedge(a,3); Place_t an = PrevE(NextF(NextE(a))); { SetNode(OrgV(an),vlt); SetRowTriangle(an); SetRowedge(Clock(an),2); } } } /* END SetDual */ 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, "-inFile"); o->inFile = argparser_get_next(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); o->fixed = argparser_keyword_present(pp, "-fixed"); o->net = argparser_keyword_present(pp, "-net"); argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: BarySubdivision" \ " -inFile -outFile \\\n" \ " [ -fixed ] [ -net ] \n"); END¦ } } return o; } /* END GetOptions */ bool_t IsMapWithBorder(ElemTableRec_t *top) { for (i = 0; i < top->wall.nelE; i++){ ??? a = top->wedge[i]; ??? n = PnegP(a); ??? p = PposP(a); { if ((n == NULL) && (p == NULL)){ return TRUE; }; } } return FALSE; } /* END IsMapWithBorder */ { DoIt() } BarySubdivision. /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP) */ Bary_Corner Bary_CCorner Bary_SetCorner