]> granicus.if.org Git - poly2tri-c/blob - refine/point.c
Make functions on point/edge/triangle/mesh return reffed objects
[poly2tri-c] / refine / point.c
1 #include <glib.h>
2 #include "point.h"
3 #include "edge.h"
4 #include "mesh.h"
5
6 P2trPoint*
7 p2tr_point_new (const P2trVector2 *c)
8 {
9   return p2tr_point_new2 (c->x, c->y);
10 }
11
12 P2trPoint*
13 p2tr_point_new2 (gdouble x, gdouble y)
14 {
15   P2trPoint *self = g_slice_new (P2trPoint);
16   
17   self->c.x = x;
18   self->c.y = y;
19   self->mesh = NULL;
20   self->outgoing_edges = NULL;
21   self->refcount = 1;
22
23   return self;
24 }
25
26 void
27 p2tr_point_remove (P2trPoint *self)
28 {
29   /* We can not iterate over the list of edges while removing the edges,
30    * because the removal action will modify the list. Instead we will
31    * simply look at the first edge untill the list is emptied. */
32   while (self->outgoing_edges != NULL)
33     p2tr_edge_remove ((P2trEdge*) self->outgoing_edges->data);
34
35   if (self->mesh != NULL)
36   {
37     p2tr_mesh_on_point_removed (self->mesh, self);
38     p2tr_mesh_unref (self->mesh);
39     self->mesh = NULL;
40   }
41 }
42
43 void
44 p2tr_point_free (P2trPoint *self)
45 {
46   p2tr_point_remove (self);
47   g_slice_free (P2trPoint, self);
48 }
49
50 P2trEdge*
51 p2tr_point_has_edge_to (P2trPoint *start,
52                         P2trPoint *end)
53 {
54   GList *iter;
55   
56   for (iter = start->outgoing_edges; iter != NULL; iter = iter->next)
57     {
58       P2trEdge *edge = (P2trEdge*) iter->data;
59       if (edge->end == end)
60         return edge;
61     }
62   
63   return NULL;
64 }
65
66 P2trEdge*
67 p2tr_point_get_edge_to (P2trPoint *start,
68                         P2trPoint *end)
69 {
70     P2trEdge* result = p2tr_point_has_edge_to (start, end);
71     if (result == NULL)
72       p2tr_exception_programmatic ("Tried to get an edge that doesn't exist!");
73     else
74       return p2tr_edge_ref (result);
75 }
76
77 void
78 _p2tr_point_insert_edge (P2trPoint *self, P2trEdge *e)
79 {
80   GList *iter = self->outgoing_edges;
81   
82   /* Remember: Edges are sorted in ASCENDING angle! */
83   while (iter != NULL && ((P2trEdge*)iter->data)->angle < e->angle)
84     iter = iter->next;
85
86   self->outgoing_edges =
87       g_list_insert_before (self->outgoing_edges, iter, e);
88
89   p2tr_edge_ref (e);
90 }
91
92 void
93 _p2tr_point_remove_edge (P2trPoint *self, P2trEdge* e)
94 {
95   GList *node;
96   
97   if (P2TR_EDGE_START(e) != self)
98     p2tr_exception_programmatic ("Could not remove the given outgoing "
99         "edge because doesn't start on this point!");
100
101   node = g_list_find (self->outgoing_edges, e);
102   if (node == NULL)
103     p2tr_exception_programmatic ("Could not remove the given outgoing "
104         "edge because it's not present in the outgoing-edges list!");
105
106   self->outgoing_edges = g_list_delete_link (self->outgoing_edges, node);
107
108   p2tr_edge_unref (e);
109 }
110
111 P2trEdge*
112 p2tr_point_edge_ccw (P2trPoint *self,
113                      P2trEdge  *e)
114 {
115   GList *node;
116   P2trEdge *result;
117
118   if (P2TR_EDGE_START(e) != self)
119       p2tr_exception_programmatic ("Not an edge of this point!");
120
121   node = g_list_find (self->outgoing_edges, e);
122   if (node == NULL)
123     p2tr_exception_programmatic ("Could not find the CCW sibling edge"
124         "because the edge is not present in the outgoing-edges list!");
125
126   result = (P2trEdge*) g_list_cyclic_next (self->outgoing_edges, node);
127   return p2tr_edge_ref (result);
128 }
129
130 P2trEdge*
131 p2tr_point_edge_cw (P2trPoint* self,
132                     P2trEdge *e)
133 {
134   GList *node;
135   P2trEdge *result;
136
137   if (P2TR_EDGE_START(e) != self)
138       p2tr_exception_programmatic ("Not an edge of this point!");
139
140   node = g_list_find (self->outgoing_edges, e);
141   if (node == NULL)
142     p2tr_exception_programmatic ("Could not find the CW sibling edge"
143         "because the edge is not present in the outgoing-edges list!");
144
145   result = (P2trEdge*) g_list_cyclic_prev (self->outgoing_edges, node);
146   return p2tr_edge_ref (result);
147 }
148
149 gboolean
150 p2tr_point_is_fully_in_domain (P2trPoint *self)
151 {
152   GList *iter;
153   for (iter = self->outgoing_edges; iter != NULL; iter = iter->next)
154     if (((P2trEdge*) iter->data)->tri == NULL)
155       return FALSE;
156       
157   return TRUE;
158 }
159
160 gboolean
161 p2tr_point_has_constrained_edge (P2trPoint *self)
162 {
163   GList *iter;
164   for (iter = self->outgoing_edges; iter != NULL; iter = iter->next)
165     if (((P2trEdge*) iter->data)->constrained)
166       return TRUE;
167       
168   return FALSE;
169 }
170
171 /**
172  * Increase the reference count of the given input point
173  * @param self - The point to ref
174  * @return The point given
175  */
176 P2trPoint*
177 p2tr_point_ref (P2trPoint *self)
178 {
179   ++self->refcount;
180   return self;
181 }
182
183 void
184 p2tr_point_unref (P2trPoint *self)
185 {
186   if (--self->refcount == 0)
187     p2tr_point_free (self);
188 }
189
190 P2trMesh*
191 p2tr_point_get_mesh (P2trPoint *self)
192 {
193   if (self->mesh)
194     return p2tr_mesh_ref (self->mesh);
195   else
196     return NULL;
197 }