]> granicus.if.org Git - poly2tri-c/commitdiff
Add the initial code for triangular meshes (Most work was on P2trPoint)
authorBarak Itkin <lightningismyname@gmail.com>
Sat, 21 Apr 2012 12:05:58 +0000 (15:05 +0300)
committerBarak Itkin <lightningismyname@gmail.com>
Sat, 21 Apr 2012 12:05:58 +0000 (15:05 +0300)
refine/edge.h [new file with mode: 0644]
refine/mesh.h [new file with mode: 0644]
refine/point.c [new file with mode: 0644]
refine/point.h [new file with mode: 0644]
refine/triangulation.h [new file with mode: 0644]
refine/utils.h

diff --git a/refine/edge.h b/refine/edge.h
new file mode 100644 (file)
index 0000000..b3709c1
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __P2TC_REFINE_EDGE_H__
+#define __P2TC_REFINE_EDGE_H__
+
+#include <glib.h>
+#include "triangulation.h"
+
+/**
+ * @struct P2trEdge_
+ * A struct for an edge in a triangular mesh
+ */
+struct P2trEdge_
+{
+  /** 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
+   */
+  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;
+};
+
+#define P2TR_EDGE_START(E) ((E)->mirror->end)
+
+void p2tr_edge_ref   (P2trEdge *self);
+void p2tr_edge_unref (P2trEdge *self);
+
+#endif
\ No newline at end of file
diff --git a/refine/mesh.h b/refine/mesh.h
new file mode 100644 (file)
index 0000000..db5217d
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __P2TC_REFINE_MESH_H__
+#define __P2TC_REFINE_MESH_H__
+
+#include <glib.h>
+#include "utils.h"
+#include "triangulation.h"
+
+struct P2trMesh_
+{
+  P2trHashSet *triangles;
+  P2trHashSet *edges;
+  P2trHashSet *points;
+};
+
+P2trMesh*     p2tr_mesh_new             (void);
+
+P2trPoint*    p2tr_mesh_new_point       (P2trMesh          *mesh,
+                                         const P2trVector2 *c);
+
+P2trEdge*     p2tr_mesh_new_edge        (P2trMesh  *mesh,
+                                         P2trPoint *A,
+                                         P2trPoint *B,
+                                         gboolean   constrained);
+
+P2trTriangle* p2tr_mesh_new_triangle    (P2trMesh  *mesh,
+                                         P2trPoint *A,
+                                         P2trPoint *B,
+                                         P2trPoint *C);
+
+P2trTriangle* p2tr_mesh_new_triangle2   (P2trMesh *mesh,
+                                         P2trEdge *AB,
+                                         P2trEdge *BC,
+                                         P2trEdge *CA);
+
+gboolean      p2tr_mesh_remove_point    (P2trMesh *mesh,
+                                         P2trEdge *edge);
+
+gboolean      p2tr_mesh_remove_edge     (P2trMesh *mesh,
+                                         P2trEdge *edge);
+
+gboolean      p2tr_mesh_remove_triangle (P2trMesh     *mesh,
+                                         P2trTriangle *triangle);
+
+void          p2tr_mesh_clear           (P2trMesh *mesh);
+
+void          p2tr_mesh_destroy         (P2trMesh *mesh);
+
+#endif
\ No newline at end of file
diff --git a/refine/point.c b/refine/point.c
new file mode 100644 (file)
index 0000000..5b72ed2
--- /dev/null
@@ -0,0 +1,154 @@
+#include <glib.h>
+#include "point.h"
+#include "edge.h"
+
+P2trPoint*
+p2tr_point_new (const P2trVector2 *c)
+{
+  P2trPoint *self = g_slice_new (P2trPoint);
+  
+  p2tr_vector2_copy (&self->c, c);
+  self->outgoing_edges = NULL;
+  
+  return self;
+}
+
+static void
+p2tr_point_delete (P2trPoint *self)
+{
+  GList *iter;
+  for (iter = self->outgoing_edges; iter != NULL; iter = iter->next)
+    p2tr_edge_unref ((P2trEdge*) iter->data);
+
+  g_list_free (self->outgoing_edges);
+  g_slice_free (P2trPoint, self);
+}
+
+static P2trEdge*
+_p2tr_point_existing_edge_to (P2trPoint* self, P2trPoint *end)
+{
+  GList *iter;
+  
+  for (iter = self->outgoing_edges; iter != NULL; iter = iter->next)
+    {
+      P2trEdge *edge = (P2trEdge*) iter->data;
+      if (edge->end == end)
+        return edge;
+    }
+  
+  return NULL;
+}
+
+P2trEdge*
+p2tr_point_get_edge_to (P2trPoint *start,
+                        P2trPoint *end)
+{
+    P2trEdge* result = _p2tr_point_existing_edge_to (start, end);
+    if (result == NULL)
+      p2tr_exception_programmatic ("Tried to get an edge that doesn't exist!");
+    else
+      return result;
+}
+
+void
+_p2tr_point_insert_edge (P2trPoint *self, P2trEdge *e)
+{
+  GList *iter = self->outgoing_edges;
+  
+  /* Remember: Edges are sorted in ASCENDING angle! */
+  while (iter != NULL && ((P2trEdge*)iter->data)->angle < e->angle)
+    iter = iter->next;
+
+  self->outgoing_edges =
+      g_list_insert_before (self->outgoing_edges, iter, e);
+
+  p2tr_edge_ref (e);
+}
+
+void
+_p2tr_point_remove_edge (P2trPoint *self, P2trEdge* e)
+{
+  GList *node;
+  
+  if (P2TR_EDGE_START(e) != self)
+    p2tr_exception_programmatic ("Could not remove the given outgoing "
+        "edge because doesn't start on this point!");
+
+  node = g_list_find (self->outgoing_edges, e);
+  if (node == NULL)
+    p2tr_exception_programmatic ("Could not remove the given outgoing "
+        "edge because it's not present in the outgoing-edges list!");
+
+  self->outgoing_edges = g_list_delete_link (self->outgoing_edges, node);
+
+  p2tr_edge_unref (e);
+}
+
+P2trEdge*
+p2tr_point_edge_ccw (P2trPoint *self,
+                     P2trEdge  *e)
+{
+  GList *node;
+
+  if (P2TR_EDGE_START(e) != self)
+      p2tr_exception_programmatic ("Not an edge of this point!");
+
+  node = g_list_find (self->outgoing_edges, e);
+  if (node == NULL)
+    p2tr_exception_programmatic ("Could not find the CCW sibling edge"
+        "because the edge is not present in the outgoing-edges list!");
+
+    return (P2trEdge*) g_list_cyclic_next (self->outgoing_edges, node);
+}
+
+P2trEdge*
+p2tr_point_edge_cw (P2trPoint* self,
+                    P2trEdge *e)
+{
+  GList *node;
+
+  if (P2TR_EDGE_START(e) != self)
+      p2tr_exception_programmatic ("Not an edge of this point!");
+
+  node = g_list_find (self->outgoing_edges, e);
+  if (node == NULL)
+    p2tr_exception_programmatic ("Could not find the CW sibling edge"
+        "because the edge is not present in the outgoing-edges list!");
+
+    return (P2trEdge*) g_list_cyclic_prev (self->outgoing_edges, node);
+}
+
+gboolean
+p2tr_point_is_fully_in_domain (P2trPoint *self)
+{
+  GList *iter;
+  for (iter = self->outgoing_edges; iter != NULL; iter = iter->next)
+    if (((P2trEdge*) iter->data)->tri == NULL)
+      return FALSE;
+      
+  return TRUE;
+}
+
+gboolean
+p2tr_point_has_constrained_edge (P2trPoint *self)
+{
+  GList *iter;
+  for (iter = self->outgoing_edges; iter != NULL; iter = iter->next)
+    if (((P2trEdge*) iter->data)->constrained)
+      return TRUE;
+      
+  return FALSE;
+}
+
+void
+p2tr_point_ref (P2trPoint *self)
+{
+  ++self->refcount;
+}
+
+void
+p2tr_point_unref (P2trPoint *self)
+{
+  if (--self->refcount == 0)
+    p2tr_point_delete (self);
+}
\ No newline at end of file
diff --git a/refine/point.h b/refine/point.h
new file mode 100644 (file)
index 0000000..b975f52
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __P2TC_REFINE_POINT_H__
+#define __P2TC_REFINE_POINT_H__
+
+#include <glib.h>
+#include "vector2.h"
+#include "triangulation.h"
+
+/**
+ * @struct P2trPoint_
+ * A struct for a point in a triangular mesh
+ */
+struct P2trPoint_
+{
+  /** The 2D coordinates of the point */
+  P2trVector2  c;
+
+  /**
+   * A list of edges (@ref P2trEdge) which go out of this point (i.e.
+   * the point is their start point). The edges are sorted by ASCENDING
+   * angle, meaning they are sorted Counter Clockwise */
+  GList       *outgoing_edges;
+
+  /** A count of references to the point */
+  guint        refcount;
+};
+
+P2trPoint*  p2tr_point_new                  (const P2trVector2 *c);
+
+P2trEdge*   p2tr_point_get_edge_to          (P2trPoint *start,
+                                             P2trPoint *end);
+
+void        _p2tr_point_insert_edge         (P2trPoint *self,
+                                             P2trEdge  *e);
+
+void        _p2tr_point_remove_edge         (P2trPoint *self,
+                                             P2trEdge  *e);
+
+P2trEdge*   p2tr_point_edge_ccw             (P2trPoint *self,
+                                             P2trEdge  *e);
+
+P2trEdge*   p2tr_point_edge_cw              (P2trPoint *self,
+                                             P2trEdge  *e);
+
+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);
+
+#endif
\ No newline at end of file
diff --git a/refine/triangulation.h b/refine/triangulation.h
new file mode 100644 (file)
index 0000000..cdeb2fc
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __P2TC_REFINE_TRIANGULATION_H__
+#define __P2TC_REFINE_TRIANGULATION_H__
+
+typedef struct P2trPoint_     P2trPoint;
+typedef struct P2trEdge_      P2trEdge;
+typedef struct P2trTriangle_  P2trTriangle;
+typedef struct P2trMesh_      P2trMesh;
+
+#endif
\ No newline at end of file
index b98931b2bdbe9da3c2a352bdb4a390d6b52df2b8..3f651a4feef65b11ba72ef8b50e5adf235fcf95f 100755 (executable)
@@ -64,6 +64,10 @@ extern "C"
 
 #define foreach(iter,list) for ((iter) = (list); (iter) != NULL; (iter) = (iter)->next)
 
+#define p2tr_exception_numeric      g_error
+#define p2tr_exception_programmatic g_error
+#define p2tr_exception_geometric    g_error
+
 #ifdef __cplusplus
 }
 #endif