From: Barak Itkin Date: Sun, 27 May 2012 15:25:08 +0000 (+0300) Subject: Many reference-count related fixes, especially to P2trEdge objects and to the clear... X-Git-Tag: p2tc-0.1.0~56 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b3d11cbede8cc7c6cdb1a07624b4c8d2fa5d1832;p=poly2tri-c Many reference-count related fixes, especially to P2trEdge objects and to the clear method of the P2trMesh object --- diff --git a/refine/cdt.c b/refine/cdt.c index 70fbb51..e0da6f2 100644 --- a/refine/cdt.c +++ b/refine/cdt.c @@ -121,9 +121,9 @@ p2tr_cdt_new (P2tCDT *cdt) P2trPoint *pt3 = g_hash_table_lookup (point_map, p2t_triangle_get_point (cdt_tri, 2)); P2trTriangle *new_tri = p2tr_mesh_new_triangle (rmesh->mesh, - p2tr_point_get_edge_to(pt1, pt2), - p2tr_point_get_edge_to(pt2, pt3), - p2tr_point_get_edge_to(pt3, pt1)); + p2tr_point_get_edge_to(pt1, pt2, FALSE), + p2tr_point_get_edge_to(pt2, pt3, FALSE), + p2tr_point_get_edge_to(pt3, pt1, FALSE)); /* We won't do any usage of the triangle, so just unref it */ p2tr_triangle_unref (new_tri); @@ -138,6 +138,7 @@ void p2tr_cdt_free (P2trCDT* self) { p2tr_pslg_free (self->outline); + p2tr_mesh_clear (self->mesh); p2tr_mesh_unref (self->mesh); g_slice_free (P2trCDT, self); @@ -362,15 +363,16 @@ p2tr_cdt_triangulate_fan (P2trCDT *self, if (A == NULL || B == NULL) continue; - AB = p2tr_point_get_edge_to (A, B); + AB = p2tr_point_get_edge_to (A, B, TRUE); BC = p2tr_mesh_new_or_existing_edge (self->mesh, B, center, FALSE); CA = p2tr_mesh_new_or_existing_edge (self->mesh, center, A, FALSE); tri = p2tr_mesh_new_triangle (self->mesh, AB, BC, CA); new_tris = g_list_prepend (new_tris, tri); - p2tr_edge_unref (BC); p2tr_edge_unref (CA); + p2tr_edge_unref (BC); + p2tr_edge_unref (AB); } return new_tris; @@ -392,8 +394,8 @@ p2tr_cdt_split_edge (P2trCDT *self, * 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; + P2trPoint *V = (e->tri != NULL) ? p2tr_triangle_get_opposite_point(e->tri, e, FALSE) : NULL; + P2trPoint *W = (e->mirror->tri != NULL) ? p2tr_triangle_get_opposite_point (e->mirror->tri, e->mirror, FALSE) : NULL; gboolean constrained = e->constrained; P2trEdge *XC, *CY; GList *new_tris = NULL, *fan = NULL, *new_edges = NULL; @@ -502,7 +504,7 @@ p2tr_cdt_flip_fix (P2trCDT *self, if (e->constrained || e->delaunay) continue; - opposite = p2tr_triangle_get_opposite_point (e->mirror->tri, e->mirror); + opposite = p2tr_triangle_get_opposite_point (e->mirror->tri, e->mirror, FALSE); if (! p2tr_circle_test_point_outside(&circum_circle, &opposite->c)) { P2trEdge *flipped = NULL; @@ -561,18 +563,17 @@ p2tr_cdt_try_flip (P2trCDT *self, A = P2TR_EDGE_START (to_flip); B = to_flip->end; - C = p2tr_triangle_get_opposite_point (to_flip->tri, to_flip); - D = p2tr_triangle_get_opposite_point (to_flip->mirror->tri, to_flip->mirror); + 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); ABC = to_flip->tri; ADB = to_flip->mirror->tri; /* Check if the quadriliteral ADBC is concave (because if it is, we * can't flip the edge) */ - if (p2tr_triangle_get_angle_at(ABC, A) + p2tr_triangle_get_angle_at(ADB, A) >= G_PI) - return FALSE; - if (p2tr_triangle_get_angle_at(ABC, B) + p2tr_triangle_get_angle_at(ADB, B) >= G_PI) - return FALSE; + if (p2tr_triangle_get_angle_at(ABC, A) + p2tr_triangle_get_angle_at(ADB, A) >= G_PI || + p2tr_triangle_get_angle_at(ABC, B) + p2tr_triangle_get_angle_at(ADB, B) >= G_PI) + return FALSE; p2tr_edge_remove (to_flip); @@ -580,13 +581,13 @@ p2tr_cdt_try_flip (P2trCDT *self, DC->delaunay = DC->mirror->delaunay = TRUE; g_queue_push_tail (new_tris, p2tr_mesh_new_triangle (self->mesh, - p2tr_point_get_edge_to (C, A), - p2tr_point_get_edge_to (A, D), + p2tr_point_get_edge_to (C, A, FALSE), + p2tr_point_get_edge_to (A, D, FALSE), DC)); g_queue_push_tail (new_tris, p2tr_mesh_new_triangle (self->mesh, - p2tr_point_get_edge_to (D, B), - p2tr_point_get_edge_to (B, C), + p2tr_point_get_edge_to (D, B, FALSE), + p2tr_point_get_edge_to (B, C, FALSE), DC->mirror)); *new_edge = DC; diff --git a/refine/delaunay-terminator.c b/refine/delaunay-terminator.c index 9c1a872..598f710 100644 --- a/refine/delaunay-terminator.c +++ b/refine/delaunay-terminator.c @@ -78,8 +78,8 @@ p2tr_cdt_is_encroached (P2trEdge *E) if (! E->constrained) return FALSE; - return (T1 != NULL && p2tr_cdt_test_encroachment_ignore_visibility (&p2tr_triangle_get_opposite_point (T1, E)->c, E)) - || (T2 != NULL && p2tr_cdt_test_encroachment_ignore_visibility (&p2tr_triangle_get_opposite_point (T2, E)->c, E)); + return (T1 != NULL && p2tr_cdt_test_encroachment_ignore_visibility (&p2tr_triangle_get_opposite_point (T1, E, FALSE)->c, E)) + || (T2 != NULL && p2tr_cdt_test_encroachment_ignore_visibility (&p2tr_triangle_get_opposite_point (T2, E, FALSE)->c, E)); } /* ****************************************************************** */ diff --git a/refine/edge.c b/refine/edge.c index d386b42..d761d1a 100644 --- a/refine/edge.c +++ b/refine/edge.c @@ -54,6 +54,7 @@ p2tr_edge_ref (P2trEdge *self) void p2tr_edge_unref (P2trEdge *self) { + g_assert (self->refcount > 0); if (--self->refcount == 0 && self->mirror->refcount == 0) p2tr_edge_free (self); } @@ -61,7 +62,7 @@ p2tr_edge_unref (P2trEdge *self) gboolean p2tr_edge_is_removed (P2trEdge *self) { - return self->end == NULL; + return self->end == NULL; /* This is only true if the edge was removed */ } void @@ -70,7 +71,7 @@ p2tr_edge_remove (P2trEdge *self) P2trMesh *mesh; P2trPoint *start, *end; - if (self->end == NULL) /* This is only true if the edge was removed */ + if (p2tr_edge_is_removed (self)) return; mesh = p2tr_edge_get_mesh (self); @@ -104,8 +105,8 @@ void p2tr_edge_free (P2trEdge *self) { p2tr_edge_remove (self); - g_slice_free (P2trEdge, self); g_slice_free (P2trEdge, self->mirror); + g_slice_free (P2trEdge, self); } void diff --git a/refine/mesh.c b/refine/mesh.c index a770a96..9e951cd 100644 --- a/refine/mesh.c +++ b/refine/mesh.c @@ -16,8 +16,6 @@ p2tr_mesh_new (void) mesh->points = p2tr_hash_set_new_default (); mesh->triangles = p2tr_hash_set_new_default (); - mesh->_is_clearing_now = FALSE; - return mesh; } @@ -100,8 +98,7 @@ p2tr_mesh_on_point_removed (P2trMesh *self, point->mesh = NULL; p2tr_mesh_unref (self); - if (! self->_is_clearing_now) - p2tr_hash_set_remove (self->points, point); + p2tr_hash_set_remove (self->points, point); p2tr_point_unref (point); } @@ -109,8 +106,7 @@ void p2tr_mesh_on_edge_removed (P2trMesh *self, P2trEdge *edge) { - if (! self->_is_clearing_now) - p2tr_hash_set_remove (self->edges, edge); + p2tr_hash_set_remove (self->edges, edge); p2tr_edge_unref (edge); } @@ -118,8 +114,7 @@ void p2tr_mesh_on_triangle_removed (P2trMesh *self, P2trTriangle *triangle) { - if (! self->_is_clearing_now) - p2tr_hash_set_remove (self->triangles, triangle); + p2tr_hash_set_remove (self->triangles, triangle); p2tr_triangle_unref (triangle); } @@ -129,24 +124,32 @@ p2tr_mesh_clear (P2trMesh *self) P2trHashSetIter iter; gpointer temp; - self->_is_clearing_now = TRUE; - + /* While iterating over the sets of points/edges/triangles to remove + * all the mesh elements, the sets will be modified by the removal + * operation itself. Therefore we can't use a regular iterator - + * instead we must look always at the first place */ p2tr_hash_set_iter_init (&iter, self->triangles); while (p2tr_hash_set_iter_next (&iter, &temp)) - p2tr_triangle_remove ((P2trTriangle*)temp); - p2tr_hash_set_remove_all (self->triangles); + { + p2tr_triangle_remove ((P2trTriangle*)temp); + p2tr_hash_set_iter_init (&iter, self->triangles); + } p2tr_hash_set_iter_init (&iter, self->edges); while (p2tr_hash_set_iter_next (&iter, &temp)) - p2tr_edge_remove ((P2trEdge*)temp); - p2tr_hash_set_remove_all (self->edges); + { + g_assert (((P2trEdge*)temp)->tri == NULL); + p2tr_edge_remove ((P2trEdge*)temp); + p2tr_hash_set_iter_init (&iter, self->edges); + } p2tr_hash_set_iter_init (&iter, self->points); while (p2tr_hash_set_iter_next (&iter, &temp)) - p2tr_point_remove ((P2trPoint*)temp); - p2tr_hash_set_remove_all (self->points); - - self->_is_clearing_now = FALSE; + { + g_assert (((P2trPoint*)temp)->outgoing_edges == NULL); + p2tr_point_remove ((P2trPoint*)temp); + p2tr_hash_set_iter_init (&iter, self->points); + } } void @@ -164,6 +167,7 @@ p2tr_mesh_free (P2trMesh *self) void p2tr_mesh_unref (P2trMesh *self) { + g_assert (self->refcount > 0); if (--self->refcount == 0) p2tr_mesh_free (self); } diff --git a/refine/mesh.h b/refine/mesh.h index e9aca11..22ef688 100644 --- a/refine/mesh.h +++ b/refine/mesh.h @@ -13,8 +13,6 @@ struct P2trMesh_ P2trHashSet *points; guint refcount; - - gboolean _is_clearing_now; }; P2trMesh* p2tr_mesh_new (void); diff --git a/refine/point.c b/refine/point.c index efd1569..ee9335b 100644 --- a/refine/point.c +++ b/refine/point.c @@ -33,11 +33,7 @@ p2tr_point_remove (P2trPoint *self) p2tr_edge_remove ((P2trEdge*) self->outgoing_edges->data); if (self->mesh != NULL) - { p2tr_mesh_on_point_removed (self->mesh, self); - p2tr_mesh_unref (self->mesh); - self->mesh = NULL; - } } void @@ -65,13 +61,14 @@ p2tr_point_has_edge_to (P2trPoint *start, P2trEdge* p2tr_point_get_edge_to (P2trPoint *start, - P2trPoint *end) + P2trPoint *end, + gboolean do_ref) { P2trEdge* result = p2tr_point_has_edge_to (start, end); if (result == NULL) p2tr_exception_programmatic ("Tried to get an edge that doesn't exist!"); else - return p2tr_edge_ref (result); + return do_ref ? p2tr_edge_ref (result) : result; } void @@ -183,6 +180,7 @@ p2tr_point_ref (P2trPoint *self) void p2tr_point_unref (P2trPoint *self) { + g_assert (self->refcount > 0); if (--self->refcount == 0) p2tr_point_free (self); } diff --git a/refine/point.h b/refine/point.h index 586d9ea..5f0b0b5 100644 --- a/refine/point.h +++ b/refine/point.h @@ -43,7 +43,8 @@ P2trEdge* p2tr_point_has_edge_to (P2trPoint *start, P2trPoint *end); P2trEdge* p2tr_point_get_edge_to (P2trPoint *start, - P2trPoint *end); + P2trPoint *end, + gboolean do_ref); void _p2tr_point_insert_edge (P2trPoint *self, P2trEdge *e); diff --git a/refine/triangle.c b/refine/triangle.c index 109bb99..a5b887b 100644 --- a/refine/triangle.c +++ b/refine/triangle.c @@ -42,6 +42,8 @@ p2tr_triangle_new (P2trEdge *AB, gint i; P2trTriangle *self = g_slice_new (P2trTriangle); + self->refcount = 0; + #ifndef P2TC_NO_LOGIC_CHECKS p2tr_validate_edges_can_form_tri (AB, BC, CA); #endif @@ -84,12 +86,10 @@ p2tr_triangle_new (P2trEdge *AB, #endif self->edges[i]->tri = self; p2tr_edge_ref (self->edges[i]); + p2tr_triangle_ref (self); } - /* Reference by 3 edges, and another for the return of this pointer */ - self->refcount = 4; - - return self; + return p2tr_triangle_ref (self); } P2trTriangle* @@ -102,6 +102,7 @@ p2tr_triangle_ref (P2trTriangle *self) void p2tr_triangle_unref (P2trTriangle *self) { + g_assert (self->refcount > 0); if (--self->refcount == 0) p2tr_triangle_free (self); } @@ -157,16 +158,20 @@ p2tr_triangle_is_removed (P2trTriangle *self) P2trPoint* p2tr_triangle_get_opposite_point (P2trTriangle *self, - P2trEdge *e) + P2trEdge *e, + gboolean do_ref) { + P2trPoint *pt; if (self->edges[0] == e || self->edges[0]->mirror == e) - return p2tr_point_ref (self->edges[1]->end); - if (self->edges[1] == e || self->edges[1]->mirror == e) - return p2tr_point_ref (self->edges[2]->end); - if (self->edges[2] == e || self->edges[2]->mirror == e) - return p2tr_point_ref (self->edges[0]->end); + pt = self->edges[1]->end; + else if (self->edges[1] == e || self->edges[1]->mirror == e) + pt = self->edges[2]->end; + else if (self->edges[2] == e || self->edges[2]->mirror == e) + pt = self->edges[0]->end; + else + p2tr_exception_programmatic ("The edge is not in the triangle!"); - p2tr_exception_programmatic ("The edge is not in the triangle!"); + return do_ref ? p2tr_point_ref (pt) : pt; } P2trEdge* diff --git a/refine/triangle.h b/refine/triangle.h index 164f7c8..f54d1ba 100644 --- a/refine/triangle.h +++ b/refine/triangle.h @@ -33,7 +33,8 @@ P2trMesh* p2tr_triangle_get_mesh (P2trTriangle *self); gboolean p2tr_triangle_is_removed (P2trTriangle *self); P2trPoint* p2tr_triangle_get_opposite_point (P2trTriangle *self, - P2trEdge *e); + P2trEdge *e, + gboolean do_ref); P2trEdge* p2tr_triangle_get_opposite_edge (P2trTriangle *self, P2trPoint *p);