#define PROG_NAME "MakeComplex" #define PROG_DESC "Creates various 3D maps for testing" #define PROG_VERS "1.0" /* Last edited on 2024-11-20 06:05:17 by stolfi */ #define MakeComplex_C_COPYRIGHT \ "Copyright © 2001 Universidade Estadual de Campinas (UNICAMP)" #define PROG_HELP \ " " PROG_NAME " \\\n" \ " -shape { Seifert | Poincare | .. } \\\n" \ " -order {NUM} [ -open ] \\\n" \ " [ -fixed [ -flat ] ] \\\n" \ " -output {NAME}" #define PROG_INFO \ "NAME\n" \ " " PROG_NAME " - " PROG_DESC "\n" \ "\n" \ "SYNOPSIS\n" \ PROG_HELP "\n" \ "\n" \ "DESCRIPTION\n" \ "\n" \ "MakeBipyramid.c:\n" \ "\n" \ " Generates \".tp\", \".tb\", \".ma\" and \".st\" files for" \ " simple 3D maps called /bipyramids/.\n" \ "\n" \ " A /simple/ bipyramid of order {n} consists of {n} tetrahedral" \ " cells sharing a common edge. With {n == 4} one obtains the" \ " regular octahedron, sliced into four tetrahedra.\n" \ "\n" \ " An /elongated/ bipyramid has a ring of {2*n} triangles" \ " inserted between the two pyramids, shaped as an antiprism" \ " without the top and bottom {n}-gons. With {n == 5}" \ " one obtains the regular icosahedron.\n" \ "\n" \ "\n" \ "MakeComplex.c:\n" \ "\n" \ "This program generates \".tp\",\".tb\",\".st\" and \".ma\" files for some\n" \ "simples tridimensional maps homeomorphics to three-manifolds. The\n" \ "node coordinates are random numbers in [-1..+1].\n" \ "\n" \ "The maps builds through the {MakeComplex} program results in dege-\n" \ "neracies. So, is necessary submit these resulting maps to aditional\n" \ "procedures for remove such degeneracies, such as the {BarySubdivision}\n" \ "and {SelectSubdivision} procedures.\n" \ "\n" \ "MakeManifold.c:\n" \ "\n" \ "This program generates \".tp\",\".tb\",\".st\" and \".ma\" files for some sim-\n" \ "ples tridimensional maps with topologies of three-manifolds, such as,\n" \ "the Hypersphere S^{3} and the Hypertorus T^{3}. The node coordinates\n" \ "are random numbers in [-1..+1].\n" \ "\n" \ "The difference with the {MakeComplex} program (that also builds 3D maps\n" \ "homeomorphic to 3D manifolds) is that, {MakeComplex} program uses polyhe-\n" \ "dra gluing scheme as a single cell, conversely, {MakeManifold} uses\n" \ "a subdivision or refinement of the cells gluing scheme.\n" \ "\n" \ "The maps builds through the {MakeComplex} program results in degeneracies\n" \ "conversely, {MakeManifold} produces maps that can be not result in degene-\n" \ "racies, depending on the {order} option.\n" \ "\n" \ "MakeObjectTriang.c:\n" \ "\n" \ "files for some simples triangulated\n" \ "and convex objects such as \"sausage\", bidimensional \"torus\" with and with out\n" \ "one twist in R^{4}.\n" \ "\n" \ "MakeElongBip.c:\n" \ "\n" \ "Generates \".tp\",\".tb\",\".ma\" and \".st\" files for some simple 3D" \ "cells called `elongated bipyramids'.\n" \ "\n" \ "MakePlatonic.c:\n" \ "\n" \ "Builds the platonic solid icosahedron and dodecahedron as unique cell," \ " i.e. without cells information\n"\ "\n" \ "MakeRawTetra.c:\n" \ "\n" \ "Creates \".tp\",\".tb\",\".st\" and \".ma\" files for one topological tetrahedron of\n" \ "order {order} with fixed geometry. The nodes of a individually tetra-\n" \ "hedron ({order == 1}) of side length Sqrt(2) be given by a particulary\n" \ "form when the nodes are taken as corners of a cube. One such tetrahedron\n" \ "for a cube of side length 1 gives the tetrahedron of side length Sqrt(2)\n" \ "having nodes: (0,0,0,0), (0,1,1,0), (1,0,1,0), (1,1,0.0).\n" \ "\n" \ "Every topological tetraedron has eight /corner places/ associa-\n" \ "ted to it. Let {a} one place of Interface Triangulation, so we associate\n" \ "the node (0,0,0,0) to {ca.el[0]}; (1,0,1,0) to {ca.el[2]}; (0,1,1,0) to {ca.el[4]}\n" \ "and the node (1,1,0,0) to {ca.el[6]}.\n"\ "\n" \ "OPTIONS\n" \ "\n" \ " -open\n" \ " If this option is present, the last tetrahedron is not glued to the" \ " first one.\n" \ "\n" \ " -fixed\n" \ " If this option is present, the node coordinates are computed" \ " to give a natural shape. Otherwise the node coordinates are set" \ " to random numbers in [-1..+1].\n" \ "\n" \ " -pyramid\n" \ " ???.\n" \ "\n" \ " -elongated\n" \ " ???.\n" \ "\n" \ "DOCUMENTATION OPTIONS\n" \ argparser_help_info_HELP_INFO "\n" \ "\n" \ "SEE ALSO\n" \ " ??? (1).\n" \ "\n" \ "AUTHOR\n" \ " L. A. P. Lozada and J. Stolfi, UNICAMP.\n" \ "\n" \ "MODIFICATION HISTORY\n" \ " 1999 Modula-3 version created by L. A. P. Lozada.\n" \ " 20-05-2000: Emphasized the original elements for drawing purposes.\n" \ " 13-09-2000: Added the option \"pyramid\" for the generation of bipyramids\n" \ " with geometry of pyramids." \ " 24-01-2007 Converted to C and extensively modified by J. Stolfi.\n" \ "\n" \ "WARRANTY\n" \ argparser_help_info_NO_WARRANTY "\n" \ "\n" \ "RIGHTS\n" \ " " MakeComplex_C_COPYRIGHT ".\n" \ "\n" \ argparser_help_info_STANDARD_RIGHTS ".\n" \ "\n" \ "UNINCORPORATED DESCRIPTIONS\n" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _GNU_SOURCE #include #include #include #define Order 1 typedef enum { /* From {MakeComplex.m3}: */ Shape_Sphere3, Shape_Cm2t, Shape_Torus3, Shape_Pseudo, Shape_Seifert, Shape_Poincare, Shape_Lens1, Shape_Lens2, Shape_Lens3, Shape_Lens4, Shape_Lens5, /* From {MakeComplexWf.m3}: */ Shape_Triang, Shape_Tetra1, Shape_Tetra2, Shape_Tetra3, Shape_TetraRe, Shape_CubeTriang, Shape_BigCube, Shape_Octa1, Shape_Octa2, Shape_Octa3, Shape_Pyramid, /* From {MakeGem.m3}: */ Shape_GemProjective, Shape_GemR2420, /* From {MakeManifold.m3}: */ Shape_Sphere1Sub, Shape_Torus3Bis, /* From {MakeNOComplex.m3}: */ Shape_Projective3, /* From {MakeObjectTriang.m3}: */ Shape_Donut, Shape_DoubleDonut, Shape_Sausage, /* From {MakePolygon.m3}: */ Shape_Polygon, /* From {MakeBipyramid.m3}: */ Shape_Bipyramid, /* From {MakeElongBip.m3}: */ Shape_ElongBip, /* From {MakeBigRawCube.m3}: */ Shape_BigRawCube, /* From {MakeRawTetra.m3}: */ Shape_RawTetra, /* From {MakePlatonic.m3}: */ Shape_Icosahedron, Shape_IcosahedronTriang, Shape_Dodecahedron, /* New: */ Shape_Cube } Shape_t; typedef struct Options_t { /* Parameters that define the topology: */ Shape_t shape; /* Topology of complex. */ uint order; /* Multipurpose numeric parameter. */ bool_t open; /* For some shapes: leave some part unglued. */ /* Parameters that define the geometry: */ bool_t fixed; /* TRUE: canonical geometry; FALSE: randomize. */ bool_t flat; /* For some shapes: geometry has a flattened part. */ /* Other parameters: */ char *shapeName; /* The {shape} in string form. */ char *output; /* Prefix for output file names. */ } Options_t; Options_t *GetOptions(int argc, char **argv); Place_t MakeTopo(Shape_t shape, uint order, bool_t open); void MakeGeom ( Random_t *coins, ElemTableRec_t *top, Place_t p, Shape_t shape, uint order, bool_t open, bool_t flat, bool_t fixed, Coords_t *cP, char **cmtP ); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, today()); char *tag = jsprintf ( "-%s-%s", (o->fixed ? "fix" : "rnd"), (o->flat ? "flt" : "sym") ); Place_t m = MakeTopo(o->shape, o->order, o->open); OctfWrite(o->output, tag, Place_vec_desc(&m, 1), topo_cmt); Random_t *coins = MakeRandomSource(4615); ElemTableRec_t top = MakeElemTable(Place_vec_desc(&m, 1)); char *geom_cmt = NULL; Coords_t c = r4_vec_new(0); MakeGeom(coins, &top, m, o->shape, o->order, o->open, o->flat, o->fixed, &c, &geom_cmt); /* Set the root elements for edges and walls */ int i; for (i = 0; i < top.wall.nel; i++) { Wall_t f = PWall(top.wall.el[i]); f->root = f->num; } for (i = 0; i < top.edge.nel; i++) { Edge_t e = PEdge(top.edge.el[i]); e->root = e->num; } /* Print the Betti Number (N-dim Euler number), out of curiosity: */ int betti = 1 - top.node.nel + top.edge.nel - top.wall.nel + top.cell.nel - 1; fprintf(stderr,"Betti number = %d\n", betti); /* Output the complex: */ WriteTopology(o->output, tag, &top, topo_cmt); WriteCoords(o->output, tag, -1, &c, txtcat(topo_cmt, geom_cmt)); /* WriteMaterials(o->output, tag, &top, topo_cmt, FALSE); */ return 0; } Place_t MakeTopo(Shape_t shape, uint order, bool_t open) { /* [!!! Some of these procedures may not work for {order > 1} !!!] */ switch(shape) { /* Form {MakeComplex.m3}: */ case Shape_Sphere3: return MakeSphere3(order); case Shape_Cm2t: return MakeCm2t(order); case Shape_Torus3: return MakeTorus3(order); case Shape_Pseudo: return MakePseudo(); case Shape_Seifert: return MakeSeifert(); case Shape_Poincare: return MakePoincare(); case Shape_Lens1: return MakeLens1(); case Shape_Lens2: return MakeLens2(); case Shape_Lens3: return MakeLens3(); case Shape_Lens4: return MakeLens4(); case Shape_Lens5: return MakeLens5(); /* Form {MakeComplexWf.m3}: */ case Shape_Tetra1: return MakeTetra(); case Shape_Tetra2: return MakeTwoTetra(order); case Shape_Tetra3: return MakeThreeTetra(order); case Shape_TetraRe: return Make12Fold(); case Shape_CubeTriang: return MakeCubeTriang(order); case Shape_BigCube: return MakeBigCube1(order); case Shape_Octa1: return MakeOcta(); case Shape_Octa2: return MakeTwoOctaGlue(); case Shape_Octa3: return MakeThreeOctaGlue(); case Shape_Pyramid: return MakePyram(order); /* Form {MakeGem.m3}: */ case Shape_GemProjective: return MakeGemProjective(); case Shape_GemR2420: return MakeGemR2420(); /* From {MakeManifold.m3}: */ case Shape_Sphere1Sub: return MakeSphere1Sub(order); case Shape_Torus3Bis: return MakeTorus3Bis(order); /* From {MakeNOComplex.m3}: */ case Shape_Projective3: return MakeProjective3(); /* From {MakeObjectTriang.m3}: */ case Shape_Donut: return MakeDonut(order); case Shape_DoubleDonut: return MakeDoubleDonut(order); case Shape_Sausage: return Make1DCubeArrayBis2(order); /* From {MakePolygon.m3}: */ case Shape_Polygon: return PolygonMakeSng(order); /* From {MakeBipyramid.c}: */ case Shape_Bipyramid: return BuildSimpleBipyr(order, open); /* From {MakeElongBip.m3}: */ case Shape_ElongBip: return BuildElongatedBipyr(order); /* From {MakeElongBip.m3}: */ case Shape_RawTetra: return MakeRawTetra(order); /* From {MakeBigRawCube.m3}: */ case Shape_BigRawCube: return BuildBigRawCube1(order, TRUE); /* From {MakePlatonic.m3}: */ case Shape_IcosahedronTriang: return MakeIcosahedronTriang1(); case Shape_Icosahedron: return MakeIcosahedron(); case Shape_Dodecahedron: return MakeDodecahedron(); /* New.m3}: */ case Shape_Cube: return CubeMakeSng(); default: assert(FALSE); return NULL; } } void MakeGeom ( Random_t *coins, ElemTableRec_t *top, Place_t p, Shape_t shape, uint order, bool_t open, bool_t flat, bool_t fixed, Coords_t *cP, char **cmtP ) { Coords_t c = r4_vec_new(top->node.nel); if (! fixed) { InitCoords(coins, &c, 1.0); cmt = "\nRandom Geometry"; } else { switch(shape) { /* From {MakePolygon.m3}: */ case Shape_Polygon: PolygonFixCoords(p, order, &c); break; /* New: */ case Shape_Cube: CubeFixCoords(p, &c, NULL, NULL); break; /* case Shape_RawTetra: */ /* FixCoordsTetra(...); */ /* break; */ case Shape_Bipyramid: case Shape_ElongBip: FixCoordsBipyramid(p, order, flat, top, &c); break; /* case Shape_BigRawCube: */ /* FixBigRawCubeCoords(cd, top, order, &c); */ /* break; */ default: fprintf(stderr, "no fixed geometry available for this shape\n"); InitCoords(coins, &c, 1.0); } cmt = "\nCanonical geometry"; } if (cP->el != NULL) { free(cP->el); } (*cP) = c; if (cmtP != NULL) { (*cmtP) = cmt; } } 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, "-order"); o->order = argparser_get_next_int(pp, 1, 9); o->fixed = argparser_keyword_present(pp, "-fixed"); o->open = argparser_keyword_present(pp, "-open"); argparser_get_keyword(pp, "-shape"); o->shapeName = argparser_get_next(pp); /* Convert shape name to code: */ if (0 == strcmp(o->shapeName, "")) { argparser_error(pp, "empty shape"); } else if (0 == strcmp(o->shapeName, "bigcube")) { o->shape = Shape_BigCube; } else if (0 == strcmp(o->shapeName, "bigrawcube")) { o->shape = Shape_BigRawCube; } else if (0 == strcmp(o->shapeName, "bipyramid")) { o->shape = Shape_Bipyramid; } else if (0 == strcmp(o->shapeName, "cm2t")) { o->shape = Shape_Cm2t; } else if (0 == strcmp(o->shapeName, "cube")) { o->shape = Shape_Cube; } else if (0 == strcmp(o->shapeName, "cubetriang")) { o->shape = Shape_CubeTriang; } else if (0 == strcmp(o->shapeName, "dodecahedron")) { o->shape = Shape_Dodecahedron; } else if (0 == strcmp(o->shapeName, "elongbip")) { o->shape = Shape_ElongBip; } else if (0 == strcmp(o->shapeName, "gem/projective")) { o->shape = Shape_GemProjective; } else if (0 == strcmp(o->shapeName, "gem/r2420")) { o->shape = Shape_GemR2420; } else if (0 == strcmp(o->shapeName, "icosahedron")) { o->shape = Shape_Icosahedron; } else if (0 == strcmp(o->shapeName, "icosatri")) { o->shape = Shape_IcosahedronTriang; } else if (0 == strcmp(o->shapeName, "lens1")) { o->shape = Shape_Lens1; } else if (0 == strcmp(o->shapeName, "lens2")) { o->shape = Shape_Lens2; } else if (0 == strcmp(o->shapeName, "lens3")) { o->shape = Shape_Lens3; } else if (0 == strcmp(o->shapeName, "lens4")) { o->shape = Shape_Lens4; } else if (0 == strcmp(o->shapeName, "lens5")) { o->shape = Shape_Lens5; } else if (0 == strcmp(o->shapeName, "octa1")) { o->shape = Shape_Octa1; } else if (0 == strcmp(o->shapeName, "octa2")) { o->shape = Shape_Octa2; } else if (0 == strcmp(o->shapeName, "octa3")) { o->shape = Shape_Octa3; } else if (0 == strcmp(o->shapeName, "poincare")) { o->shape = Shape_Poincare; } else if (0 == strcmp(o->shapeName, "polygon")) { o->shape = Shape_Polygon; } else if (0 == strcmp(o->shapeName, "projective3")) { o->shape = Shape_Projective3; } else if (0 == strcmp(o->shapeName, "pseudo")) { o->shape = Shape_Pseudo; } else if (0 == strcmp(o->shapeName, "pyramid")) { o->shape = Shape_Pyramid; } else if (0 == strcmp(o->shapeName, "rawtetra")) { o->shape = Shape_RawTetra; } else if (0 == strcmp(o->shapeName, "seifert")) { o->shape = Shape_Seifert; } else if (0 == strcmp(o->shapeName, "sphere1/sub")) { o->shape = Shape_Sphere1Sub; } else if (0 == strcmp(o->shapeName, "sphere3")) { o->shape = Shape_Sphere3; } else if (0 == strcmp(o->shapeName, "tetra1")) { o->shape = Shape_Tetra1; } else if (0 == strcmp(o->shapeName, "tetra2")) { o->shape = Shape_Tetra2; } else if (0 == strcmp(o->shapeName, "tetra3")) { o->shape = Shape_Tetra3; } else if (0 == strcmp(o->shapeName, "tetrare")) { o->shape = Shape_TetraRe ; } else if (0 == strcmp(o->shapeName, "torus3")) { o->shape = Shape_Torus3; } else if (0 == strcmp(o->shapeName, "torus3bis")) { o->shape = Shape_Torus3Bis; } else { argparser_error(pp, "Bad shape name\n"); } argparser_get_keyword(pp, "-output"); o->output = argparser_get_next(pp); argparser_finish(pp); return o; } #define MakeComplex_C_author \ "Modula-3 version created by L.A.P.Lozada in 1999-2000\n" \ "Revisions:\n" \ " xx-xx-1999 : {MakePolygon.m3} implemented by L. A. P. Lozada.\n" \ " 11-11-1999 : {MakePolygon.m3} modified by L. A. P. Lozada.\n" \ " 30-08-2000 : nice version of the {MakeOctahedron} procedure.\n" \ " 31-01-2007 : Split off the shape building procs ({MakePoincare} etc.).\n" \ " 01-02-2007 : Merged {MakeComplexWf.c}, {MakeGem.c}, {MakeManifold.c} into here.\n" \ " 01-02-2007 : Merged {MakeNOComplex.c}, {MakePolygon.c} into here.\n" \ " 01-02-2007 : Merged {MakeElongBip.c}, {MakePlatonic.c}, {MakeRawTetra.c} into here.\n" \ " 02-02-2007 : Merged {MakeBipyramid.c} into here." \