]> granicus.if.org Git - poly2tri-c/commitdiff
Add edge cluster computation support
authorBarak Itkin <lightningismyname@gmail.com>
Fri, 27 Apr 2012 14:30:40 +0000 (17:30 +0300)
committerBarak Itkin <lightningismyname@gmail.com>
Fri, 27 Apr 2012 14:30:40 +0000 (17:30 +0300)
refine/cluster.c [new file with mode: 0644]
refine/cluster.h [new file with mode: 0644]

diff --git a/refine/cluster.c b/refine/cluster.c
new file mode 100644 (file)
index 0000000..e103be7
--- /dev/null
@@ -0,0 +1,109 @@
+#include <math.h>
+
+#include <glib.h>
+#include "utils.h"
+#include "point.h"
+#include "edge.h"
+
+#include "cluster.h"
+
+static gboolean p2tr_cluster_cw_tri_between_is_in_domain (P2trEdge *e1,
+                                                          P2trEdge *e2);
+
+gdouble
+p2tr_cluster_shortest_edge_length (P2trCluster *self)
+{
+  gdouble min_length_sq = G_MAXDOUBLE, temp;
+  GList *iter;
+  
+  for (iter = g_queue_peek_head(&self->edges); iter != NULL; iter = iter->next)
+    {
+      temp = p2tr_edge_get_length_squared ((P2trEdge*)iter->data);
+      min_length_sq = MIN(min_length_sq, temp);
+    }
+  return sqrt (min_length_sq);
+}
+
+/**
+ * Return the edge cluster of the specified edge from the specified end
+ * point. THE EDGES IN THE CLUSTER MUST BE UNREFFED!
+ * @param[in] P The point which is shared between all edges of the cluster
+ * @param[in] E The edge whose cluster should be returned
+ * @return The cluster of @ref E from the point @ref P
+ */
+P2trCluster*
+p2tr_cluster_get_for (P2trPoint   *P,
+                      P2trEdge    *E)
+{
+  P2trCluster *cluster = g_slice_new (P2trCluster);
+  gdouble temp_angle;
+  P2trEdge *current, *next;
+  
+  cluster->min_angle = G_MAXDOUBLE;
+  g_queue_init (&cluster->edges);
+
+  if (P == E->end)
+    P = P2TR_EDGE_START (E);
+  else if (P != P2TR_EDGE_START (E))
+    p2tr_exception_programmatic ("Unexpected point for the edge!");
+
+  g_queue_push_head (&cluster->edges, E);
+
+  current = E;
+  next = p2tr_point_edge_cw (P, current);
+  
+  while (next != g_queue_peek_head (&cluster->edges)
+      && (temp_angle = p2tr_edge_angle_between (current->mirror, next)) <= P2TR_CLUSTER_LIMIT_ANGLE
+      && p2tr_cluster_cw_tri_between_is_in_domain (current, next))
+    {
+      g_queue_push_tail (&cluster->edges, next);
+      p2tr_edge_ref (next);
+      current = next;
+      next = p2tr_point_edge_cw (P, current);
+      cluster->min_angle = MIN (cluster->min_angle, temp_angle);
+    }
+
+  current = E;
+  next = p2tr_point_edge_ccw(P, current);
+  while (next != g_queue_peek_tail (&cluster->edges)
+      && (temp_angle = p2tr_edge_angle_between (current->mirror, next)) <= P2TR_CLUSTER_LIMIT_ANGLE
+      && p2tr_cluster_cw_tri_between_is_in_domain (next, current))
+    {
+      g_queue_push_head (&cluster->edges, next);
+      p2tr_edge_ref (next);
+      current = next;
+      next = p2tr_point_edge_ccw (P, current);
+      cluster->min_angle = MIN(cluster->min_angle, temp_angle);
+    }
+
+  return cluster;
+}
+
+/*     ^ e1
+ *    /
+ *   /_ e1.Tri (e2.Mirror.Tri)
+ *  /  |
+ * *---------> e2
+ *
+ * Check if the angle marked is a part of the triangulation
+ * domain
+ */
+static gboolean
+p2tr_cluster_cw_tri_between_is_in_domain (P2trEdge *e1, P2trEdge *e2)
+{
+  if (P2TR_EDGE_START(e1) != P2TR_EDGE_START(e2) || e1->tri != e2->mirror->tri)
+    p2tr_exception_programmatic ("Non clockwise adjacent edges!");
+  return e1->tri != NULL;
+}
+
+void
+p2tr_cluster_free (P2trCluster *self)
+{
+  GList *iter;
+  
+  for (iter = g_queue_peek_head(&self->edges); iter != NULL; iter = iter->next)
+    p2tr_edge_unref ((P2trEdge*)iter->data);
+
+  g_queue_clear (&self->edges);
+  g_slice_free (P2trCluster, self);
+}
\ No newline at end of file
diff --git a/refine/cluster.h b/refine/cluster.h
new file mode 100644 (file)
index 0000000..2ab2a46
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __P2TC_REFINE_CLUSTER_H__
+#define __P2TC_REFINE_CLUSTER_H__
+
+#include <glib.h>
+#include "point.h"
+#include "edge.h"
+
+#define P2TR_CLUSTER_LIMIT_ANGLE (G_PI / 6)
+
+typedef struct
+{
+  GQueue   edges;
+  gdouble  min_angle;
+} P2trCluster;
+
+P2trCluster*  p2tr_cluster_get_for              (P2trPoint *P,
+                                                 P2trEdge  *E);
+
+gdouble       p2tr_cluster_shortest_edge_length (P2trCluster *self);
+
+void          p2tr_cluster_free                 (P2trCluster *self);
+
+#endif
\ No newline at end of file