From: Barak Itkin Date: Fri, 27 Apr 2012 14:30:40 +0000 (+0300) Subject: Add edge cluster computation support X-Git-Tag: p2tc-0.1.0~91 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1f3e446e9e86b4231527ddc9aeb40506f8f5cb55;p=poly2tri-c Add edge cluster computation support --- diff --git a/refine/cluster.c b/refine/cluster.c new file mode 100644 index 0000000..e103be7 --- /dev/null +++ b/refine/cluster.c @@ -0,0 +1,109 @@ +#include + +#include +#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 index 0000000..2ab2a46 --- /dev/null +++ b/refine/cluster.h @@ -0,0 +1,23 @@ +#ifndef __P2TC_REFINE_CLUSTER_H__ +#define __P2TC_REFINE_CLUSTER_H__ + +#include +#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