]> granicus.if.org Git - poly2tri-c/commitdiff
More work on P2trPoint, and implement P2trEdge
authorBarak Itkin <lightningismyname@gmail.com>
Thu, 26 Apr 2012 10:54:21 +0000 (13:54 +0300)
committerBarak Itkin <lightningismyname@gmail.com>
Thu, 26 Apr 2012 10:54:21 +0000 (13:54 +0300)
refine/edge.c [new file with mode: 0644]
refine/edge.h
refine/mesh.h
refine/point.c
refine/point.h
refine/triangle.h [new file with mode: 0644]
refine/vector2.c
refine/vector2.h

diff --git a/refine/edge.c b/refine/edge.c
new file mode 100644 (file)
index 0000000..141a930
--- /dev/null
@@ -0,0 +1,191 @@
+#include <math.h>
+#include <glib.h>
+#include "point.h"
+#include "edge.h"
+
+static void
+p2tr_edge_init (P2trEdge  *self,
+                P2trPoint *start,
+                P2trPoint *end,
+                gboolean   constrained,
+                P2trEdge  *mirror)
+{
+  self->angle       = atan2 (end->y - start->y, end->x - start->x);
+  self->constrained = constrained;
+  self->delaunay    = FALSE;
+  self->end         = end;
+  self->mirror      = mirror;
+  self->refcount    = 0;
+  self->removed     = FALSE;
+  self->tri         = NULL;
+}
+
+P2trEdge*
+p2tr_edge_new (P2trPoint *start,
+               P2trPoint *end,
+               gboolean   constrained)
+{
+  P2trEdge *self   = g_slice_new (P2trEdge);
+  P2trEdge *mirror = g_slice_new (P2trEdge);
+
+  p2tr_edge_init (self, start, end, constrained, mirror);
+  p2tr_edge_init (mirror, end, start, constrained, self);
+
+  p2tr_point_ref (start);
+  p2tr_point_ref (end);
+  
+  _p2tr_point_insert_edge (start, self);
+  _p2tr_point_insert_edge (end,   mirror);
+
+  ++self->refcount;
+  return self;
+}
+
+void
+p2tr_edge_ref (P2trEdge *self)
+{
+  ++self->refcount;
+}
+
+void
+p2tr_edge_unref (P2trEdge *self)
+{
+  if (--self->refcount == 0 && self->mirror->refcount == 0)
+    p2tr_edge_free (self);
+}
+
+gboolean
+p2tr_edge_is_removed (P2trEdge *self)
+{
+  return self->end == NULL;
+}
+
+static void
+p2tr_edge_remove_one_side (P2trEdge *self)
+{
+  if (self->tri != NULL)
+  {
+    p2tr_triangle_remove (self->tri);
+    p2tr_triangle_unref (self->tri);
+    self->tri = NULL;
+  }
+  _p2tr_point_remove_edge(P2TR_EDGE_START(self), self);
+  p2tr_point_unref (self->end);
+  self->end = NULL;
+}
+
+void
+p2tr_edge_remove (P2trEdge *self)
+{
+  P2trMesh *mesh;
+
+  if (self->end == NULL) /* This is only true if the edge was removed */
+    return;
+
+  mesh = p2tr_edge_get_mesh (self);
+  p2tr_edge_remove_one_side (self);
+  p2tr_edge_remove_one_side (self->mirror);
+  
+  if (mesh != NULL)
+  {
+    p2tr_mesh_on_edge_removed (self);
+    p2tr_mesh_on_edge_removed (self->mirror);
+  }
+}
+
+void
+p2tr_edge_free (P2trEdge *self)
+{
+  p2tr_edge_remove (self);
+  g_slice_free (P2trEdge, self);
+  g_slice_free (P2trEdge, self->mirror);
+}
+
+void
+p2tr_edge_get_diametral_circle (P2trEdge   *self,
+                                P2trCircle *circle)
+{
+  P2trVector2 radius;
+  
+  p2tr_vector2_center (self->end, P2TR_EDGE_START(self), &circle->center);
+  p2tr_vector2_sub (self->end, &circle->center, &radius);
+
+  circle->radius = p2tr_vector2_norm (&radius);
+}
+
+//public void p2tr_edge_remove(P2trTriangulation t)
+//{
+//    _p2tr_edge_remove(T, false);
+//}
+
+//private void _p2tr_edge_remove(P2trTriangulation t, bool is_mirror)
+//{
+//    if (this.removed)
+//        return;
+//
+//    t.edges.Remove(this);
+//    this.removed = true;
+//
+//    this.start.p2tr_point_remove_edge(this);
+//
+//    if (this.tri != null)
+//        this.tri.p2tr_triangle_remove(t);
+//
+//    if (! is_mirror)
+//        this.mirror._p2tr_edge_remove(t, true);
+//}
+
+gdouble
+p2tr_edge_get_length(P2trEdge* self)
+{
+  return sqrt (p2tr_math_length_sq2 (&self->end, &P2TR_EDGE_START(self)));
+}
+
+gdouble
+p2tr_edge_get_length_squared(P2trEdge* self)
+{
+  return p2tr_math_length_sq2 (&self->end, &P2TR_EDGE_START(self));
+}
+
+gdouble
+p2tr_edge_angle_between(P2trEdge *e1, P2trEdge *e2)
+{
+  /* A = E1.angle, a = abs (A)
+   * B = E1.angle, b = abs (B)
+   *
+   * W is the angle we wish to find. Note the fact that we want
+   * to find the angle so that the edges go CLOCKWISE around it.
+   *
+   * Case 1: Signs of A and B agree | Case 2: Signs of A and B disagree
+   *         and A > 0              |         and A > 0
+   *                                |
+   * a = A, b = B                   | a = A, b = -B
+   *             ^^                 |
+   *         E2 //                  |           /
+   *           //\                  |          /
+   *          //b|                  |         /a
+   * - - - - * - |W- - - - - - - -  | - - - - * - - - - 
+   *         ^^a'|                  |       ^^ \\b
+   *         ||_/                   |      // W \\
+   *      E1 ||\                    |  E1 // \_/ \\ E2
+   *        '||a\                   |    //       \\
+   *     - - - - - -                |   //         vv
+   *                                |
+   * W = A' + B = (180 - A) + B     | W = 180 - (a + b) = 180 - (A - B) 
+   * W = 180 - A + B                | W = 180 - A + B
+   * 
+   * By the illustration above, we can see that in general the angle W
+   * can be computed by W = 180 - A + B in every case. The only thing to
+   * note is that the range of the result of the computation is
+   * [180 - 360, 180 + 360] = [-180, +540] so we may need to subtract
+   * 360 to put it back in the range [-180, +180].
+   */
+  if (e1->end != P2TR_EDGE_START(e2))
+    p2tr_exception_programmatic ("The end-point of the first edge isn't"
+        " the end-point of the second edge!");
+
+  gdouble result = G_PI - e1->angle + e2->angle;
+  if (result > 2 * G_PI)
+      result -= 2 * G_PI;
+  return result;
+}
\ No newline at end of file
index b3709c1d4bb0fad1e7a013f5c862046aeaf391de..b0070359bb31034a5154ab48ada66bb17bd6d43e 100644 (file)
@@ -25,7 +25,8 @@ struct P2trEdge_
   /**
    * The angle of the direction of this edge. Although it can be
    * computed anytime using atan2 on the vector of this edge, we cache
-   * it here since it's heavily used and the computation is expensive
+   * it here since it's heavily used and the computation is expensive.
+   * The angle increases as we go CCW, and it's in the range [-PI,+PI]
    */
   gdouble       angle;
   
@@ -41,7 +42,19 @@ struct P2trEdge_
 
 #define P2TR_EDGE_START(E) ((E)->mirror->end)
 
-void p2tr_edge_ref   (P2trEdge *self);
-void p2tr_edge_unref (P2trEdge *self);
+void        p2tr_edge_new                  (P2trPoint *start,
+                                            P2trPoint *end,
+                                            gboolean   constrained);
 
+void        p2tr_edge_ref                  (P2trEdge *self);
+
+void        p2tr_edge_unref                (P2trEdge *self);
+
+void        p2tr_edge_free                 (P2trEdge *self);
+
+void        p2tr_edge_remove               (P2trEdge *self);
+
+void        p2tr_edge_get_mesh             (P2trEdge *self);
+
+gboolean    p2tr_edge_is_removed           (P2trEdge *self);
 #endif
\ No newline at end of file
index db5217dc67799678a4f85e556037cb359f6739b7..1041f46b44fdae78ff98e7a114e7b22967287535 100644 (file)
@@ -32,17 +32,21 @@ P2trTriangle* p2tr_mesh_new_triangle2   (P2trMesh *mesh,
                                          P2trEdge *BC,
                                          P2trEdge *CA);
 
-gboolean      p2tr_mesh_remove_point    (P2trMesh *mesh,
-                                         P2trEdge *edge);
+gboolean      p2tr_mesh_on_point_removed    (P2trMesh  *mesh,
+                                             P2trPoint *point);
 
-gboolean      p2tr_mesh_remove_edge     (P2trMesh *mesh,
-                                         P2trEdge *edge);
+gboolean      p2tr_mesh_on_edge_removed     (P2trMesh *mesh,
+                                             P2trEdge *edge);
 
-gboolean      p2tr_mesh_remove_triangle (P2trMesh     *mesh,
-                                         P2trTriangle *triangle);
+gboolean      p2tr_mesh_on_triangle_removed (P2trMesh     *mesh,
+                                             P2trTriangle *triangle);
 
 void          p2tr_mesh_clear           (P2trMesh *mesh);
 
 void          p2tr_mesh_destroy         (P2trMesh *mesh);
 
+void          p2tr_mesh_unref           (P2trMesh *mesh);
+
+void          p2tr_mesh_ref             (P2trMesh *mesh);
+
 #endif
\ No newline at end of file
index 5b72ed275fb75f3f2bd588cc251cbe7aa3e5e527..7d920652a9bdd2083ddb6f00bdb935fc1c1d2a87 100644 (file)
@@ -8,19 +8,34 @@ p2tr_point_new (const P2trVector2 *c)
   P2trPoint *self = g_slice_new (P2trPoint);
   
   p2tr_vector2_copy (&self->c, c);
+  self->mesh = NULL;
   self->outgoing_edges = NULL;
-  
+  self->refcount = 1;
+
   return self;
 }
 
-static void
-p2tr_point_delete (P2trPoint *self)
+void
+p2tr_point_remove (P2trPoint *self)
 {
-  GList *iter;
-  for (iter = self->outgoing_edges; iter != NULL; iter = iter->next)
-    p2tr_edge_unref ((P2trEdge*) iter->data);
+  /* We can not iterate over the list of edges while removing the edges,
+   * because the removal action will modify the list. Instead we will
+   * simply look at the first edge untill the list is emptied. */
+  while (self->outgoing_edges != NULL)
+    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;
+  }
+}
 
-  g_list_free (self->outgoing_edges);
+void
+p2tr_point_free (P2trPoint *self)
+{
+  p2tr_point_remove (self);
   g_slice_free (P2trPoint, self);
 }
 
@@ -150,5 +165,11 @@ void
 p2tr_point_unref (P2trPoint *self)
 {
   if (--self->refcount == 0)
-    p2tr_point_delete (self);
+    p2tr_point_free (self);
+}
+
+P2trMesh*
+p2tr_point_get_mesh (P2trPoint *self)
+{
+  return self->mesh;
 }
\ No newline at end of file
index b975f522e115914fb12827cb15ebd313d9f398af..81d513a107f4e2031de4677e06d97c7325db789d 100644 (file)
@@ -22,10 +22,21 @@ struct P2trPoint_
 
   /** A count of references to the point */
   guint        refcount;
+  
+  /** The triangular mesh containing this point */
+  P2trMesh    *mesh;
 };
 
 P2trPoint*  p2tr_point_new                  (const P2trVector2 *c);
 
+void        p2tr_point_ref                  (P2trPoint *self);
+
+void        p2tr_point_unref                (P2trPoint *self);
+
+void        p2tr_point_free                 (P2trPoint *self);
+
+void        p2tr_point_remove               (P2trPoint *self);
+
 P2trEdge*   p2tr_point_get_edge_to          (P2trPoint *start,
                                              P2trPoint *end);
 
@@ -45,8 +56,6 @@ gboolean    p2tr_point_is_fully_in_domain   (P2trPoint *self);
 
 gboolean    p2tr_point_has_constrained_edge (P2trPoint *self);
 
-void        p2tr_point_ref                  (P2trPoint *self);
-
-void        p2tr_point_unref                (P2trPoint *self);
+P2trMesh*   p2tr_point_get_mesh             (P2trPoint *self);
 
 #endif
\ No newline at end of file
diff --git a/refine/triangle.h b/refine/triangle.h
new file mode 100644 (file)
index 0000000..62ea2bd
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef __P2TC_REFINE_TRIANGLE_H__
+#define __P2TC_REFINE_TRIANGLE_H__
+
+#include <glib.h>
+#include "triangulation.h"
+
+/**
+ * @struct P2trTriangle_
+ * A struct for a triangle in a triangular mesh
+ */
+struct P2trTriangle_
+{
+  /** The end point of this mesh */
+  P2trPoint    *end;
+
+  /** The edge going in the opposite direction from this edge */
+  P2trEdge     *mirror;
+  
+  /** Is this a constrained edge? */
+  gboolean      constrained;
+  
+  /** The triangle where this edge goes clockwise along its outline */
+  P2trTriangle *tri;
+
+  /**
+   * The angle of the direction of this edge. Although it can be
+   * computed anytime using atan2 on the vector of this edge, we cache
+   * it here since it's heavily used and the computation is expensive.
+   * The angle increases as we go CCW, and it's in the range [-PI, +PI]
+   */
+  gdouble       angle;
+  
+  /**
+   * Is this edge a delaunay edge? This field is used by the refinement
+   * algorithm and should not be used elsewhere!
+   */
+  gboolean      delaunay;
+
+  /** A count of references to the edge */
+  guint         refcount;
+  
+  /**
+   * Is this edge still present in the triangulation? Or maybe it is
+   * just pending for the last unref?
+   */
+  gboolean      removed;
+};
+
+#define P2TR_EDGE_START(E) ((E)->mirror->end)
+
+void p2tr_edge_ref    (P2trEdge *self);
+void p2tr_edge_unref  (P2trEdge *self);
+
+void p2tr_edge_remove (P2trEdge *self);
+#endif
\ No newline at end of file
index fde20b6a07aaffa2d3053920bfe62fe5d6ed4f0f..485356753fa6d68fc91d07b62feeecc429f4f1f3 100644 (file)
@@ -28,6 +28,15 @@ p2tr_vector2_sub (const P2trVector2 *a,
   dest->y = a->y - b->y;\r
 }\r
 \r
+void\r
+p2tr_vector2_center (const P2trVector2 *a,\r
+                     const P2trVector2 *b,\r
+                     P2trVector2       *dest)\r
+{\r
+  dest->x = (a->x + b->x) * 0.5;\r
+  dest->y = (a->y + b->y) * 0.5;\r
+}\r
+\r
 gdouble\r
 p2tr_vector2_norm (const P2trVector2 *v)\r
 {\r
index 92381a07669203ef971b0fd72163ce62ba555b9e..8fe7a611831eb95cd23bde5d1eee5627f33c367f 100644 (file)
@@ -28,6 +28,14 @@ gboolean      p2tr_vector2_is_same   (const P2trVector2 *a, const P2trVector2 *b
  */\r
 void          p2tr_vector2_sub       (const P2trVector2 *a, const P2trVector2 *b, P2trVector2 *dest);\r
 \r
+/**\r
+ * Compute the center point of the edge defined between two points\r
+ * @param[in] a The first side of the edge\r
+ * @param[in] b The second side of the edge\r
+ * @param[out] dest The vector in which the result should be stored\r
+ */\r
+void          p2tr_vector2_center    (const P2trVector2 *a, const P2trVector2 *b, P2trVector2 *dest);\r
+\r
 /**\r
  * Compute the norm of a vector (the length of the line from the origin\r
  * to the 2D point it represents)\r