]> granicus.if.org Git - poly2tri-c/commitdiff
More work on P2trEdge, implement P2trTriangle
authorBarak Itkin <lightningismyname@gmail.com>
Thu, 26 Apr 2012 13:09:52 +0000 (16:09 +0300)
committerBarak Itkin <lightningismyname@gmail.com>
Thu, 26 Apr 2012 13:09:52 +0000 (16:09 +0300)
refine/edge.c
refine/edge.h
refine/triangle.c [new file with mode: 0644]
refine/triangle.h

index 9e394f18a62307b86f0f2c00db7daa5896d0950f..b517e121c2b709da4b19de551efcf669576dad8d 100644 (file)
@@ -135,6 +135,15 @@ p2tr_edge_get_diametral_circle (P2trEdge   *self,
 //        this.mirror._p2tr_edge_remove(t, true);
 //}
 
+P2trMesh*
+p2tr_edge_get_mesh (P2trEdge *self)
+{
+  if (self->end != NULL)
+    return self->end->mesh;
+  else
+    return NULL;
+}
+
 gdouble
 p2tr_edge_get_length(P2trEdge* self)
 {
index c820e8b43bcdccbb19c687e71f7febae667b2a06..392483f7da3e50d9979b1ff6f807ce1ee110f650 100644 (file)
@@ -58,4 +58,12 @@ void        p2tr_edge_remove               (P2trEdge *self);
 P2trMesh*   p2tr_edge_get_mesh             (P2trEdge *self);
 
 gboolean    p2tr_edge_is_removed           (P2trEdge *self);
+
+gdouble     p2tr_edge_get_length           (P2trEdge* self);
+
+gdouble     p2tr_edge_get_length_squared   (P2trEdge* self);
+
+gdouble     p2tr_edge_angle_between        (P2trEdge *e1,
+                                            P2trEdge *e2);
+
 #endif
\ No newline at end of file
diff --git a/refine/triangle.c b/refine/triangle.c
new file mode 100644 (file)
index 0000000..ae5ae02
--- /dev/null
@@ -0,0 +1,200 @@
+#include <glib.h>
+#include "point.h"
+#include "edge.h"
+#include "triangle.h"
+#include "utils.h"
+#include "math.h"
+
+P2trTriangle*
+p2tr_triangle_new (P2trEdge *AB,
+                   P2trEdge *BC,
+                   P2trEdge *CA)
+{
+  gint i;
+  P2trTriangle *self = g_slice_new (P2trTriangle);
+
+#ifndef P2TC_NO_LOGIC_CHECKS
+  if (AB->end != P2TR_EDGE_START(BC)
+      || BC->end != P2TR_EDGE_START(CA)
+      || CA->end != P2TR_EDGE_START(AB))
+    {
+      p2tr_exception_programmatic ("Unexpected edge sequence for a triangle!");
+    }
+
+  if (AB == BC->mirror || BC == CA->mirror || CA == AB->mirror)
+    {
+      p2tr_exception_programmatic ("Repeated edge in a triangle!");
+    }
+#endif
+
+  switch (p2tr_math_orient2d(&CA->end->c, &AB->end->c, &BC->end->c))
+    {
+      case P2TR_ORIENTATION_CCW:
+        self->edges[0] = CA->mirror;
+        self->edges[1] = BC->mirror;
+        self->edges[2] = AB->mirror;
+        break;
+
+      case P2TR_ORIENTATION_CW:
+        self->edges[0] = AB;
+        self->edges[1] = BC;
+        self->edges[2] = CA;
+        break;
+
+      case P2TR_ORIENTATION_LINEAR:
+        p2tr_exception_geometric ("Can't make a triangle of linear points!");
+    }
+
+#ifdef P2TC_DEBUG_CHECKS
+  if (p2tr_math_orient2d (&self->edges[0]->end.c,
+                          &self->edges[1]->end.c,
+                          &self->edges[2]->end.c) != P2TR_ORIENTATION_CW)
+    {
+      p2tr_exception_programmatic ("Bad ordering!");
+    }
+#endif
+
+  for (i = 0; i < 3; i++)
+    {
+#ifdef P2TC_DEBUG_CHECKS
+      if (self->edges[i]->tri != NULL)
+        p2tr_exception_programmatic ("This edge is already in use by "
+            "another triangle!");
+#endif
+      self->edges[i]->tri = self;
+      p2tr_edge_ref (self->edges[i]);
+    }
+
+  /* Reference by 3 edges, and another for the return of this pointer */
+  self->refcount = 4;
+
+  return self;
+}
+
+void
+p2tr_triangle_ref (P2trTriangle *self)
+{
+  ++self->refcount;
+}
+
+void
+p2tr_triangle_unref (P2trTriangle *self)
+{
+  if (--self->refcount == 0)
+    p2tr_triangle_free (self);
+}
+
+void
+p2tr_triangle_free (P2trTriangle *self)
+{
+  p2tr_triangle_remove (self);
+  g_slice_free (P2trTriangle, self);
+}
+
+void
+p2tr_triangle_remove (P2trTriangle *self)
+{
+  gint i;
+  P2trMesh *mesh;
+  
+  if (p2tr_triangle_is_removed (self))
+    return;
+
+  mesh = p2tr_triangle_get_mesh (self);
+  
+  for (i = 0; i < 3; i++)
+  {
+    self->edges[i]->tri = NULL;
+    p2tr_triangle_unref (self);
+
+    p2tr_edge_unref (self->edges[i]);
+    self->edges[i] = NULL;
+  }
+
+  if (mesh != NULL)
+    p2tr_mesh_on_triangle_removed (mesh, self);
+}
+
+P2trMesh*
+p2tr_triangle_get_mesh (P2trTriangle *self)
+{
+  if (self->edges[0] != NULL)
+    return p2tr_edge_get_mesh (self->edges[0]);
+  else
+    return NULL;
+}
+
+gboolean 
+p2tr_triangle_is_removed (P2trTriangle *self)
+{
+  return self->edges[0] == NULL;
+}
+
+P2trPoint*
+p2tr_triangle_get_opposite_point (P2trTriangle *self,
+                                  P2trEdge     *e)
+{
+  if (self->edges[0] == e || self->edges[0]->mirror == e)
+    return self->edges[1]->end;
+  if (self->edges[1] == e || self->edges[1]->mirror == e)
+    return self->edges[2]->end;
+  if (self->edges[2] == e || self->edges[2]->mirror == e)
+    return self->edges[0]->end;
+
+  p2tr_exception_programmatic ("The edge is not in the triangle!");
+}
+
+P2trEdge*
+p2tr_triangle_get_opposite_edge (P2trTriangle *self,
+                                 P2trPoint    *p)
+{
+  if (self->edges[0]->end == p)
+    return self->edges[2];
+  if (self->edges[1]->end == p)
+    return self->edges[0];
+  if (self->edges[2]->end == p)
+    return self->edges[1];
+
+  p2tr_exception_programmatic ("The point is not in the triangle!");
+}
+
+gdouble
+p2tr_triangle_get_angle_at (P2trTriangle *self,
+                            P2trPoint    *p)
+{
+  if (p == self->edges[0]->end)
+    return p2tr_edge_angle_between (self->edges[0], self->edges[1]);
+  else if (p == self->edges[1]->end)
+    return p2tr_edge_angle_between (self->edges[1], self->edges[2]);
+  else if (p == self->edges[2]->end)
+    return p2tr_edge_angle_between (self->edges[2], self->edges[0]);
+
+  p2tr_exception_programmatic ("Can't find the point!");
+}
+
+gdouble
+p2tr_triangle_smallest_non_constrained_angle (P2trTriangle *self)
+{
+    gdouble result = G_MAXDOUBLE, angle;
+    gint i;
+    
+    if (! self->edges[0]->constrained || !self->edges[1]->constrained)
+      {
+        angle = p2tr_edge_angle_between(self->edges[0], self->edges[1]);
+        result = MIN(result, angle);
+      }
+
+    if (!self->edges[1]->constrained || !self->edges[2]->constrained)
+      {
+        angle = p2tr_edge_angle_between(self->edges[1], self->edges[2]);
+        result = MIN(result, angle);
+      }
+
+    if (!self->edges[2]->constrained || !self->edges[0]->constrained)
+      {
+        angle = p2tr_edge_angle_between(self->edges[2], self->edges[0]);
+        result = MIN(result, angle);
+      }
+
+    return result;
+}
index 62ea2bd229872f3c567f1b4489e1bc1f4c913b50..65ad46f6ba0a359d1534bc2f41213f1e403ca86c 100644 (file)
  */
 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;
+  P2trEdge* edges[3];
   
-  /**
-   * Is this edge still present in the triangulation? Or maybe it is
-   * just pending for the last unref?
-   */
-  gboolean      removed;
+  guint refcount;
 };
 
-#define P2TR_EDGE_START(E) ((E)->mirror->end)
+P2trTriangle*   p2tr_triangle_new            (P2trEdge *AB,
+                                              P2trEdge *BC,
+                                              P2trEdge *CA);
+
+void        p2tr_triangle_ref                (P2trTriangle *self);
+
+void        p2tr_triangle_unref              (P2trTriangle *self);
+
+void        p2tr_triangle_free               (P2trTriangle *self);
+
+void        p2tr_triangle_remove             (P2trTriangle *self);
+
+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*   p2tr_triangle_get_opposite_edge  (P2trTriangle *self,
+                                              P2trPoint    *p);
+
+gdouble     p2tr_triangle_get_angle_at       (P2trTriangle *self,
+                                              P2trPoint    *p);
 
-void p2tr_edge_ref    (P2trEdge *self);
-void p2tr_edge_unref  (P2trEdge *self);
+gdouble    p2tr_triangle_smallest_non_constrained_angle (P2trTriangle *self);
 
-void p2tr_edge_remove (P2trEdge *self);
 #endif
\ No newline at end of file