--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
#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