--- /dev/null
+#include <math.h>
+#include <glib.h>
+#include "point.h"
+#include "edge.h"
+
+static void
+p2tr_edge_init (P2trEdge *self,
+ P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained,
+ P2trEdge *mirror)
+{
+ self->angle = atan2 (end->y - start->y, end->x - start->x);
+ self->constrained = constrained;
+ self->delaunay = FALSE;
+ self->end = end;
+ self->mirror = mirror;
+ self->refcount = 0;
+ self->removed = FALSE;
+ self->tri = NULL;
+}
+
+P2trEdge*
+p2tr_edge_new (P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained)
+{
+ P2trEdge *self = g_slice_new (P2trEdge);
+ P2trEdge *mirror = g_slice_new (P2trEdge);
+
+ p2tr_edge_init (self, start, end, constrained, mirror);
+ p2tr_edge_init (mirror, end, start, constrained, self);
+
+ p2tr_point_ref (start);
+ p2tr_point_ref (end);
+
+ _p2tr_point_insert_edge (start, self);
+ _p2tr_point_insert_edge (end, mirror);
+
+ ++self->refcount;
+ return self;
+}
+
+void
+p2tr_edge_ref (P2trEdge *self)
+{
+ ++self->refcount;
+}
+
+void
+p2tr_edge_unref (P2trEdge *self)
+{
+ if (--self->refcount == 0 && self->mirror->refcount == 0)
+ p2tr_edge_free (self);
+}
+
+gboolean
+p2tr_edge_is_removed (P2trEdge *self)
+{
+ return self->end == NULL;
+}
+
+static void
+p2tr_edge_remove_one_side (P2trEdge *self)
+{
+ if (self->tri != NULL)
+ {
+ p2tr_triangle_remove (self->tri);
+ p2tr_triangle_unref (self->tri);
+ self->tri = NULL;
+ }
+ _p2tr_point_remove_edge(P2TR_EDGE_START(self), self);
+ p2tr_point_unref (self->end);
+ self->end = NULL;
+}
+
+void
+p2tr_edge_remove (P2trEdge *self)
+{
+ P2trMesh *mesh;
+
+ if (self->end == NULL) /* This is only true if the edge was removed */
+ return;
+
+ mesh = p2tr_edge_get_mesh (self);
+ p2tr_edge_remove_one_side (self);
+ p2tr_edge_remove_one_side (self->mirror);
+
+ if (mesh != NULL)
+ {
+ p2tr_mesh_on_edge_removed (self);
+ p2tr_mesh_on_edge_removed (self->mirror);
+ }
+}
+
+void
+p2tr_edge_free (P2trEdge *self)
+{
+ p2tr_edge_remove (self);
+ g_slice_free (P2trEdge, self);
+ g_slice_free (P2trEdge, self->mirror);
+}
+
+void
+p2tr_edge_get_diametral_circle (P2trEdge *self,
+ P2trCircle *circle)
+{
+ P2trVector2 radius;
+
+ p2tr_vector2_center (self->end, P2TR_EDGE_START(self), &circle->center);
+ p2tr_vector2_sub (self->end, &circle->center, &radius);
+
+ circle->radius = p2tr_vector2_norm (&radius);
+}
+
+//public void p2tr_edge_remove(P2trTriangulation t)
+//{
+// _p2tr_edge_remove(T, false);
+//}
+
+//private void _p2tr_edge_remove(P2trTriangulation t, bool is_mirror)
+//{
+// if (this.removed)
+// return;
+//
+// t.edges.Remove(this);
+// this.removed = true;
+//
+// this.start.p2tr_point_remove_edge(this);
+//
+// if (this.tri != null)
+// this.tri.p2tr_triangle_remove(t);
+//
+// if (! is_mirror)
+// this.mirror._p2tr_edge_remove(t, true);
+//}
+
+gdouble
+p2tr_edge_get_length(P2trEdge* self)
+{
+ return sqrt (p2tr_math_length_sq2 (&self->end, &P2TR_EDGE_START(self)));
+}
+
+gdouble
+p2tr_edge_get_length_squared(P2trEdge* self)
+{
+ return p2tr_math_length_sq2 (&self->end, &P2TR_EDGE_START(self));
+}
+
+gdouble
+p2tr_edge_angle_between(P2trEdge *e1, P2trEdge *e2)
+{
+ /* A = E1.angle, a = abs (A)
+ * B = E1.angle, b = abs (B)
+ *
+ * W is the angle we wish to find. Note the fact that we want
+ * to find the angle so that the edges go CLOCKWISE around it.
+ *
+ * Case 1: Signs of A and B agree | Case 2: Signs of A and B disagree
+ * and A > 0 | and A > 0
+ * |
+ * a = A, b = B | a = A, b = -B
+ * ^^ |
+ * E2 // | /
+ * //\ | /
+ * //b| | /a
+ * - - - - * - |W- - - - - - - - | - - - - * - - - -
+ * ^^a'| | ^^ \\b
+ * ||_/ | // W \\
+ * E1 ||\ | E1 // \_/ \\ E2
+ * '||a\ | // \\
+ * - - - - - - | // vv
+ * |
+ * W = A' + B = (180 - A) + B | W = 180 - (a + b) = 180 - (A - B)
+ * W = 180 - A + B | W = 180 - A + B
+ *
+ * By the illustration above, we can see that in general the angle W
+ * can be computed by W = 180 - A + B in every case. The only thing to
+ * note is that the range of the result of the computation is
+ * [180 - 360, 180 + 360] = [-180, +540] so we may need to subtract
+ * 360 to put it back in the range [-180, +180].
+ */
+ if (e1->end != P2TR_EDGE_START(e2))
+ p2tr_exception_programmatic ("The end-point of the first edge isn't"
+ " the end-point of the second edge!");
+
+ gdouble result = G_PI - e1->angle + e2->angle;
+ if (result > 2 * G_PI)
+ result -= 2 * G_PI;
+ return result;
+}
\ No newline at end of file
/**
* 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
+ * it here since it's heavily used and the computation is expensive.
+ * The angle increases as we go CCW, and it's in the range [-PI,+PI]
*/
gdouble angle;
#define P2TR_EDGE_START(E) ((E)->mirror->end)
-void p2tr_edge_ref (P2trEdge *self);
-void p2tr_edge_unref (P2trEdge *self);
+void p2tr_edge_new (P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained);
+void p2tr_edge_ref (P2trEdge *self);
+
+void p2tr_edge_unref (P2trEdge *self);
+
+void p2tr_edge_free (P2trEdge *self);
+
+void p2tr_edge_remove (P2trEdge *self);
+
+void p2tr_edge_get_mesh (P2trEdge *self);
+
+gboolean p2tr_edge_is_removed (P2trEdge *self);
#endif
\ No newline at end of file
P2trEdge *BC,
P2trEdge *CA);
-gboolean p2tr_mesh_remove_point (P2trMesh *mesh,
- P2trEdge *edge);
+gboolean p2tr_mesh_on_point_removed (P2trMesh *mesh,
+ P2trPoint *point);
-gboolean p2tr_mesh_remove_edge (P2trMesh *mesh,
- P2trEdge *edge);
+gboolean p2tr_mesh_on_edge_removed (P2trMesh *mesh,
+ P2trEdge *edge);
-gboolean p2tr_mesh_remove_triangle (P2trMesh *mesh,
- P2trTriangle *triangle);
+gboolean p2tr_mesh_on_triangle_removed (P2trMesh *mesh,
+ P2trTriangle *triangle);
void p2tr_mesh_clear (P2trMesh *mesh);
void p2tr_mesh_destroy (P2trMesh *mesh);
+void p2tr_mesh_unref (P2trMesh *mesh);
+
+void p2tr_mesh_ref (P2trMesh *mesh);
+
#endif
\ No newline at end of file
P2trPoint *self = g_slice_new (P2trPoint);
p2tr_vector2_copy (&self->c, c);
+ self->mesh = NULL;
self->outgoing_edges = NULL;
-
+ self->refcount = 1;
+
return self;
}
-static void
-p2tr_point_delete (P2trPoint *self)
+void
+p2tr_point_remove (P2trPoint *self)
{
- GList *iter;
- for (iter = self->outgoing_edges; iter != NULL; iter = iter->next)
- p2tr_edge_unref ((P2trEdge*) iter->data);
+ /* We can not iterate over the list of edges while removing the edges,
+ * because the removal action will modify the list. Instead we will
+ * simply look at the first edge untill the list is emptied. */
+ while (self->outgoing_edges != NULL)
+ p2tr_edge_remove ((P2trEdge*) self->outgoing_edges->data);
+
+ if (self->mesh != NULL)
+ {
+ p2tr_mesh_on_point_removed (self->mesh, self);
+ p2tr_mesh_unref (self->mesh);
+ self->mesh = NULL;
+ }
+}
- g_list_free (self->outgoing_edges);
+void
+p2tr_point_free (P2trPoint *self)
+{
+ p2tr_point_remove (self);
g_slice_free (P2trPoint, self);
}
p2tr_point_unref (P2trPoint *self)
{
if (--self->refcount == 0)
- p2tr_point_delete (self);
+ p2tr_point_free (self);
+}
+
+P2trMesh*
+p2tr_point_get_mesh (P2trPoint *self)
+{
+ return self->mesh;
}
\ No newline at end of file
/** A count of references to the point */
guint refcount;
+
+ /** The triangular mesh containing this point */
+ P2trMesh *mesh;
};
P2trPoint* p2tr_point_new (const P2trVector2 *c);
+void p2tr_point_ref (P2trPoint *self);
+
+void p2tr_point_unref (P2trPoint *self);
+
+void p2tr_point_free (P2trPoint *self);
+
+void p2tr_point_remove (P2trPoint *self);
+
P2trEdge* p2tr_point_get_edge_to (P2trPoint *start,
P2trPoint *end);
gboolean p2tr_point_has_constrained_edge (P2trPoint *self);
-void p2tr_point_ref (P2trPoint *self);
-
-void p2tr_point_unref (P2trPoint *self);
+P2trMesh* p2tr_point_get_mesh (P2trPoint *self);
#endif
\ No newline at end of file
--- /dev/null
+#ifndef __P2TC_REFINE_TRIANGLE_H__
+#define __P2TC_REFINE_TRIANGLE_H__
+
+#include <glib.h>
+#include "triangulation.h"
+
+/**
+ * @struct P2trTriangle_
+ * A struct for a triangle in a triangular mesh
+ */
+struct P2trTriangle_
+{
+ /** 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.
+ * The angle increases as we go CCW, and it's in the range [-PI, +PI]
+ */
+ 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;
+
+ /**
+ * Is this edge still present in the triangulation? Or maybe it is
+ * just pending for the last unref?
+ */
+ gboolean removed;
+};
+
+#define P2TR_EDGE_START(E) ((E)->mirror->end)
+
+void p2tr_edge_ref (P2trEdge *self);
+void p2tr_edge_unref (P2trEdge *self);
+
+void p2tr_edge_remove (P2trEdge *self);
+#endif
\ No newline at end of file
dest->y = a->y - b->y;\r
}\r
\r
+void\r
+p2tr_vector2_center (const P2trVector2 *a,\r
+ const P2trVector2 *b,\r
+ P2trVector2 *dest)\r
+{\r
+ dest->x = (a->x + b->x) * 0.5;\r
+ dest->y = (a->y + b->y) * 0.5;\r
+}\r
+\r
gdouble\r
p2tr_vector2_norm (const P2trVector2 *v)\r
{\r
*/\r
void p2tr_vector2_sub (const P2trVector2 *a, const P2trVector2 *b, P2trVector2 *dest);\r
\r
+/**\r
+ * Compute the center point of the edge defined between two points\r
+ * @param[in] a The first side of the edge\r
+ * @param[in] b The second side of the edge\r
+ * @param[out] dest The vector in which the result should be stored\r
+ */\r
+void p2tr_vector2_center (const P2trVector2 *a, const P2trVector2 *b, P2trVector2 *dest);\r
+\r
/**\r
* Compute the norm of a vector (the length of the line from the origin\r
* to the 2D point it represents)\r