Exemple #1
0
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);
}