void data_to_triangulation( TriangulationData *data, Triangulation **manifold_ptr) { /* * We assume the UI has done some basic error checking * on the data, so we don't repeat it here. */ Triangulation *manifold; Tetrahedron **tet_array; Cusp **cusp_array; Boolean cusps_are_given; int i, j, k, l, m; Boolean all_peripheral_curves_are_zero, finite_vertices_are_present; /* * Initialize *manifold_ptr to NULL. * We'll do all our work with manifold, and then copy * manifold to *manifold_ptr at the very end. */ *manifold_ptr = NULL; /* * Allocate and initialize the Triangulation structure. */ manifold = NEW_STRUCT(Triangulation); initialize_triangulation(manifold); /* * Allocate and copy the name. */ manifold->name = NEW_ARRAY(strlen(data->name) + 1, char); strcpy(manifold->name, data->name); /* * Set up the global information. * * The hyperbolic structure is included in the file only for * human readers; here we recompute it from scratch. */ manifold->num_tetrahedra = data->num_tetrahedra; manifold->solution_type[complete] = not_attempted; manifold->solution_type[ filled ] = not_attempted; manifold->orientability = data->orientability; manifold->num_or_cusps = data->num_or_cusps; manifold->num_nonor_cusps = data->num_nonor_cusps; manifold->num_cusps = manifold->num_or_cusps + manifold->num_nonor_cusps; /* * Allocate the Tetrahedra. * Keep pointers to them on a temporary array, so we can * find them by their indices. */ tet_array = NEW_ARRAY(manifold->num_tetrahedra, Tetrahedron *); for (i = 0; i < manifold->num_tetrahedra; i++) { tet_array[i] = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(tet_array[i]); INSERT_BEFORE(tet_array[i], &manifold->tet_list_end); } /* * If num_or_cusps or num_nonor_cusps is nonzero, allocate the Cusps. * Keep pointers to them on temporary arrays, so we can find them * by their indices. * Otherwise we will create arbitrary Cusps later. */ cusps_are_given = (data->num_or_cusps != 0) || (data->num_nonor_cusps != 0); if (cusps_are_given == TRUE) { cusp_array = NEW_ARRAY(manifold->num_cusps, Cusp *); for (i = 0; i < manifold->num_cusps; i++) { cusp_array[i] = NEW_STRUCT(Cusp); initialize_cusp(cusp_array[i]); INSERT_BEFORE(cusp_array[i], &manifold->cusp_list_end); } }
void create_one_cusp( Triangulation *manifold, Tetrahedron *tet, Boolean is_finite, VertexIndex v, int cusp_index) { Cusp *cusp; IdealVertex *queue; int queue_first, queue_last; Tetrahedron *tet1, *nbr; VertexIndex v1, nbr_v; FaceIndex f; /* * Create the cusp, add it to the list, and set * the is_finite and index fields. */ cusp = NEW_STRUCT(Cusp); initialize_cusp(cusp); INSERT_BEFORE(cusp, &manifold->cusp_list_end); cusp->is_finite = is_finite; cusp->index = cusp_index; /* * We don't set the topology, is_complete, m, l, holonomy, * cusp_shape or shape_precision fields. * * For "real" cusps the calling routine may * * (1) call peripheral_curves() to set the cusp->topology, * * (2) keep the default values of cusp->is_complete, * cusp->m and cusp->l as set by initialize_cusp(), and * * (3) let the holonomy and cusp_shape be computed automatically * when hyperbolic structure is computed. * * Alternatively, the calling routine may set these fields in other * ways, as it sees fit. * * If we were called by create_fake_cusps(), then the above fields * are all irrelevant and ignored. */ /* * Set the tet->cusp field at all vertices incident to the new cusp. */ /* * Allocate space for a queue of pointers to the IdealVertices. * Each IdealVertex will appear on the queue at most once, so an * array of length 4 * manifold->num_tetrahedra will suffice. */ queue = NEW_ARRAY(4 * manifold->num_tetrahedra, IdealVertex); /* * Set the cusp of the given IdealVertex... */ tet->cusp[v] = cusp; /* * ...and put it on the queue. */ queue_first = 0; queue_last = 0; queue[0].tet = tet; queue[0].v = v; /* * Start processing the queue. */ do { /* * Pull an IdealVertex off the front of the queue. */ tet1 = queue[queue_first].tet; v1 = queue[queue_first].v; queue_first++; /* * Look at the three neighboring IdealVertices. */ for (f = 0; f < 4; f++) { if (f == v1) continue; nbr = tet1->neighbor[f]; nbr_v = EVALUATE(tet1->gluing[f], v1); /* * If the neighbor's cusp hasn't been set... */ if (nbr->cusp[nbr_v] == NULL) { /* * ...set it... */ nbr->cusp[nbr_v] = cusp; /* * ...and add it to the end of the queue. */ ++queue_last; queue[queue_last].tet = nbr; queue[queue_last].v = nbr_v; } } } while (queue_first <= queue_last); /* * Free the memory used for the queue. */ my_free(queue); }