From: Barak Itkin Date: Sat, 30 Jun 2012 18:42:18 +0000 (+0300) Subject: Lots of clean up to the flip-fix code, including using virtual edges X-Git-Tag: p2tc-0.1.0~26 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=18407f76fcce09d6898443c118aacd1ce0e5a5cc;p=poly2tri-c Lots of clean up to the flip-fix code, including using virtual edges --- diff --git a/poly2tri-c/refine/Makefile.am b/poly2tri-c/refine/Makefile.am index c96f466..17ea508 100644 --- a/poly2tri-c/refine/Makefile.am +++ b/poly2tri-c/refine/Makefile.am @@ -1,6 +1,6 @@ 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 diff --git a/poly2tri-c/refine/cdt-flipfix.c b/poly2tri-c/refine/cdt-flipfix.c new file mode 100644 index 0000000..7811393 --- /dev/null +++ b/poly2tri-c/refine/cdt-flipfix.c @@ -0,0 +1,223 @@ +/* + * This file is a part of Poly2Tri-C + * (c) Barak Itkin + * 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 + +#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); +} + diff --git a/poly2tri-c/refine/cdt-flipfix.h b/poly2tri-c/refine/cdt-flipfix.h new file mode 100644 index 0000000..e7fa0e9 --- /dev/null +++ b/poly2tri-c/refine/cdt-flipfix.h @@ -0,0 +1,96 @@ +/* + * This file is a part of Poly2Tri-C + * (c) Barak Itkin + * 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 + +#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 diff --git a/poly2tri-c/refine/cdt.c b/poly2tri-c/refine/cdt.c index b53c3b1..f664c56 100644 --- a/poly2tri-c/refine/cdt.c +++ b/poly2tri-c/refine/cdt.c @@ -39,6 +39,7 @@ #include "cdt.h" #include "visibility.h" +#include "cdt-flipfix.h" static gboolean p2tr_cdt_visible_from_tri (P2trCDT *self, P2trTriangle *tri, @@ -51,18 +52,6 @@ static P2trHashSet* p2tr_cdt_triangulate_fan (P2trCDT *self, 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) { @@ -90,7 +79,8 @@ p2tr_cdt_new (P2tCDT *cdt) 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; @@ -142,7 +132,7 @@ p2tr_cdt_new (P2tCDT *cdt) /* 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); } } } @@ -167,7 +157,7 @@ p2tr_cdt_new (P2tCDT *cdt) /* 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); @@ -336,8 +326,6 @@ p2tr_cdt_insert_point (P2trCDT *self, /* 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); @@ -353,7 +341,7 @@ p2tr_cdt_insert_point_into_triangle (P2trCDT *self, 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; @@ -375,20 +363,20 @@ p2tr_cdt_insert_point_into_triangle (P2trCDT *self, 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); } /** @@ -397,12 +385,12 @@ p2tr_cdt_insert_point_into_triangle (P2trCDT *self, * 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 */ @@ -427,9 +415,9 @@ p2tr_cdt_triangulate_fan (P2trCDT *self, 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; @@ -494,159 +482,8 @@ p2tr_cdt_split_edge (P2trCDT *self, 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 -} - diff --git a/poly2tri-c/refine/vedge.c b/poly2tri-c/refine/vedge.c index f37e16d..8afbffe 100644 --- a/poly2tri-c/refine/vedge.c +++ b/poly2tri-c/refine/vedge.c @@ -85,7 +85,7 @@ p2tr_vedge_unref (P2trVEdge *self) } P2trEdge* -p2tr_edge_is_real (P2trVEdge *self) +p2tr_vedge_is_real (P2trVEdge *self) { return p2tr_point_has_edge_to (self->start, self->end); } @@ -109,3 +109,14 @@ p2tr_vedge_get (P2trVEdge *self) { 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; +} diff --git a/poly2tri-c/refine/vedge.h b/poly2tri-c/refine/vedge.h index 1aa8f8f..1e3ac05 100644 --- a/poly2tri-c/refine/vedge.h +++ b/poly2tri-c/refine/vedge.h @@ -69,4 +69,16 @@ P2trMesh* p2tr_vedge_get_mesh (P2trVEdge *self); 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