void p2tr_cdt_validate_edges (P2trCDT *self) { P2trHashSetIter iter; P2trEdge *e; p2tr_hash_set_iter_init (&iter, self->mesh->edges); while (p2tr_hash_set_iter_next (&iter, (gpointer*)&e)) { if (! e->constrained && e->tri == NULL) p2tr_exception_geometric ("Found a non constrained edge without a triangle"); if (e->tri != NULL) { gboolean found = FALSE; gint i = 0; for (i = 0; i < 3; i++) if (e->tri->edges[i] == e) { found = TRUE; break; } if (! found) p2tr_exception_geometric ("An edge has a triangle to which it does not belong!"); } } }
/** * Insert a point so that is splits an existing edge. This function * assumes that the point is on the edge itself and between its * end-points. * If the edge being split is constrained, then the function returns a * list containing both parts resulted from the splitting. In that case, * THE RETURNED EDGES MUST BE UNREFERENCED! */ GList* p2tr_cdt_split_edge (P2trCDT *self, P2trEdge *e, P2trPoint *C) { /* W * /|\ * / | \ * / | \ E.Mirror.Tri: YXW * X*---*---*Y E: X->Y * \ |C / E.Tri: XYV * \ | / * \|/ * V */ P2trPoint *X = P2TR_EDGE_START (e), *Y = e->end; P2trPoint *V = (e->tri != NULL) ? p2tr_triangle_get_opposite_point(e->tri, e) : NULL; P2trPoint *W = (e->mirror->tri != NULL) ? p2tr_triangle_get_opposite_point (e->mirror->tri, e->mirror) : NULL; gboolean constrained = e->constrained; P2trEdge *XC, *CY; GList *new_tris = NULL, *fan = NULL, *new_edges = NULL; p2tr_edge_remove (e); XC = p2tr_mesh_new_edge (self->mesh, X, C, constrained); CY = p2tr_mesh_new_edge (self->mesh, C, Y, constrained); fan = p2tr_utils_new_reversed_pointer_list (4, W, X, V, Y); new_tris = p2tr_cdt_triangulate_fan (self, C, fan); g_list_free (fan); /* Now make this a CDT again * The new triangles will be unreffed by the flip_fix function, which * is good since we receive them with an extra reference! */ p2tr_cdt_flip_fix (self, new_tris); g_list_free (new_tris); if (constrained) { /* If this was a subsegment, then both parts of the subsegment * should exist */ if (p2tr_edge_is_removed (XC) || p2tr_edge_is_removed (CY)) p2tr_exception_geometric ("Subsegments gone!"); else { new_edges = g_list_prepend (new_edges, CY); new_edges = g_list_prepend (new_edges, XC); } } else { p2tr_edge_unref (XC); p2tr_edge_unref (CY); } p2tr_cdt_on_new_point (self, C); return new_edges; }
void p2tr_cdt_validate_cdt (P2trCDT *self) { P2trHashSetIter iter; P2trTriangle *tri; p2tr_hash_set_iter_init (&iter, self->mesh->triangles); while (p2tr_hash_set_iter_next (&iter, (gpointer*)&tri)) if (! p2tr_cdt_has_empty_circum_circle(self, tri)) p2tr_exception_geometric ("Not a CDT!"); }
P2trPoint* p2tr_cdt_insert_point (P2trCDT *self, const P2trVector2 *pc, P2trTriangle *point_location_guess) { P2trTriangle *tri; P2trPoint *pt; gboolean inserted = FALSE; gint i; P2TR_CDT_VALIDATE_UNUSED (self); if (point_location_guess == NULL) tri = p2tr_mesh_find_point (self->mesh, pc); else tri = p2tr_mesh_find_point_local (self->mesh, pc, point_location_guess); if (tri == NULL) p2tr_exception_geometric ("Tried to add point outside of domain!"); pt = p2tr_mesh_new_point (self->mesh, pc); /* If the point falls on a line, we should split the line */ for (i = 0; i < 3; i++) { P2trEdge *edge = tri->edges[i]; if (p2tr_math_orient2d (& P2TR_EDGE_START(edge)->c, &edge->end->c, pc) == P2TR_ORIENTATION_LINEAR) { GList *parts = p2tr_cdt_split_edge (self, edge, pt), *eIter; for (eIter = parts; eIter != NULL; eIter = eIter->next) p2tr_edge_unref ((P2trEdge*)eIter->data); g_list_free(parts); inserted = TRUE; break; } } if (! inserted) /* If we reached this line, then the point is inside the triangle */ p2tr_cdt_insert_point_into_triangle (self, pt, tri); /* We no longer need the triangle */ p2tr_triangle_unref (tri); P2TR_CDT_VALIDATE_UNUSED (self); return pt; }
P2trPoint* p2tr_cdt_insert_point (P2trCDT *self, const P2trVector2 *pc, P2trTriangle *point_location_guess) { P2trTriangle *tri; P2trPoint *pt; gboolean inserted = FALSE; gint i; if (point_location_guess == NULL) tri = p2tr_mesh_find_point (self->mesh, pc); else tri = p2tr_mesh_find_point_local (self->mesh, pc, point_location_guess); if (tri == NULL) p2tr_exception_geometric ("Tried to add point outside of domain!"); pt = p2tr_mesh_new_point (self->mesh, pc); /* If the point falls on a line, we should split the line */ for (i = 0; i < 3; i++) { P2trEdge *edge = tri->edges[i]; if (p2tr_math_orient2d (& P2TR_EDGE_START(edge)->c, &edge->end->c, pc) == P2TR_ORIENTATION_LINEAR) { p2tr_cdt_split_edge (self, edge, pt); inserted = TRUE; break; } } if (! inserted) /* If we reached this line, then the point is inside the triangle */ p2tr_cdt_insert_point_into_triangle (self, pt, tri); p2tr_cdt_on_new_point (self, pt); return pt; }