From: Barak Itkin Date: Sat, 21 Apr 2012 12:05:58 +0000 (+0300) Subject: Add the initial code for triangular meshes (Most work was on P2trPoint) X-Git-Tag: p2tc-0.1.0~102 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=02d3fb2c624b9e064ba0a6210dd48f9090405150;p=poly2tri-c Add the initial code for triangular meshes (Most work was on P2trPoint) --- diff --git a/refine/edge.h b/refine/edge.h new file mode 100644 index 0000000..b3709c1 --- /dev/null +++ b/refine/edge.h @@ -0,0 +1,47 @@ +#ifndef __P2TC_REFINE_EDGE_H__ +#define __P2TC_REFINE_EDGE_H__ + +#include +#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 index 0000000..db5217d --- /dev/null +++ b/refine/mesh.h @@ -0,0 +1,48 @@ +#ifndef __P2TC_REFINE_MESH_H__ +#define __P2TC_REFINE_MESH_H__ + +#include +#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 index 0000000..5b72ed2 --- /dev/null +++ b/refine/point.c @@ -0,0 +1,154 @@ +#include +#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 index 0000000..b975f52 --- /dev/null +++ b/refine/point.h @@ -0,0 +1,52 @@ +#ifndef __P2TC_REFINE_POINT_H__ +#define __P2TC_REFINE_POINT_H__ + +#include +#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 index 0000000..cdeb2fc --- /dev/null +++ b/refine/triangulation.h @@ -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 diff --git a/refine/utils.h b/refine/utils.h index b98931b..3f651a4 100755 --- a/refine/utils.h +++ b/refine/utils.h @@ -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