int main(int argc, char* argv[]) { if (argc < 4 || argc > 5) { std::cerr << "Usage: " << argv[0] << " <tri> <m> <l> [output-file]\n"; std::cerr << "Example: " << argv[0] << " m003 -3 1\n"; return 1; } long m = atoi(argv[2]); long l = atoi(argv[3]); int tets; bool orbl; switch (argv[1][0]) { case 'm': tets = 5; orbl = true /* ignored */; break; case 's': tets = 6; orbl = true; break; case 'x': tets = 6; orbl = false; break; case 'v': tets = 7; orbl = true; break; case 'y': tets = 7; orbl = false; break; default: std::cerr << "Cannot interpret triangulation name " << argv[1] << ".\n"; return 1; } Triangulation* tri = GetCuspedCensusManifold(tets, orbl ? oriented_manifold : nonorientable_manifold, atoi(argv[1] + 1)); if (! tri) { std::cerr << "Could not load triangulation " << argv[1] << ".\n"; return 1; } set_cusp_info(tri, 0, 0, m, l); do_Dehn_filling(tri); double vol = volume(tri, 0); Triangulation* filled = fill_cusps(tri, 0, const_cast<char*>("filled"), 1); std::string name = triName(filled, vol); set_triangulation_name(filled, const_cast<char*>(name.c_str())); std::cout << "Writing " << name << "... "; save_triangulation(filled, argc > 4 ? argv[4] : const_cast<char*>(name.c_str())); std::cout << "done.\n"; return 0; }
static Triangulation *try_Dirichlet_to_triangulation( WEPolyhedron *polyhedron) { /* * Implement Plan A as described above. */ Triangulation *triangulation; WEEdge *edge, *nbr_edge, *mate_edge; WEEdgeEnd end; WEEdgeSide side; Tetrahedron *new_tet; FaceIndex f; /* * Don't attempt to triangulate an orbifold. */ if (singular_set_is_empty(polyhedron) == FALSE) return NULL; /* * Set up the Triangulation. */ triangulation = NEW_STRUCT(Triangulation); initialize_triangulation(triangulation); /* * Allocate and copy the name. */ triangulation->name = NEW_ARRAY(strlen(DEFAULT_NAME) + 1, char); strcpy(triangulation->name, DEFAULT_NAME); /* * Allocate the Tetrahedra. */ triangulation->num_tetrahedra = 4 * polyhedron->num_edges; for (edge = polyhedron->edge_list_begin.next; edge != &polyhedron->edge_list_end; edge = edge->next) for (end = 0; end < 2; end++) /* = tail, tip */ for (side = 0; side < 2; side++) /* = left, right */ { new_tet = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet); INSERT_BEFORE(new_tet, &triangulation->tet_list_end); edge->tet[end][side] = new_tet; } /* * Initialize neighbors. */ for (edge = polyhedron->edge_list_begin.next; edge != &polyhedron->edge_list_end; edge = edge->next) for (end = 0; end < 2; end++) /* = tail, tip */ for (side = 0; side < 2; side++) /* = left, right */ { /* * Neighbor[0] is associated to this same WEEdge. * It lies on the same side (left or right), but * at the opposite end (tail or tip). */ edge->tet[end][side]->neighbor[0] = edge->tet[!end][side]; /* * Neighbor[1] lies on the same face of the Dirichlet * domain, but at the "next side" of that face. */ nbr_edge = edge->e[end][side]; if (nbr_edge->v[!end] == edge->v[end]) /* edge and nbr_edge point in the same direction */ edge->tet[end][side]->neighbor[1] = nbr_edge->tet[!end][side]; else if (nbr_edge->v[end] == edge->v[end]) /* edge and nbr_edge point in opposite directions */ edge->tet[end][side]->neighbor[1] = nbr_edge->tet[end][!side]; else uFatalError("Dirichlet_to_triangulation", "Dirichlet_conversion"); /* * Neighbor[2] is associated to this same WEEdge. * It lies at the same end (tail or tip), but * on the opposite side (left or right). */ edge->tet[end][side]->neighbor[2] = edge->tet[end][!side]; /* * Neighbor[3] lies on this face's "mate" elsewhere * on the Dirichlet domain. */ mate_edge = edge->neighbor[side]; edge->tet[end][side]->neighbor[3] = mate_edge->tet [edge->preserves_direction[side] ? end : !end ] [edge->preserves_sides[side] ? side : !side]; } /* * Initialize all gluings to the identity. */ for (edge = polyhedron->edge_list_begin.next; edge != &polyhedron->edge_list_end; edge = edge->next) for (end = 0; end < 2; end++) /* = tail, tip */ for (side = 0; side < 2; side++) /* = left, right */ for (f = 0; f < 4; f++) edge->tet[end][side]->gluing[f] = IDENTITY_PERMUTATION; /* * Set up the EdgeClasses. */ create_edge_classes(triangulation); orient_edge_classes(triangulation); /* * Attempt to orient the manifold. */ orient(triangulation); /* * Set up the Cusps, including "fake cusps" for the finite vertices. * Then locate and remove the fake cusps. If the manifold is closed, * drill out an arbitrary curve to express it as a Dehn filling. * Finally, determine the topology of each cusp (torus or Klein bottle) * and count them. */ create_cusps(triangulation); mark_fake_cusps(triangulation); peripheral_curves(triangulation); remove_finite_vertices(triangulation); count_cusps(triangulation); /* * Try to compute a hyperbolic structure, first for the unfilled * manifold, and then for the closed manifold if appropriate. */ find_complete_hyperbolic_structure(triangulation); do_Dehn_filling(triangulation); /* * If the manifold is hyperbolic, install a shortest basis on each cusp. */ if ( triangulation->solution_type[complete] == geometric_solution || triangulation->solution_type[complete] == nongeometric_solution) install_shortest_bases(triangulation); /* * All done! */ return triangulation; }
static FuncResult drill_one_curve( Triangulation **manifold, MergedMultiLength *remaining_curves) { int i; int num_curves; DualOneSkeletonCurve **the_curves; int desired_index; Complex filled_length; Triangulation *new_manifold; int count; /* * See what curves are drillable. */ dual_curves(*manifold, MAX_DUAL_CURVE_LENGTH, &num_curves, &the_curves); if (num_curves == 0) return func_failed; desired_index = -1; for (i = 0; i < num_curves; i++) { get_dual_curve_info(the_curves[i], NULL, &filled_length, NULL); if ( fabs(remaining_curves->length - filled_length.real) < LENGTH_EPSILON && fabs(remaining_curves->torsion - fabs(filled_length.imag)) < TORSION_EPSILON && ( ( remaining_curves->pos_multiplicity > 0 && filled_length.imag > ZERO_TORSION_EPSILON ) || ( remaining_curves->neg_multiplicity > 0 && filled_length.imag < -ZERO_TORSION_EPSILON ) || ( remaining_curves->zero_multiplicity > 0 && fabs(filled_length.imag) < ZERO_TORSION_EPSILON ) ) ) { desired_index = i; break; } } if (desired_index == -1) { free_dual_curves(num_curves, the_curves); return func_failed; } new_manifold = drill_cusp(*manifold, the_curves[desired_index], get_triangulation_name(*manifold)); if (new_manifold == NULL) { free_dual_curves(num_curves, the_curves); return func_failed; } /* * Usually the complete solution will be geometric, even if * the filled solution is not. But occasionally we'll get * a new_manifold which didn't simplify sufficiently, and * we'll need to rattle it around to get a decent triangulation. */ count = MAX_RANDOMIZATIONS; while (--count >= 0 && get_complete_solution_type(new_manifold) != geometric_solution) randomize_triangulation(new_manifold); /* * Set the new Dehn filling coefficient to (1, 0) * to recover the closed manifold. */ set_cusp_info(new_manifold, get_num_cusps(new_manifold) - 1, FALSE, 1.0, 0.0); do_Dehn_filling(new_manifold); free_dual_curves(num_curves, the_curves); free_triangulation(*manifold); *manifold = new_manifold; new_manifold = NULL; if (filled_length.imag > ZERO_TORSION_EPSILON) remaining_curves->pos_multiplicity--; else if (filled_length.imag < -ZERO_TORSION_EPSILON) remaining_curves->neg_multiplicity--; else remaining_curves->zero_multiplicity--; remaining_curves->total_multiplicity--; return func_OK; }