]> granicus.if.org Git - poly2tri-c/commitdiff
Many reference-count related fixes, especially to P2trEdge objects and to the clear...
authorBarak Itkin <lightningismyname@gmail.com>
Sun, 27 May 2012 15:25:08 +0000 (18:25 +0300)
committerBarak Itkin <lightningismyname@gmail.com>
Sun, 27 May 2012 15:25:08 +0000 (18:25 +0300)
refine/cdt.c
refine/delaunay-terminator.c
refine/edge.c
refine/mesh.c
refine/mesh.h
refine/point.c
refine/point.h
refine/triangle.c
refine/triangle.h

index 70fbb517699c005d4854aec9433dcc06ae43a016..e0da6f225360de40eaf6859078f735cc6b189339 100644 (file)
@@ -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;
index 9c1a8729c937196705eef4825c66920da69cfef5..598f710c1f6fc90a84a4d9c09c161dd2e7d8d9ad 100644 (file)
@@ -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));
 }
 
 /* ****************************************************************** */
index d386b427e82114a1f436ae7543e3153bd6c3a986..d761d1a6f30ed9e59c00026f7b9d3418465b64be 100644 (file)
@@ -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
index a770a9690f6c1191ffba2b0fcc45e133dfa09111..9e951cd2203ef8737916e785ef8b357e816d350b 100644 (file)
@@ -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);
 }
index e9aca113012b6cef20ba39b8bfac732188eb87e5..22ef688e04b35bdafc4f74dab8d207f2b4548f6d 100644 (file)
@@ -13,8 +13,6 @@ struct P2trMesh_
   P2trHashSet *points;
   
   guint        refcount;
-  
-  gboolean     _is_clearing_now;
 };
 
 P2trMesh*     p2tr_mesh_new             (void);
index efd1569f17f1db24c0bbd09ed6714c7672273163..ee9335ba4955f0c502f80fc41776b3380744e879 100644 (file)
@@ -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);
 }
index 586d9ea6a13dd3dc07191f2347dbfccc50c7bbc1..5f0b0b573958cf13ceb7400acd5bf9ba23e06030 100644 (file)
@@ -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);
index 109bb99a8bff9f28602c1d7f8bf1129617167e89..a5b887b437a8c16fbfaeb82b3fd0646441624146 100644 (file)
@@ -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*
index 164f7c894e68791c5ff5226ac76835fcfe85367d..f54d1baba7191b3cc02aee8af753f998d51e2a43 100644 (file)
@@ -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);