*\r
* http://www.blackpawn.com/texts/pointinpoly/default.html\r
*/\r
-#define INTRIANGLE_EPSILON 0e-9\r
-\r
-P2trInTriangle\r
-p2tr_math_intriangle(const P2trVector2 *A,\r
- const P2trVector2 *B,\r
- const P2trVector2 *C,\r
- const P2trVector2 *P)\r
+void\r
+p2tr_math_triangle_barcycentric (const P2trVector2 *A,\r
+ const P2trVector2 *B,\r
+ const P2trVector2 *C,\r
+ const P2trVector2 *P,\r
+ gdouble *u,\r
+ gdouble *v)\r
{\r
+ gdouble dot00, dot01, dot02, dot11, dot12, invDenom;\r
+\r
/* Compute the vectors offsetted so that A is the origin */\r
P2trVector2 v0, v1, v2;\r
p2tr_vector2_sub(C, A, &v0);\r
p2tr_vector2_sub(P, A, &v2);\r
\r
/* Compute dot products */\r
- double dot00 = VECTOR2_DOT(&v0, &v0);\r
- double dot01 = VECTOR2_DOT(&v0, &v1);\r
- double dot02 = VECTOR2_DOT(&v0, &v2);\r
- double dot11 = VECTOR2_DOT(&v1, &v1);\r
- double dot12 = VECTOR2_DOT(&v1, &v2);\r
+ dot00 = VECTOR2_DOT(&v0, &v0);\r
+ dot01 = VECTOR2_DOT(&v0, &v1);\r
+ dot02 = VECTOR2_DOT(&v0, &v2);\r
+ dot11 = VECTOR2_DOT(&v1, &v1);\r
+ dot12 = VECTOR2_DOT(&v1, &v2);\r
\r
/* Compute barycentric coordinates */\r
- double invDenom = 1 / (dot00 * dot11 - dot01 * dot01);\r
- double u = (dot11 * dot02 - dot01 * dot12) * invDenom;\r
- double v = (dot00 * dot12 - dot01 * dot02) * invDenom;\r
+ invDenom = 1 / (dot00 * dot11 - dot01 * dot01);\r
+ *u = (dot11 * dot02 - dot01 * dot12) * invDenom;\r
+ *v = (dot00 * dot12 - dot01 * dot02) * invDenom;\r
+}\r
+\r
+#define INTRIANGLE_EPSILON 0e-9\r
+\r
+P2trInTriangle\r
+p2tr_math_intriangle (const P2trVector2 *A,\r
+ const P2trVector2 *B,\r
+ const P2trVector2 *C,\r
+ const P2trVector2 *P)\r
+{\r
+ gdouble u, v;\r
\r
+ p2tr_math_triangle_barcycentric(A, B, C, P, &u, &v);\r
+ \r
/* Check if point is in triangle - i.e. whether (u + v) < 1 and both\r
* u and v are positive */\r
if ((u >= INTRIANGLE_EPSILON) && (v >= INTRIANGLE_EPSILON) && (u + v < 1 - INTRIANGLE_EPSILON))\r
P2TR_INTRIANGLE_IN = 1\r
} P2trInTriangle;
+/**\r
+ * Return the barycentric coordinates of a point inside a triangle. This\r
+ * means that the computation returns @ref u and @ref v so that the\r
+ * following equation is satisfied:\r
+ * {{{ AP = u * AB + v * AC }}}\r
+ *\r
+ * @param[in] A The first point of the triangle\r
+ * @param[in] B The second point of the triangle\r
+ * @param[in] C The third point of the triangle\r
+ * @param[in] P The point whose barycentric coordinates should be\r
+ * computed\r
+ * @param[out] u The first barycentric coordinate\r
+ * @param[out] v The second barycentric coordinate\r
+ */\r
+void p2tr_math_triangle_barcycentric (const P2trVector2 *A,\r
+ const P2trVector2 *B,\r
+ const P2trVector2 *C,\r
+ const P2trVector2 *P,\r
+ gdouble *u,\r
+ gdouble *v);\r
+\r
P2trInTriangle p2tr_math_intriangle (const P2trVector2 *A,\r
const P2trVector2 *B,\r
const P2trVector2 *C,\r
--- /dev/null
+#include <glib.h>
+#include "utils.h"
+
+#include "mesh.h"
+#include "point.h"
+#include "edge.h"
+#include "triangle.h"
+
+P2trMesh*
+p2tr_mesh_new (void)
+{
+ P2trMesh *mesh = g_slice_new (P2trMesh);
+
+ mesh->refcount = 1;
+ mesh->edges = p2tr_hash_set_new_default ();
+ mesh->points = p2tr_hash_set_new_default ();
+ mesh->triangles = p2tr_hash_set_new_default ();
+
+ mesh->_is_clearing_now = FALSE;
+
+ return mesh;
+}
+
+P2trPoint*
+p2tr_mesh_new_point (P2trMesh *self,
+ const P2trVector2 *c)
+{
+ P2trPoint *pt = p2tr_point_new (c);
+
+ pt->mesh = self;
+ p2tr_mesh_ref (self);
+
+ p2tr_hash_set_insert (self->points, pt);
+ p2tr_point_ref (pt);
+
+ return pt;
+}
+
+P2trEdge*
+p2tr_mesh_new_edge (P2trMesh *self,
+ P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained)
+{
+ P2trEdge *ed = p2tr_edge_new (start, end, constrained);
+
+ p2tr_hash_set_insert (self->edges, ed);
+ p2tr_pdge_ref (ed);
+
+ return ed;
+}
+
+P2trTriangle*
+p2tr_mesh_new_triangle (P2trMesh *self,
+ P2trEdge *AB,
+ P2trEdge *BC,
+ P2trEdge *CA)
+{
+ P2trTriangle *tr = p2tr_triangle_new (AB, BC, CA);
+
+ p2tr_hash_set_insert (self->triangles, tr);
+ p2tr_pdge_ref (tr);
+
+ return tr;
+}
+
+void
+p2tr_mesh_on_point_removed (P2trMesh *self,
+ P2trPoint *point)
+{
+ if (self != point->mesh)
+ p2tr_exception_programmatic ("Point does not belong to this mesh!");
+
+ point->mesh = NULL;
+ p2tr_mesh_unref (self);
+
+ if (! self->_is_clearing_now)
+ p2tr_hash_set_remove (self->points, point);
+ p2tr_point_unref (point);
+}
+
+void
+p2tr_mesh_on_edge_removed (P2trMesh *self,
+ P2trEdge *edge)
+{
+ if (! self->_is_clearing_now)
+ p2tr_hash_set_remove (self->edges, edge);
+ p2tr_edge_unref (edge);
+}
+
+void
+p2tr_mesh_on_triangle_removed (P2trMesh *self,
+ P2trTriangle *triangle)
+{
+ if (! self->_is_clearing_now)
+ p2tr_hash_set_remove (self->triangles, triangle);
+ p2tr_triangle_unref (triangle);
+}
+
+void
+p2tr_mesh_clear (P2trMesh *self)
+{
+ P2trHashSetIter iter;
+ gpointer temp;
+
+ self->_is_clearing_now = TRUE;
+
+ p2tr_hash_set_iter_init (&iter, self->triangles);
+ while (p2tr_hash_set_iter_next (&iter, &temp))
+ p2tr_triangle_remove ((P2trTriangle*)temp);
+ p2tr_hash_set_remove_all (self->triangles);
+
+ p2tr_hash_set_iter_init (&iter, self->edges);
+ while (p2tr_hash_set_iter_next (&iter, &temp))
+ p2tr_edge_remove ((P2trEdge*)temp);
+ p2tr_hash_set_remove_all (self->edges);
+
+ p2tr_hash_set_iter_init (&iter, self->points);
+ while (p2tr_hash_set_iter_next (&iter, &temp))
+ p2tr_point_remove ((P2trPoint*)temp);
+ p2tr_hash_set_remove_all (self->points);
+
+ self->_is_clearing_now = FALSE;
+}
+
+void
+p2tr_mesh_free (P2trMesh *self)
+{
+ p2tr_mesh_clear (self);
+
+ p2tr_hash_set_free (self->points);
+ p2tr_hash_set_free (self->edges);
+ p2tr_hash_set_free (self->triangles);
+
+ g_slice_free (P2trMesh, self);
+}
+
+void
+p2tr_mesh_unref (P2trMesh *self)
+{
+ if (--self->refcount == 0)
+ p2tr_mesh_free (self);
+}
+
+void
+p2tr_mesh_ref (P2trMesh *self)
+{
+ ++self->refcount;
+}
#define __P2TC_REFINE_MESH_H__
#include <glib.h>
+#include "vector2.h"
#include "utils.h"
#include "triangulation.h"
P2trHashSet *triangles;
P2trHashSet *edges;
P2trHashSet *points;
+
+ guint refcount;
+
+ gboolean _is_clearing_now;
};
P2trMesh* p2tr_mesh_new (void);
const P2trVector2 *c);
P2trEdge* p2tr_mesh_new_edge (P2trMesh *mesh,
- P2trPoint *A,
- P2trPoint *B,
+ P2trPoint *start,
+ P2trPoint *end,
gboolean constrained);
-P2trTriangle* p2tr_mesh_new_triangle (P2trMesh *mesh,
- P2trPoint *A,
- P2trPoint *B,
- P2trPoint *C);
+P2trTriangle* p2tr_mesh_new_triangle (P2trMesh *mesh,
+ P2trEdge *AB,
+ P2trEdge *BC,
+ P2trEdge *CA);
-P2trTriangle* p2tr_mesh_new_triangle2 (P2trMesh *mesh,
- P2trEdge *AB,
- P2trEdge *BC,
- P2trEdge *CA);
-
-gboolean p2tr_mesh_on_point_removed (P2trMesh *mesh,
+void p2tr_mesh_on_point_removed (P2trMesh *mesh,
P2trPoint *point);
-gboolean p2tr_mesh_on_edge_removed (P2trMesh *mesh,
+void p2tr_mesh_on_edge_removed (P2trMesh *mesh,
P2trEdge *edge);
-gboolean p2tr_mesh_on_triangle_removed (P2trMesh *mesh,
+void p2tr_mesh_on_triangle_removed (P2trMesh *mesh,
P2trTriangle *triangle);
void p2tr_mesh_clear (P2trMesh *mesh);
typedef GHashTable P2trHashSet;
typedef GHashTableIter P2trHashSetIter;
-#define p2tr_hash_set_set_new(hash_func, equal_func, destroy) g_hash_table_new_full ((hash_func), (equal_func), (destroy),NULL)
+#define p2tr_hash_set_new_default() g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL)
+#define p2tr_hash_set_new(hash_func, equal_func, destroy) g_hash_table_new_full ((hash_func), (equal_func), (destroy),NULL)
#define p2tr_hash_set_insert(set,element) g_hash_table_insert ((set), (element), (element))
#define p2tr_hash_set_contains(set,element) g_hash_table_lookup_extended ((set), (element), NULL, NULL)
#define p2tr_hash_set_remove(set,element) g_hash_table_remove ((set), (element))
+#define p2tr_hash_set_remove_all(set) g_hash_table_remove_all ((set))
+#define p2tr_hash_set_free(set) g_hash_table_destroy(set)
#define p2tr_hash_set_iter_init(iter,hash_set) g_hash_table_iter_init ((iter),(hash_set))
#define p2tr_hash_set_iter_next(iter,val) g_hash_table_iter_next ((iter),(val),NULL)