/** * Try to flip a given edge, If successfull, return the new edge (reffed!), * otherwise return NULL */ P2trEdge* p2tr_cdt_try_flip (P2trCDT *self, P2trEdge *to_flip) { /* C * / | \ * B-----A to_flip: A->B * \ | / to_flip.Tri: ABC * D */ P2trPoint *A, *B, *C, *D; P2trEdge *AB, *CA, *AD, *DB, *BC, *DC; g_assert (! to_flip->constrained && ! to_flip->delaunay); A = P2TR_EDGE_START (to_flip); B = to_flip->end; C = p2tr_triangle_get_opposite_point (to_flip->tri, to_flip, FALSE); D = p2tr_triangle_get_opposite_point (to_flip->mirror->tri, to_flip->mirror, FALSE); AB = to_flip; /* Check if the quadriliteral ADBC is concave (because if it is, we * can't flip the edge) */ if (p2tr_triangle_circumcircle_contains_point (AB->tri, &D->c) != P2TR_INCIRCLE_IN) return NULL; CA = p2tr_point_get_edge_to (C, A, FALSE); AD = p2tr_point_get_edge_to (A, D, FALSE); DB = p2tr_point_get_edge_to (D, B, FALSE); BC = p2tr_point_get_edge_to (B, C, FALSE); p2tr_edge_remove (AB); DC = p2tr_mesh_new_edge (self->mesh, D, C, FALSE); p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh, CA, AD, DC)); p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh, DB, BC, DC->mirror)); return DC; }
/* Whenever a new point was inserted, it may disturb triangles * that are extremly skinny and therefor their circumscribing * circles are very large and will contain that point, even though they * may be very far from that point. * We have no choice but to check these and fix them if necessary */ static void p2tr_cdt_on_new_point (P2trCDT *self, P2trPoint *pt) { GList *bad_tris = NULL; P2trTriangle *tri; P2trHashSetIter iter; p2tr_hash_set_iter_init (&iter, self->mesh->triangles); while (p2tr_hash_set_iter_next (&iter, (gpointer*)&tri)) { if (p2tr_triangle_circumcircle_contains_point (tri, &pt->c) != P2TR_INCIRCLE_OUT) { bad_tris = g_list_prepend (bad_tris, tri); p2tr_triangle_ref (tri); } } p2tr_cdt_flip_fix (self, bad_tris); g_list_free (bad_tris); }