noinst_LTLIBRARIES = libp2tc-refine.la
-libp2tc_refine_la_SOURCES = bounded-line.c bounded-line.h cdt.c cdt.h circle.c circle.h cluster.c cluster.h delaunay-terminator.c delaunay-terminator.h edge.c edge.h line.c line.h rmath.c rmath.h mesh.c mesh.h point.c point.h pslg.c pslg.h refine.h refiner.c refiner.h triangle.c triangle.h triangulation.h utils.c utils.h vector2.c vector2.h vedge.c vedge.h vtriangle.c vtriangle.h visibility.c visibility.h
+libp2tc_refine_la_SOURCES = bounded-line.c bounded-line.h cdt.c cdt.h cdt-flipfix.c cdt-flipfix.h circle.c circle.h cluster.c cluster.h delaunay-terminator.c delaunay-terminator.h edge.c edge.h line.c line.h rmath.c rmath.h mesh.c mesh.h point.c point.h pslg.c pslg.h refine.h refiner.c refiner.h triangle.c triangle.h triangulation.h utils.c utils.h vector2.c vector2.h vedge.c vedge.h vtriangle.c vtriangle.h visibility.c visibility.h
P2TC_REFINE_publicdir = $(P2TC_publicdir)/refine
P2TC_REFINE_public_HEADERS = bounded-line.h cdt.h circle.h cluster.h edge.h line.h mesh.h point.h pslg.h refine.h refiner.h rmath.h triangle.h triangulation.h utils.h vector2.h vedge.h vtriangle.h visibility.h
--- /dev/null
+/*
+ * This file is a part of Poly2Tri-C
+ * (c) Barak Itkin <lightningismyname@gmail.com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Poly2Tri nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <glib.h>
+
+#include "point.h"
+#include "edge.h"
+#include "triangle.h"
+#include "vedge.h"
+
+#include "cdt-flipfix.h"
+
+
+static P2trEdge* p2tr_cdt_try_flip (P2trCDT *self,
+ P2trEdge *to_flip);
+
+P2trFlipSet*
+p2tr_flip_set_new ()
+{
+ return p2tr_hash_set_new (
+ (GHashFunc) p2tr_vedge_undirected_hash,
+ (GEqualFunc) p2tr_vedge_undirected_equals,
+ NULL
+ );
+}
+
+void
+p2tr_flip_set_add (P2trFlipSet *self,
+ P2trEdge *to_flip)
+{
+ p2tr_flip_set_add2 (self, p2tr_vedge_new2 (to_flip));
+ p2tr_edge_unref (to_flip);
+}
+
+void
+p2tr_flip_set_add2 (P2trFlipSet *self,
+ P2trVEdge *to_flip)
+{
+ if (p2tr_hash_set_contains (self, to_flip))
+ p2tr_vedge_unref (to_flip);
+ else
+ p2tr_hash_set_insert (self, to_flip);
+}
+
+gboolean
+p2tr_flip_set_pop (P2trFlipSet *self,
+ P2trVEdge **value)
+{
+ P2trHashSetIter iter;
+ p2tr_hash_set_iter_init (&iter, self);
+ if (p2tr_hash_set_iter_next (&iter, (gpointer*) value))
+ {
+ p2tr_hash_set_remove (self, *value);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+void
+p2tr_flip_set_free (P2trFlipSet *self)
+{
+ g_assert (p2tr_hash_set_size (self) == 0);
+ p2tr_hash_set_free (self);
+}
+
+/* This function implements "Lawson's algorithm", also known as "The
+ * diagonal swapping algorithm". This algorithm takes a CDT, and a list
+ * of triangles that were formed by the insertion of a new point into
+ * the triangular mesh, and makes the triangulation a CDT once more. Its
+ * logic is explained below:
+ *
+ * If a point is added to an existing triangular mesh then
+ * circumcircles are formed for all new triangles formed. If any of
+ * the neighbours lie inside the circumcircle of any triangle, then a
+ * quadrilateral is formed using the triangle and its neighbour. The
+ * diagonals of this quadrilateral are swapped to give a new
+ * triangulation. This process is continued till there are no more
+ * faulty triangles and no more swaps are required.
+ *
+ * The description above may seem slightly inaccurate, as it does not
+ * consider the case were the diagonals can not be swapped since the
+ * quadrilateral is concave (then swapping the diagonals would result
+ * in a diagonal outside the quad, which is undesired).
+ *
+ * However, the description above is accurate. If the opposite point
+ * is inside the circular cut created by the edge, then since the
+ * circular cut is inside the infinite area created by extending the
+ * two other edges of the triangle, therefor the point is also inside
+ * that area - meaning that the quadrilateral is not concave!
+ */
+
+void
+p2tr_cdt_flip_fix (P2trCDT *self,
+ P2trFlipSet *candidates)
+{
+ P2trEdge *edge;
+ P2trVEdge *vedge;
+
+ while (p2tr_flip_set_pop (candidates, &vedge))
+ {
+ if (! p2tr_vedge_try_get_and_unref (vedge, &edge))
+ continue;
+
+ if (! edge->constrained
+ /* TODO: we probably don't need this check... */
+ && ! p2tr_edge_is_removed (edge))
+ {
+ /* If the edge is not constrained, then it should be
+ * a part of two triangles */
+ P2trPoint *A = P2TR_EDGE_START(edge), *B = edge->end;
+ P2trPoint *C1 = p2tr_triangle_get_opposite_point (edge->tri, edge, FALSE);
+ P2trPoint *C2 = p2tr_triangle_get_opposite_point (edge->mirror->tri, edge->mirror, FALSE);
+
+ P2trEdge *flipped = p2tr_cdt_try_flip (self, edge);
+ if (flipped != NULL)
+ {
+ p2tr_flip_set_add2 (candidates, p2tr_vedge_new (A, C1));
+ p2tr_flip_set_add2 (candidates, p2tr_vedge_new (A, C2));
+ p2tr_flip_set_add2 (candidates, p2tr_vedge_new (B, C1));
+ p2tr_flip_set_add2 (candidates, p2tr_vedge_new (B, C2));
+ p2tr_edge_unref (flipped);
+ }
+ }
+
+ p2tr_edge_unref (edge);
+ }
+}
+
+/**
+ * Try to flip a given edge, If successfull, return the new edge (reffed!),
+ * otherwise return NULL
+ */
+P2trEdge*
+p2tr_cdt_try_flip (P2trCDT *self,
+ P2trEdge *to_flip)
+{
+ /* C
+ * / | \
+ * B-----A to_flip: A->B
+ * \ | / to_flip.Tri: ABC
+ * D
+ */
+ P2trPoint *A, *B, *C, *D;
+ P2trEdge *AB, *CA, *AD, *DB, *BC, *DC;
+
+ g_assert (! to_flip->constrained && ! to_flip->delaunay);
+
+ A = P2TR_EDGE_START (to_flip);
+ B = to_flip->end;
+ C = p2tr_triangle_get_opposite_point (to_flip->tri, to_flip, FALSE);
+ D = p2tr_triangle_get_opposite_point (to_flip->mirror->tri, to_flip->mirror, FALSE);
+
+ AB = to_flip;
+
+ CA = p2tr_point_get_edge_to (C, A, FALSE);
+ AD = p2tr_point_get_edge_to (A, D, FALSE);
+ DB = p2tr_point_get_edge_to (D, B, FALSE);
+ BC = p2tr_point_get_edge_to (B, C, FALSE);
+
+ /* Check if the quadriliteral ADBC is concave (because if it is, we
+ * can't flip the edge) */
+ if (p2tr_triangle_circumcircle_contains_point (AB->tri, &D->c) != P2TR_INCIRCLE_IN)
+ return NULL;
+
+ p2tr_edge_remove (AB);
+
+ DC = p2tr_mesh_new_edge (self->mesh, D, C, FALSE);
+
+ p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh,
+ CA, AD, DC));
+
+ p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh,
+ DB, BC, DC->mirror));
+
+ return DC;
+}
+
+gboolean
+p2tr_vedge_undirected_equals (const P2trVEdge *e1,
+ const P2trVEdge *e2)
+{
+ return ((e1 == NULL) == (e2 == NULL)) &&
+ (e1 == e2
+ || (e1->start == e2->start && e1->end == e2->end)
+ || (e1->end == e2->start && e1->start == e2->end));
+}
+
+guint
+p2tr_vedge_undirected_hash (const P2trVEdge *edge)
+{
+ return g_direct_hash (edge->start) ^ g_direct_hash (edge->end);
+}
+
--- /dev/null
+/*
+ * This file is a part of Poly2Tri-C
+ * (c) Barak Itkin <lightningismyname@gmail.com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Poly2Tri nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __P2TC_REFINE_CDT_FLIPFIX_H__
+#define __P2TC_REFINE_CDT_FLIPFIX_H__
+
+#include <glib.h>
+
+#include "edge.h"
+#include "vedge.h"
+#include "cdt.h"
+#include "utils.h"
+
+/**
+ * A set of edges to flip is basically a hash set, with unique equality
+ * and hashing function to prevent the same edge from appearing twice
+ * in different directions
+ */
+typedef P2trHashSet P2trFlipSet;
+
+/**
+ * Create a new flip-set - a set of virtual edges that should possibly
+ * be flipped to restore the Constrained Delaunay property to a
+ * triangulation
+*/
+P2trFlipSet* p2tr_flip_set_new ();
+
+/**
+ * Add the given edge to the flip set. THE EDGE MUST HAVE BEEN REFFED
+ * BEFORE THE CALL TO THIS FUNCTION!
+ */
+void p2tr_flip_set_add (P2trFlipSet *self,
+ P2trEdge *to_flip);
+
+/**
+ * Add the given virtual edge to the flip set. THE VIRTUAL EDGE MUST
+ * HAVE BEEN REFFED BEFORE THE CALL TO THIS FUNCTION!
+ */
+void p2tr_flip_set_add2 (P2trFlipSet *self,
+ P2trVEdge *to_flip);
+
+/**
+ * Try popping a virtual edge from the set. If succeeds, THE RETURNED
+ * VIRTUAL EDGE MUST BE UNREFFED!
+ */
+gboolean p2tr_flip_set_pop (P2trFlipSet *self,
+ P2trVEdge **value);
+
+/**
+ * Free the flip set. IT IS THE REPONSIBILITY OF THE CALLER TO MAKE
+ * SURE NO VIRTUAL EDGES WERE LEFT IN THE SET!
+ */
+void p2tr_flip_set_free (P2trFlipSet *self);
+
+/**
+ * Flip-Fix all the virtual edges inside the given set
+ */
+void p2tr_cdt_flip_fix (P2trCDT *self,
+ P2trFlipSet *candidates);
+
+
+gboolean p2tr_vedge_undirected_equals (const P2trVEdge *e1,
+ const P2trVEdge *e2);
+
+guint p2tr_vedge_undirected_hash (const P2trVEdge *edge);
+
+#endif
#include "cdt.h"
#include "visibility.h"
+#include "cdt-flipfix.h"
static gboolean p2tr_cdt_visible_from_tri (P2trCDT *self,
P2trTriangle *tri,
P2trPoint *center,
GList *edge_pts);
-static void p2tr_cdt_add_edge (P2trHashSet *candidates,
- P2trEdge *candidate);
-
-static void p2tr_cdt_flip_fix (P2trCDT *self,
- P2trHashSet *candidates);
-
-static P2trEdge* p2tr_cdt_try_flip (P2trCDT *self,
- P2trEdge *to_flip);
-
-static void p2tr_cdt_on_new_point (P2trCDT *self,
- P2trPoint *pt);
-
void
p2tr_cdt_validate_unused (P2trCDT* self)
{
P2trCDT *rmesh = g_slice_new (P2trCDT);
GHashTableIter iter;
P2trPoint *pt_iter = NULL;
- P2trHashSet *new_edges = p2tr_hash_set_new_default ();
+
+ P2trFlipSet *new_edges = p2tr_flip_set_new ();
gint i, j;
/* We only wanted to create the edge now. We will use it
* later */
- p2tr_cdt_add_edge (new_edges, edge);
+ p2tr_flip_set_add (new_edges, edge);
}
}
}
/* And do an extra flip fix */
p2tr_cdt_flip_fix (rmesh, new_edges);
- p2tr_hash_set_free (new_edges);
+ p2tr_flip_set_free (new_edges);
/* Now finally unref the points we added into the map */
g_hash_table_iter_init (&iter, point_map);
/* If we reached this line, then the point is inside the triangle */
p2tr_cdt_insert_point_into_triangle (self, pt, tri);
- p2tr_cdt_on_new_point (self, pt);
-
/* We no longer need the triangle */
p2tr_triangle_unref (tri);
P2trPoint *P,
P2trTriangle *tri)
{
- P2trHashSet *flip_candidates = p2tr_hash_set_new_default ();
+ P2trFlipSet *flip_candidates = p2tr_flip_set_new ();
P2trPoint *A = tri->edges[0]->end;
P2trPoint *B = tri->edges[1]->end;
p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh, BC, CP, BP->mirror));
p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh, CA, AP, CP->mirror));
- p2tr_cdt_add_edge (flip_candidates, CP);
- p2tr_cdt_add_edge (flip_candidates, AP);
- p2tr_cdt_add_edge (flip_candidates, BP);
+ p2tr_flip_set_add (flip_candidates, CP);
+ p2tr_flip_set_add (flip_candidates, AP);
+ p2tr_flip_set_add (flip_candidates, BP);
- p2tr_cdt_add_edge (flip_candidates, p2tr_edge_ref (CA));
- p2tr_cdt_add_edge (flip_candidates, p2tr_edge_ref (AB));
- p2tr_cdt_add_edge (flip_candidates, p2tr_edge_ref (BC));
+ p2tr_flip_set_add (flip_candidates, p2tr_edge_ref (CA));
+ p2tr_flip_set_add (flip_candidates, p2tr_edge_ref (AB));
+ p2tr_flip_set_add (flip_candidates, p2tr_edge_ref (BC));
/* Flip fix the newly created triangles to preserve the the
* constrained delaunay property. The flip-fix function will unref the
* new triangles for us! */
p2tr_cdt_flip_fix (self, flip_candidates);
- p2tr_hash_set_free (flip_candidates);
+ p2tr_flip_set_free (flip_candidates);
}
/**
* created (these are the two that would have used it)
* 2. THE RETURNED EDGES MUST BE UNREFFED!
*/
-static P2trHashSet*
+static P2trFlipSet*
p2tr_cdt_triangulate_fan (P2trCDT *self,
P2trPoint *center,
GList *edge_pts)
{
- P2trHashSet* fan_edges = p2tr_hash_set_new_default ();
+ P2trFlipSet* fan_edges = p2tr_flip_set_new ();
GList *iter;
/* We can not triangulate unless at least two points are given */
p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh, AB, BC, CA));
- p2tr_cdt_add_edge (fan_edges, CA);
- p2tr_cdt_add_edge (fan_edges, BC);
- p2tr_cdt_add_edge (fan_edges, AB);
+ p2tr_flip_set_add (fan_edges, CA);
+ p2tr_flip_set_add (fan_edges, BC);
+ p2tr_flip_set_add (fan_edges, AB);
}
return fan_edges;
p2tr_edge_unref (CY);
}
- p2tr_cdt_on_new_point (self, C);
p2tr_cdt_validate_unused (self);
return new_edges;
}
-/* This function implements "Lawson's algorithm", also known as "The
- * diagonal swapping algorithm". This algorithm takes a CDT, and a list
- * of triangles that were formed by the insertion of a new point into
- * the triangular mesh, and makes the triangulation a CDT once more. Its
- * logic is explained below:
- *
- * If a point is added to an existing triangular mesh then
- * circumcircles are formed for all new triangles formed. If any of
- * the neighbours lie inside the circumcircle of any triangle, then a
- * quadrilateral is formed using the triangle and its neighbour. The
- * diagonals of this quadrilateral are swapped to give a new
- * triangulation. This process is continued till there are no more
- * faulty triangles and no more swaps are required.
- *
- * The description above is slightly inaccurate, as it does not consider
- * the case were the diagonals can not be swapped since the
- * quadrilateral is concave (then swapping the diagonals would result in
- * a diagonal outside the quad, which is undesired). This code does also
- * handle that case.
- */
-
-#define CDT_180_EPS (1e-4)
-/**
- * Try to flip a given edge, If successfull, return the new edge (reffed!),
- * otherwise return NULL
- */
-static P2trEdge*
-p2tr_cdt_try_flip (P2trCDT *self,
- P2trEdge *to_flip)
-{
- /* C
- * / | \
- * B-----A to_flip: A->B
- * \ | / to_flip.Tri: ABC
- * D
- */
- P2trPoint *A, *B, *C, *D;
- P2trEdge *AB, *CA, *AD, *DB, *BC, *DC;
-
- g_assert (! to_flip->constrained && ! to_flip->delaunay);
-
- A = P2TR_EDGE_START (to_flip);
- B = to_flip->end;
- C = p2tr_triangle_get_opposite_point (to_flip->tri, to_flip, FALSE);
- D = p2tr_triangle_get_opposite_point (to_flip->mirror->tri, to_flip->mirror, FALSE);
-
- AB = to_flip;
-
- CA = p2tr_point_get_edge_to (C, A, FALSE);
- AD = p2tr_point_get_edge_to (A, D, FALSE);
- DB = p2tr_point_get_edge_to (D, B, FALSE);
- BC = p2tr_point_get_edge_to (B, C, FALSE);
-
- /* Check if the quadriliteral ADBC is concave (because if it is, we
- * can't flip the edge) */
- if (p2tr_triangle_circumcircle_contains_point (AB->tri, &D->c) != P2TR_INCIRCLE_IN)
- return NULL;
-
- p2tr_edge_remove (AB);
-
- DC = p2tr_mesh_new_edge (self->mesh, D, C, FALSE);
-
- p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh,
- CA, AD, DC));
-
- p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh,
- DB, BC, DC->mirror));
-
- return DC;
-}
-
-static void
-p2tr_cdt_add_edge (P2trHashSet *candidates,
- P2trEdge *candidate)
-{
- if (p2tr_hash_set_contains (candidates, candidate->mirror) ||
- p2tr_hash_set_contains (candidates, candidate))
- p2tr_edge_unref (candidate);
- else
- p2tr_hash_set_insert (candidates, candidate);
-}
-
-static void
-p2tr_cdt_flip_fix (P2trCDT *self,
- P2trHashSet *candidates)
-{
- P2trHashSetIter iter;
- while (TRUE)
- {
- P2trEdge* edge = NULL;
- p2tr_hash_set_iter_init (&iter, candidates);
- if (! p2tr_hash_set_iter_next (&iter, (gpointer*)&edge))
- break;
-
- p2tr_hash_set_remove (candidates, edge);
-
- if (! edge->constrained && ! p2tr_edge_is_removed (edge))
- {
- /* If the edge is not constrained, then it should be
- * a part of two triangles */
- P2trPoint *A = P2TR_EDGE_START(edge), *B = edge->end;
- P2trPoint *C1 = p2tr_triangle_get_opposite_point (edge->tri, edge, FALSE);
- P2trPoint *C2 = p2tr_triangle_get_opposite_point (edge->mirror->tri, edge->mirror, FALSE);
-
- P2trEdge *flipped = p2tr_cdt_try_flip (self, edge);
- if (flipped != NULL)
- {
- p2tr_cdt_add_edge (candidates, p2tr_point_get_edge_to (A, C1, TRUE));
- p2tr_cdt_add_edge (candidates, p2tr_point_get_edge_to (A, C2, TRUE));
- p2tr_cdt_add_edge (candidates, p2tr_point_get_edge_to (B, C1, TRUE));
- p2tr_cdt_add_edge (candidates, p2tr_point_get_edge_to (B, C2, TRUE));
- p2tr_edge_unref (flipped);
- }
- }
-
- p2tr_edge_unref (edge);
- }
-}
-
-/* Whenever a new point was inserted, it may disturb triangles
- * that are extremly skinny and therefor their circumscribing
- * circles are very large and will contain that point, even though they
- * may be very far from that point.
- * We have no choice but to check these and fix them if necessary
- */
-static void
-p2tr_cdt_on_new_point (P2trCDT *self,
- P2trPoint *pt)
-{
-#if FALSE
- GList *bad_tris = NULL;
- P2trTriangle *tri;
- P2trHashSetIter iter;
-
- p2tr_hash_set_iter_init (&iter, self->mesh->triangles);
- while (p2tr_hash_set_iter_next (&iter, (gpointer*)&tri))
- {
- if (p2tr_triangle_circumcircle_contains_point (tri, &pt->c)
- != P2TR_INCIRCLE_OUT)
- {
- bad_tris = g_list_prepend (bad_tris, tri);
- p2tr_triangle_ref (tri);
- }
- }
-
- p2tr_cdt_flip_fix (self, bad_tris);
- g_list_free (bad_tris);
-#endif
-}
-
}
P2trEdge*
-p2tr_edge_is_real (P2trVEdge *self)
+p2tr_vedge_is_real (P2trVEdge *self)
{
return p2tr_point_has_edge_to (self->start, self->end);
}
{
return p2tr_point_get_edge_to (self->start, self->end, TRUE);
}
+
+gboolean
+p2tr_vedge_try_get_and_unref (P2trVEdge *self,
+ P2trEdge **real)
+{
+ P2trEdge *real_one = p2tr_vedge_is_real (self);
+ if (real_one)
+ p2tr_edge_ref (real_one);
+ p2tr_vedge_unref (self);
+ return (*real = real_one) != NULL;
+}
P2trEdge* p2tr_vedge_is_real (P2trVEdge *self);
P2trEdge* p2tr_vedge_get (P2trVEdge *self);
+
+/**
+ * Try get a real edge from a virtual edge, and then
+ * unref the virtual edge. IF A MATCHING REAL EDGE IS
+ * RETURNED, IT MUST BE UNREFFED BY THE CALLER!
+ * @param self The virtual edge to test
+ * @param real The place to store the matching real edge
+ * @return TRUE if a real edge was returned, FALSE if no
+ * matching edge exists.
+ */
+gboolean p2tr_vedge_try_get_and_unref (P2trVEdge *self,
+ P2trEdge **real);
#endif