void choose_generators( Triangulation *manifold, Boolean compute_corners, Boolean centroid_at_origin) { /* * To compute the corners we need some sort of geometric structure. */ if (compute_corners == TRUE && manifold->solution_type[filled] == not_attempted) uFatalError("choose_generators", "choose_generators.c"); /* * For each Tetrahedron tet, set tet->flag to unknown_orientation * to indicate that the Tetrahedron has not yet been visited, and * set each tet->generator_status[i] to unassigned_generator to * indicate that no generator has yet been assigned to any face. */ initialize_flags(manifold); /* * Start a recursion which visits each tetrahedron, assigns * generators to its faces, and recursively visits any unvisited * neighbors. */ visit_tetrahedra(manifold, compute_corners, centroid_at_origin); /* * The number_of_generators should be one plus the number of tetrahedra. */ if (manifold->num_generators != manifold->num_tetrahedra + 1) uFatalError("choose_generators", "choose_generators"); /* * At this point we have a valid set of generators, but it's * not as simple as it might be. We'll perform two types of * simplifications. First we need to count how many of the * faces incident to each EdgeClass correspond to active generators. * Initialize all the active_relation flags to TRUE while we're at it. */ count_incident_generators(manifold); /* Now look for EdgeClasses in the Triangulation (2-cells in the * dual complex) which show that a single generator is homotopically * trivial, and eliminate the trivial generator. Topologically, this * corresponds to folding together two adjacent triangular faces * on the boundary of the fundamental domain (the close-the-book * move). Geometrically, this corresponds to realizing that two * faces of the (geometric) fundamental domain are in fact already * superimposed on each other. In Heegaard terms, it's a handle * cancellation. */ eliminate_trivial_generators(manifold); /* * At this point the boundary of the fundamental domain is likely * to contain groups of faces which are essentially n-gons (n > 3) * arbitrarily divided into triangles. The generators for such * triangular faces are all equivalent, and can be merged. They * can be recognized by looking for EdgeClasses with exactly two * incident (and distinct) generators. */ merge_equivalent_generators(manifold); }
void choose_generators( Triangulation *manifold, Boolean compute_corners, Boolean centroid_at_origin) { /* * To compute the corners we need some sort of geometric structure. */ if (compute_corners == TRUE && manifold->solution_type[filled] == not_attempted) uFatalError("choose_generators", "choose_generators.c"); /* * For each Tetrahedron tet, set tet->flag to unknown_orientation * to indicate that the Tetrahedron has not yet been visited, and * set each tet->generator_status[i] to unassigned_generator to * indicate that no generator has yet been assigned to any face. */ initialize_flags(manifold); /* * Start a recursion which visits each tetrahedron, assigns * generators to its faces, and recursively visits any unvisited * neighbors. */ visit_tetrahedra(manifold, compute_corners, centroid_at_origin); /* * The number_of_generators should be one plus the number of tetrahedra. */ if (manifold->num_generators != manifold->num_tetrahedra + 1) uFatalError("choose_generators", "choose_generators.c"); /* * At this point we have a valid set of generators, but it's * not as simple as it might be. We'll perform two types of * simplifications. First we need to count how many of the * faces incident to each EdgeClass correspond to active generators. * Initialize all the active_relation flags to TRUE while we're at it. */ count_incident_generators(manifold); /* * Now look for EdgeClasses in the Triangulation (2-cells in the * dual complex) which show that a single generator is homotopically * trivial, and eliminate the trivial generator. Topologically, this * corresponds to folding together two adjacent triangular faces * on the boundary of the fundamental domain (the close-the-book * move). Geometrically, this corresponds to realizing that two * faces of the (geometric) fundamental domain are in fact already * superimposed on each other. In Heegaard terms, it's a handle * cancellation. */ eliminate_trivial_generators(manifold); /* * At this point the boundary of the fundamental domain is likely * to contain groups of faces which are essentially n-gons (n > 3) * arbitrarily divided into triangles. The generators for such * triangular faces are all equivalent, and can be merged. They * can be recognized by looking for EdgeClasses with exactly two * incident (and distinct) generators. */ merge_equivalent_generators(manifold); /* * 2008/6/12 JRW * * Eliminate relations with zero generators. * * How can such relations arise? * * Under normal operation, eliminate_trivial_generators() finds an active generator * whose dual 2-cell is incident to an EdgeClass whose other incident 2-cells are * all dual to inactive generators (i.e. they lie in the interior * of the fundamental domain). The EdgeClass's relation (of length 1) cancels * the generator and all is well. One may visualize this operation as taking * two adjacent triangles on the boundary of the fundamental domain, which share * a common edge, and gluing them together via a "close-the-book move". * * Now consider two adjacent triangles (still on the boundary of the fundamental * domain) that share two common edges -- in effect a sort of triangular "pita pocket" * with two closed edges and one open edge. When eliminate_trivial_generators() * cancels the generator (dual to the triangular face) against one of the * incident EdgeClasses, the other EdgeClass is left with zero generators, * and may be eliminated. * * Note: Thinking in term of truncated tetrahedra, the above description seems * to imply that the boundary component at the tip of the pita pocket * between the two "closed edges" becomes a spherical boundary component * of the manifold. This suggests that this case would arise for finite * triangulations (as opposed to ideal triangulations), or for highly degenerate * ideal triangulations, but I confess that I haven't thought this through carefully. */ eliminate_empty_relations(manifold); }