[gegl/soc-2011-seamless-clone: 38/49] Add a local copy of poly2tri-c for use by seamless-cloning as a fallback
- From: Barak Itkin <barakitkin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/soc-2011-seamless-clone: 38/49] Add a local copy of poly2tri-c for use by seamless-cloning as a fallback
- Date: Sat, 29 Sep 2012 20:30:03 +0000 (UTC)
commit e4190bc36d91e1896cace2214c562ed186bbff66
Author: Barak Itkin <lightningismyname gmail com>
Date: Sat Aug 11 21:27:33 2012 +0300
Add a local copy of poly2tri-c for use by seamless-cloning as a fallback
configure.ac | 25 +-
libs/Makefile.am | 2 +-
libs/poly2tri-c/.gitignore | 6 +
libs/poly2tri-c/COPYING | 40 +
libs/poly2tri-c/LICENSE-Poly2Tri-C.txt | 30 +
libs/poly2tri-c/LICENSE-Poly2Tri.txt | 31 +
libs/poly2tri-c/Makefile.am | 9 +
libs/poly2tri-c/README | 13 +
libs/poly2tri-c/poly2tri-c/Makefile.am | 4 +
libs/poly2tri-c/poly2tri-c/p2t/Makefile.am | 10 +
libs/poly2tri-c/poly2tri-c/p2t/common/Makefile.am | 5 +
libs/poly2tri-c/poly2tri-c/p2t/common/cutils.h | 67 ++
.../poly2tri-c/p2t/common/poly2tri-private.h | 62 ++
libs/poly2tri-c/poly2tri-c/p2t/common/shapes.c | 677 +++++++++++++
libs/poly2tri-c/poly2tri-c/p2t/common/shapes.h | 262 +++++
libs/poly2tri-c/poly2tri-c/p2t/common/utils.c | 114 +++
libs/poly2tri-c/poly2tri-c/p2t/common/utils.h | 67 ++
libs/poly2tri-c/poly2tri-c/p2t/poly2tri.h | 43 +
libs/poly2tri-c/poly2tri-c/p2t/sweep/Makefile.am | 5 +
.../poly2tri-c/p2t/sweep/advancing_front.c | 229 +++++
.../poly2tri-c/p2t/sweep/advancing_front.h | 92 ++
libs/poly2tri-c/poly2tri-c/p2t/sweep/cdt.c | 95 ++
libs/poly2tri-c/poly2tri-c/p2t/sweep/cdt.h | 105 ++
libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep.c | 1024 ++++++++++++++++++++
libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep.h | 282 ++++++
.../poly2tri-c/p2t/sweep/sweep_context.c | 319 ++++++
.../poly2tri-c/p2t/sweep/sweep_context.h | 137 +++
libs/poly2tri-c/poly2tri-c/refine/Makefile.am | 6 +
libs/poly2tri-c/poly2tri-c/refine/bounded-line.c | 84 ++
libs/poly2tri-c/poly2tri-c/refine/bounded-line.h | 58 ++
libs/poly2tri-c/poly2tri-c/refine/cdt-flipfix.c | 159 +++
libs/poly2tri-c/poly2tri-c/refine/cdt-flipfix.h | 49 +
libs/poly2tri-c/poly2tri-c/refine/cdt.c | 491 ++++++++++
libs/poly2tri-c/poly2tri-c/refine/cdt.h | 127 +++
libs/poly2tri-c/poly2tri-c/refine/circle.c | 47 +
libs/poly2tri-c/poly2tri-c/refine/circle.h | 46 +
libs/poly2tri-c/poly2tri-c/refine/cluster.c | 139 +++
libs/poly2tri-c/poly2tri-c/refine/cluster.h | 55 ++
.../poly2tri-c/refine/delaunay-terminator.c | 529 ++++++++++
.../poly2tri-c/refine/delaunay-terminator.h | 71 ++
libs/poly2tri-c/poly2tri-c/refine/edge.c | 247 +++++
libs/poly2tri-c/poly2tri-c/refine/edge.h | 104 ++
libs/poly2tri-c/poly2tri-c/refine/line.c | 102 ++
libs/poly2tri-c/poly2tri-c/refine/line.h | 66 ++
libs/poly2tri-c/poly2tri-c/refine/mesh-action.c | 228 +++++
libs/poly2tri-c/poly2tri-c/refine/mesh-action.h | 170 ++++
libs/poly2tri-c/poly2tri-c/refine/mesh.c | 406 ++++++++
libs/poly2tri-c/poly2tri-c/refine/mesh.h | 361 +++++++
libs/poly2tri-c/poly2tri-c/refine/point.c | 227 +++++
libs/poly2tri-c/poly2tri-c/refine/point.h | 99 ++
libs/poly2tri-c/poly2tri-c/refine/pslg.c | 105 ++
libs/poly2tri-c/poly2tri-c/refine/pslg.h | 115 +++
libs/poly2tri-c/poly2tri-c/refine/refine.h | 59 ++
libs/poly2tri-c/poly2tri-c/refine/refiner.c | 70 ++
libs/poly2tri-c/poly2tri-c/refine/refiner.h | 61 ++
libs/poly2tri-c/poly2tri-c/refine/rmath.c | 301 ++++++
libs/poly2tri-c/poly2tri-c/refine/rmath.h | 132 +++
libs/poly2tri-c/poly2tri-c/refine/triangle.c | 313 ++++++
libs/poly2tri-c/poly2tri-c/refine/triangle.h | 94 ++
libs/poly2tri-c/poly2tri-c/refine/triangulation.h | 49 +
libs/poly2tri-c/poly2tri-c/refine/utils.c | 51 +
libs/poly2tri-c/poly2tri-c/refine/utils.h | 88 ++
libs/poly2tri-c/poly2tri-c/refine/vector2.c | 84 ++
libs/poly2tri-c/poly2tri-c/refine/vector2.h | 101 ++
libs/poly2tri-c/poly2tri-c/refine/vedge.c | 228 +++++
libs/poly2tri-c/poly2tri-c/refine/vedge.h | 143 +++
libs/poly2tri-c/poly2tri-c/refine/visibility.c | 438 +++++++++
libs/poly2tri-c/poly2tri-c/refine/visibility.h | 46 +
libs/poly2tri-c/poly2tri-c/refine/vtriangle.c | 145 +++
libs/poly2tri-c/poly2tri-c/refine/vtriangle.h | 70 ++
libs/poly2tri-c/poly2tri-c/render/Makefile.am | 6 +
libs/poly2tri-c/poly2tri-c/render/mesh-render.c | 273 ++++++
libs/poly2tri-c/poly2tri-c/render/mesh-render.h | 175 ++++
libs/poly2tri-c/poly2tri-c/render/svg-plot.c | 204 ++++
libs/poly2tri-c/poly2tri-c/render/svg-plot.h | 75 ++
operations/common/seamless-clone/Makefile.am | 2 -
76 files changed, 11044 insertions(+), 10 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 527463f..458b657 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1030,20 +1030,24 @@ AC_SUBST(UMFPACK_LIBS)
# Check for poly2tri-c
######################
-AC_ARG_WITH(p2tc, AS_HELP_STRING([--without-p2tc], [build without poly2tri-c support]))
-
have_p2tc="no"
-if test "x$with_p2tc" != "xno"; then
- PKG_CHECK_MODULES(P2TC, poly2tri-c >= poly2tri-c_required_version,
- have_p2tc="yes",
- have_p2tc="no (poly2tri-c not found)")
-fi
+PKG_CHECK_MODULES(P2TC, poly2tri-c >= poly2tri-c_required_version,
+ have_p2tc="yes",
+ have_p2tc="yes (installed poly2tri-c not found, using local version)")
AM_CONDITIONAL(HAVE_P2TC, test "$have_p2tc" = "yes")
AC_SUBST(P2TC_CFLAGS)
AC_SUBST(P2TC_LIBS)
+# If no poly2tri-c version is installed, we should use the local version
+# we have cached in the libs directory
+if test "x$have_p2tc" != "xyes"; then
+ AC_SUBST(P2TC_SRC_DIR, "`cd $srcdir; pwd`/libs/poly2tri-c")
+ AC_SUBST(P2TC_CFLAGS, "-I\"$P2TC_SRC_DIR\"")
+ AC_SUBST(P2TC_LIBS, "-L\"$P2TC_SRC_DIR/poly2tri-c\" -lpoly2tri-c")
+fi
+
#######################
# Check for other items
#######################
@@ -1109,6 +1113,13 @@ gegl/property-types/Makefile
gegl/opencl/Makefile
libs/Makefile
libs/rgbe/Makefile
+libs/poly2tri-c/Makefile
+libs/poly2tri-c/poly2tri-c/Makefile
+libs/poly2tri-c/poly2tri-c/render/Makefile
+libs/poly2tri-c/poly2tri-c/p2t/sweep/Makefile
+libs/poly2tri-c/poly2tri-c/p2t/common/Makefile
+libs/poly2tri-c/poly2tri-c/p2t/Makefile
+libs/poly2tri-c/poly2tri-c/refine/Makefile
operations/Makefile
operations/core/Makefile
operations/common/Makefile
diff --git a/libs/Makefile.am b/libs/Makefile.am
index 933933d..176d347 100644
--- a/libs/Makefile.am
+++ b/libs/Makefile.am
@@ -1 +1 @@
-SUBDIRS = rgbe
+SUBDIRS = rgbe poly2tri-c
diff --git a/libs/poly2tri-c/.gitignore b/libs/poly2tri-c/.gitignore
new file mode 100644
index 0000000..612c816
--- /dev/null
+++ b/libs/poly2tri-c/.gitignore
@@ -0,0 +1,6 @@
+*.la
+*.lo
+*Makefile
+*Makefile.in
+*.deps/
+*.libs/
diff --git a/libs/poly2tri-c/COPYING b/libs/poly2tri-c/COPYING
new file mode 100644
index 0000000..11f143f
--- /dev/null
+++ b/libs/poly2tri-c/COPYING
@@ -0,0 +1,40 @@
+The Poly2Tri-C is a three-part library, where all parts are licensed
+under the same license - The BSD 3-Clause License (also known as "New
+BSD License" or "Modified BSD License"):
+
+ 1. Constrained Delaunay Triangulation - Based on the code of Poly2Tri
+ (Poly2Tri is licensed under the same license)
+ 2. Delaunay Refinement - New code implemented in this library
+ 3. Mesh Rendering - New code implemented in this library
+
+The first part of the library is a port of the Poly2Tri library from C++
+to C (with GLib). This port can be found inside the poly2tri-c/p2t
+directory of this source code distribution.
+
+ Poly2Tri - A 2D constrained Delaunay triangulation library
+ Homepage: http://code.google.com/p/poly2tri/
+ Code License File: LICENSE-Poly2Tri.txt
+
+The second part of the library is an implementaiton of a Delaunay
+Refinement algorithm named "The Terminator" which appears in a paper
+written by Jonathan Richard Shewchuk.
+The implementation of the algorithm in C was done by Barak Itkin, and it
+can be found inside the poly2tri-c/refine directory of this source code
+distribution.
+
+ Algorithm Author:
+ Jonathan Richard Shewchuk
+ http://www.cs.berkeley.edu/~jrs/
+
+ Algorithm Paper:
+ Delaunay Refinement Algorithms for Triangular Mesh Generation
+ http://www.cs.berkeley.edu/~jrs/papers/2dj.pdf
+
+ Code License File: LICENSE-Poly2Tri-C.txt
+
+Finally, the third part of the library contains various techniques to
+render mesh objects as raster/vector images. This part is 'original' and
+is not based on any other reference. This code can be found inside the
+poly2tri-c/render directory of this source code distribution.
+
+ Code License File: LICENSE-Poly2Tri-C.txt
diff --git a/libs/poly2tri-c/LICENSE-Poly2Tri-C.txt b/libs/poly2tri-c/LICENSE-Poly2Tri-C.txt
new file mode 100644
index 0000000..097ab24
--- /dev/null
+++ b/libs/poly2tri-c/LICENSE-Poly2Tri-C.txt
@@ -0,0 +1,30 @@
+Poly2Tri-C Copyright (c) 2011-2012, 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-C 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.
+
diff --git a/libs/poly2tri-c/LICENSE-Poly2Tri.txt b/libs/poly2tri-c/LICENSE-Poly2Tri.txt
new file mode 100644
index 0000000..79fa687
--- /dev/null
+++ b/libs/poly2tri-c/LICENSE-Poly2Tri.txt
@@ -0,0 +1,31 @@
+
+Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+http://code.google.com/p/poly2tri/
+
+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.
+
diff --git a/libs/poly2tri-c/Makefile.am b/libs/poly2tri-c/Makefile.am
new file mode 100644
index 0000000..75990ee
--- /dev/null
+++ b/libs/poly2tri-c/Makefile.am
@@ -0,0 +1,9 @@
+if HAVE_P2TC
+ SUBDIRS =
+else
+ SUBDIRS = poly2tri-c
+ AM_CFLAGS = -I $(CURDIR) $(GLIB_CFLAGS)
+ export AM_CFLAGS
+ AM_LIBS = $(GLIB_LIBS)
+ export AM_LIBS
+endif
diff --git a/libs/poly2tri-c/README b/libs/poly2tri-c/README
new file mode 100644
index 0000000..3f39b14
--- /dev/null
+++ b/libs/poly2tri-c/README
@@ -0,0 +1,13 @@
+========================================================================
+==== Poly2Tri-C: A library for generating, refining and rendering ====
+==== 2-Dimensional Constrained Delaunay Triangulations ====
+========================================================================
+
+This is a minimal version of the Poly2Tri-C library, required to compile
+the seamless cloning operation. For more information, and in order to
+get the full library, see http://code.google.com/p/poly2tri-c
+
+Poly2Tri-C Version info:
+
+ CURRENT REVISION: b27c5b79df2ffa4e2cb37f9e5536831f16afb11b
+ CACHED ON: August 11th, 2012
diff --git a/libs/poly2tri-c/poly2tri-c/Makefile.am b/libs/poly2tri-c/poly2tri-c/Makefile.am
new file mode 100644
index 0000000..7c67fed
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/Makefile.am
@@ -0,0 +1,4 @@
+SUBDIRS = p2t refine render
+noinst_LTLIBRARIES = libpoly2tri-c.la
+libpoly2tri_c_la_LIBADD = p2t/libp2tc.la refine/libp2tc-refine.la render/libp2tc-render.la
+libpoly2tri_c_la_SOURCES =
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/Makefile.am b/libs/poly2tri-c/poly2tri-c/p2t/Makefile.am
new file mode 100644
index 0000000..b14155c
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/Makefile.am
@@ -0,0 +1,10 @@
+SUBDIRS = sweep common
+
+noinst_LTLIBRARIES = libp2tc.la
+
+P2TC_P2T_publicdir = $(P2TC_publicdir)/p2t
+export P2TC_P2T_publicdir
+P2TC_P2T_public_HEADERS = poly2tri.h
+
+libp2tc_la_LIBADD = common/libp2tc-common.la sweep/libp2tc-sweep.la
+libp2tc_la_SOURCES =
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/common/Makefile.am b/libs/poly2tri-c/poly2tri-c/p2t/common/Makefile.am
new file mode 100644
index 0000000..8da3514
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/common/Makefile.am
@@ -0,0 +1,5 @@
+noinst_LTLIBRARIES = libp2tc-common.la
+libp2tc_common_la_SOURCES = cutils.h poly2tri-private.h shapes.c shapes.h utils.c utils.h
+
+P2TC_P2T_COMMON_publicdir = $(P2TC_P2T_publicdir)/common
+P2TC_P2T_COMMON_public_HEADERS = cutils.h poly2tri-private.h shapes.h utils.h
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/common/cutils.h b/libs/poly2tri-c/poly2tri-c/p2t/common/cutils.h
new file mode 100644
index 0000000..596078e
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/common/cutils.h
@@ -0,0 +1,67 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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_P2T_CUTILS_H__
+#define __P2TC_P2T_CUTILS_H__
+
+#include <glib.h>
+#include "poly2tri-private.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define DEBUG FALSE
+
+ typedef GPtrArray* P2tEdgePtrArray;
+#define edge_index(array,index_) ((P2tEdge*)g_ptr_array_index(array,index_))
+ typedef GPtrArray* P2tPointPtrArray;
+#define point_index(array,index_) ((P2tPoint*)g_ptr_array_index(array,index_))
+ typedef GPtrArray* P2tTrianglePtrArray;
+#define triangle_index(array,index_) ((P2tTriangle*)g_ptr_array_index(array,index_))
+ typedef GPtrArray* P2tNodePtrArray;
+#define node_index(array,index_) ((P2tNode*)g_ptr_array_index(array,index_))
+ typedef GList* P2tTrianglePtrList;
+#define triangle_val(list) ((P2tTriangle*)((list)->data))
+
+#define g_ptr_array_index_cyclic(array,index_) g_ptr_array_index(array,(index_)%((array)->len))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CUTILS_H */
+
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/common/poly2tri-private.h b/libs/poly2tri-c/poly2tri-c/p2t/common/poly2tri-private.h
new file mode 100644
index 0000000..0be3193
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/common/poly2tri-private.h
@@ -0,0 +1,62 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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_P2T_POLY2TRI_PRIVATE_H__
+#define __P2TC_P2T_POLY2TRI_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct _P2tNode P2tNode;
+typedef struct AdvancingFront_ P2tAdvancingFront;
+typedef struct CDT_ P2tCDT;
+typedef struct _P2tEdge P2tEdge;
+typedef struct _P2tPoint P2tPoint;
+typedef struct _P2tTriangle P2tTriangle;
+typedef struct SweepContext_ P2tSweepContext;
+typedef struct Sweep_ P2tSweep;
+
+typedef struct P2tSweepContextBasin_ P2tSweepContextBasin;
+typedef struct P2tSweepContextEdgeEvent_ P2tSweepContextEdgeEvent;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLY2TRI_PRIVATE_H */
+
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/common/shapes.c b/libs/poly2tri-c/poly2tri-c/p2t/common/shapes.c
new file mode 100644
index 0000000..62fec89
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/common/shapes.c
@@ -0,0 +1,677 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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 "shapes.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+/** Default constructor does nothing (for performance). */
+
+void
+p2t_point_init (P2tPoint* THIS)
+{
+ THIS->x = 0;
+ THIS->y = 0;
+ THIS->edge_list = g_ptr_array_new ();
+}
+
+P2tPoint*
+p2t_point_new ()
+{
+ P2tPoint* THIS = g_slice_new (P2tPoint);
+ p2t_point_init (THIS);
+ return THIS;
+}
+
+/** Construct using coordinates. */
+
+void
+p2t_point_init_dd (P2tPoint* THIS, double x, double y)
+{
+ THIS->x = x;
+ THIS->y = y;
+ THIS->edge_list = g_ptr_array_new ();
+}
+
+P2tPoint*
+p2t_point_new_dd (double x, double y)
+{
+ P2tPoint* THIS = g_slice_new (P2tPoint);
+ p2t_point_init_dd (THIS, x, y);
+ return THIS;
+}
+
+void
+p2t_point_destroy (P2tPoint* THIS)
+{
+ g_ptr_array_free (THIS->edge_list, TRUE);
+}
+
+void
+p2t_point_free (P2tPoint* THIS)
+{
+ p2t_point_destroy (THIS);
+ g_slice_free (P2tPoint, THIS);
+}
+
+/** Constructor */
+
+void
+p2t_edge_init (P2tEdge* THIS, P2tPoint* p1, P2tPoint* p2)
+{
+ THIS->p = p1;
+ THIS->q = p2;
+ if (p1->y > p2->y)
+ {
+ THIS->q = p1;
+ THIS->p = p2;
+ }
+ else if (p1->y == p2->y)
+ {
+ if (p1->x > p2->x)
+ {
+ THIS->q = p1;
+ THIS->p = p2;
+ }
+ else if (p1->x == p2->x)
+ {
+ /* Repeat points */
+ assert (FALSE);
+ }
+ }
+
+ g_ptr_array_add (THIS->q->edge_list, THIS);
+}
+
+P2tEdge*
+p2t_edge_new (P2tPoint* p1, P2tPoint* p2)
+{
+ P2tEdge* THIS = g_slice_new (P2tEdge);
+ p2t_edge_init (THIS, p1, p2);
+ return THIS;
+}
+
+void
+p2t_edge_destroy (P2tEdge* THIS) { }
+
+void
+p2t_edge_free (P2tEdge* THIS)
+{
+ p2t_edge_destroy (THIS);
+ g_slice_free (P2tEdge, THIS);
+}
+
+P2tTriangle*
+p2t_triangle_new (P2tPoint* a, P2tPoint* b, P2tPoint* c)
+{
+ P2tTriangle *tr = g_new (P2tTriangle, 1);
+ p2t_triangle_init (tr, a, b, c);
+ return tr;
+}
+
+void
+p2t_triangle_init (P2tTriangle* THIS, P2tPoint* a, P2tPoint* b, P2tPoint* c)
+{
+ THIS->points_[0] = a;
+ THIS->points_[1] = b;
+ THIS->points_[2] = c;
+ THIS->neighbors_[0] = NULL;
+ THIS->neighbors_[1] = NULL;
+ THIS->neighbors_[2] = NULL;
+ THIS->constrained_edge[0] = THIS->constrained_edge[1] = THIS->constrained_edge[2] = FALSE;
+ THIS->delaunay_edge[0] = THIS->delaunay_edge[1] = THIS->delaunay_edge[2] = FALSE;
+ THIS->interior_ = FALSE;
+
+}
+/* Update neighbor pointers */
+
+void
+p2t_triangle_mark_neighbor_pt_pt_tr (P2tTriangle* THIS, P2tPoint* p1, P2tPoint* p2, P2tTriangle* t)
+{
+ if ((p1 == THIS->points_[2] && p2 == THIS->points_[1]) || (p1 == THIS->points_[1] && p2 == THIS->points_[2]))
+ THIS->neighbors_[0] = t;
+ else if ((p1 == THIS->points_[0] && p2 == THIS->points_[2]) || (p1 == THIS->points_[2] && p2 == THIS->points_[0]))
+ THIS->neighbors_[1] = t;
+ else if ((p1 == THIS->points_[0] && p2 == THIS->points_[1]) || (p1 == THIS->points_[1] && p2 == THIS->points_[0]))
+ THIS->neighbors_[2] = t;
+ else
+ assert (0);
+}
+
+/* Exhaustive search to update neighbor pointers */
+
+void
+p2t_triangle_mark_neighbor_tr (P2tTriangle* THIS, P2tTriangle *t)
+{
+ if (p2t_triangle_contains_pt_pt (t, THIS->points_[1], THIS->points_[2]))
+ {
+ THIS->neighbors_[0] = t;
+ p2t_triangle_mark_neighbor_pt_pt_tr (t, THIS->points_[1], THIS->points_[2], THIS);
+ }
+ else if (p2t_triangle_contains_pt_pt (t, THIS->points_[0], THIS->points_[2]))
+ {
+ THIS->neighbors_[1] = t;
+ p2t_triangle_mark_neighbor_pt_pt_tr (t, THIS->points_[0], THIS->points_[2], THIS);
+ }
+ else if (p2t_triangle_contains_pt_pt (t, THIS->points_[0], THIS->points_[1]))
+ {
+ THIS->neighbors_[2] = t;
+ p2t_triangle_mark_neighbor_pt_pt_tr (t, THIS->points_[0], THIS->points_[1], THIS);
+ }
+}
+
+/**
+ * Clears all references to all other triangles and points
+ */
+void
+p2t_triangle_clear (P2tTriangle* THIS)
+{
+ int i;
+ P2tTriangle *t;
+ for (i = 0; i < 3; i++)
+ {
+ t = THIS->neighbors_[i];
+ if (t != NULL)
+ {
+ p2t_triangle_clear_neighbor_tr (t, THIS);
+ }
+ }
+ p2t_triangle_clear_neighbors (THIS);
+ THIS->points_[0] = THIS->points_[1] = THIS->points_[2] = NULL;
+}
+
+void
+p2t_triangle_clear_neighbor_tr (P2tTriangle* THIS, P2tTriangle *triangle)
+{
+ if (THIS->neighbors_[0] == triangle)
+ {
+ THIS->neighbors_[0] = NULL;
+ }
+ else if (THIS->neighbors_[1] == triangle)
+ {
+ THIS->neighbors_[1] = NULL;
+ }
+ else
+ {
+ THIS->neighbors_[2] = NULL;
+ }
+}
+
+void
+p2t_triangle_clear_neighbors (P2tTriangle* THIS)
+{
+ THIS->neighbors_[0] = NULL;
+ THIS->neighbors_[1] = NULL;
+ THIS->neighbors_[2] = NULL;
+}
+
+void
+p2t_triangle_clear_delunay_edges (P2tTriangle* THIS)
+{
+ THIS->delaunay_edge[0] = THIS->delaunay_edge[1] = THIS->delaunay_edge[2] = FALSE;
+}
+
+P2tPoint*
+p2t_triangle_opposite_point (P2tTriangle* THIS, P2tTriangle* t, P2tPoint* p)
+{
+ P2tPoint *cw = p2t_triangle_point_cw (t, p);
+ /*double x = cw->x;
+ double y = cw->y;
+ x = p->x;
+ y = p->y;
+ P2tPoint* ham = */p2t_triangle_point_cw (THIS, cw);
+ return p2t_triangle_point_cw (THIS, cw);
+}
+
+/* Legalized triangle by rotating clockwise around point(0) */
+
+void
+p2t_triangle_legalize_pt (P2tTriangle* THIS, P2tPoint *point)
+{
+ THIS->points_[1] = THIS->points_[0];
+ THIS->points_[0] = THIS->points_[2];
+ THIS->points_[2] = point;
+}
+
+/* Legalize triagnle by rotating clockwise around oPoint */
+
+void
+p2t_triangle_legalize_pt_pt (P2tTriangle* THIS, P2tPoint *opoint, P2tPoint *npoint)
+{
+ if (opoint == THIS->points_[0])
+ {
+ THIS->points_[1] = THIS->points_[0];
+ THIS->points_[0] = THIS->points_[2];
+ THIS->points_[2] = npoint;
+ }
+ else if (opoint == THIS->points_[1])
+ {
+ THIS->points_[2] = THIS->points_[1];
+ THIS->points_[1] = THIS->points_[0];
+ THIS->points_[0] = npoint;
+ }
+ else if (opoint == THIS->points_[2])
+ {
+ THIS->points_[0] = THIS->points_[2];
+ THIS->points_[2] = THIS->points_[1];
+ THIS->points_[1] = npoint;
+ }
+ else
+ {
+ assert (0);
+ }
+}
+
+int
+p2t_triangle_index (P2tTriangle* THIS, const P2tPoint* p)
+{
+ if (p == THIS->points_[0])
+ {
+ return 0;
+ }
+ else if (p == THIS->points_[1])
+ {
+ return 1;
+ }
+ else if (p == THIS->points_[2])
+ {
+ return 2;
+ }
+ assert (0);
+}
+
+int
+p2t_triangle_edge_index (P2tTriangle* THIS, const P2tPoint* p1, const P2tPoint* p2)
+{
+ if (THIS->points_[0] == p1)
+ {
+ if (THIS->points_[1] == p2)
+ {
+ return 2;
+ }
+ else if (THIS->points_[2] == p2)
+ {
+ return 1;
+ }
+ }
+ else if (THIS->points_[1] == p1)
+ {
+ if (THIS->points_[2] == p2)
+ {
+ return 0;
+ }
+ else if (THIS->points_[0] == p2)
+ {
+ return 2;
+ }
+ }
+ else if (THIS->points_[2] == p1)
+ {
+ if (THIS->points_[0] == p2)
+ {
+ return 1;
+ }
+ else if (THIS->points_[1] == p2)
+ {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+void
+p2t_triangle_mark_constrained_edge_i (P2tTriangle* THIS, const int index)
+{
+ THIS->constrained_edge[index] = TRUE;
+}
+
+void
+p2t_triangle_mark_constrained_edge_ed (P2tTriangle* THIS, P2tEdge* edge)
+{
+ p2t_triangle_mark_constrained_edge_pt_pt (THIS, edge->p, edge->q);
+}
+
+/* Mark edge as constrained */
+
+void
+p2t_triangle_mark_constrained_edge_pt_pt (P2tTriangle* THIS, P2tPoint* p, P2tPoint* q)
+{
+ if ((q == THIS->points_[0] && p == THIS->points_[1]) || (q == THIS->points_[1] && p == THIS->points_[0]))
+ {
+ THIS->constrained_edge[2] = TRUE;
+ }
+ else if ((q == THIS->points_[0] && p == THIS->points_[2]) || (q == THIS->points_[2] && p == THIS->points_[0]))
+ {
+ THIS->constrained_edge[1] = TRUE;
+ }
+ else if ((q == THIS->points_[1] && p == THIS->points_[2]) || (q == THIS->points_[2] && p == THIS->points_[1]))
+ {
+ THIS->constrained_edge[0] = TRUE;
+ }
+}
+
+/* The point counter-clockwise to given point */
+
+P2tPoint*
+p2t_triangle_point_cw (P2tTriangle* THIS, P2tPoint* point)
+{
+ if (point == THIS->points_[0])
+ {
+ return THIS->points_[2];
+ }
+ else if (point == THIS->points_[1])
+ {
+ return THIS->points_[0];
+ }
+ else if (point == THIS->points_[2])
+ {
+ return THIS->points_[1];
+ }
+ assert (0);
+}
+
+/* The point counter-clockwise to given point */
+
+P2tPoint*
+p2t_triangle_point_ccw (P2tTriangle* THIS, P2tPoint* point)
+{
+ if (point == THIS->points_[0])
+ {
+ return THIS->points_[1];
+ }
+ else if (point == THIS->points_[1])
+ {
+ return THIS->points_[2];
+ }
+ else if (point == THIS->points_[2])
+ {
+ return THIS->points_[0];
+ }
+ assert (0);
+}
+
+/* The neighbor clockwise to given point */
+
+P2tTriangle*
+p2t_triangle_neighbor_cw (P2tTriangle* THIS, P2tPoint* point)
+{
+ if (point == THIS->points_[0])
+ {
+ return THIS->neighbors_[1];
+ }
+ else if (point == THIS->points_[1])
+ {
+ return THIS->neighbors_[2];
+ }
+ return THIS->neighbors_[0];
+}
+
+/* The neighbor counter-clockwise to given point */
+
+P2tTriangle*
+p2t_triangle_neighbor_ccw (P2tTriangle* THIS, P2tPoint* point)
+{
+ if (point == THIS->points_[0])
+ {
+ return THIS->neighbors_[2];
+ }
+ else if (point == THIS->points_[1])
+ {
+ return THIS->neighbors_[0];
+ }
+ return THIS->neighbors_[1];
+}
+
+gboolean
+p2t_triangle_get_constrained_edge_ccw (P2tTriangle* THIS, P2tPoint* p)
+{
+ if (p == THIS->points_[0])
+ {
+ return THIS->constrained_edge[2];
+ }
+ else if (p == THIS->points_[1])
+ {
+ return THIS->constrained_edge[0];
+ }
+ return THIS->constrained_edge[1];
+}
+
+gboolean
+p2t_triangle_get_constrained_edge_cw (P2tTriangle* THIS, P2tPoint* p)
+{
+ if (p == THIS->points_[0])
+ {
+ return THIS->constrained_edge[1];
+ }
+ else if (p == THIS->points_[1])
+ {
+ return THIS->constrained_edge[2];
+ }
+ return THIS->constrained_edge[0];
+}
+
+void
+p2t_triangle_set_constrained_edge_ccw (P2tTriangle* THIS, P2tPoint* p, gboolean ce)
+{
+ if (p == THIS->points_[0])
+ {
+ THIS->constrained_edge[2] = ce;
+ }
+ else if (p == THIS->points_[1])
+ {
+ THIS->constrained_edge[0] = ce;
+ }
+ else
+ {
+ THIS->constrained_edge[1] = ce;
+ }
+}
+
+void
+p2t_triangle_set_constrained_edge_cw (P2tTriangle* THIS, P2tPoint* p, gboolean ce)
+{
+ if (p == THIS->points_[0])
+ {
+ THIS->constrained_edge[1] = ce;
+ }
+ else if (p == THIS->points_[1])
+ {
+ THIS->constrained_edge[2] = ce;
+ }
+ else
+ {
+ THIS->constrained_edge[0] = ce;
+ }
+}
+
+gboolean
+p2t_triangle_get_delunay_edge_ccw (P2tTriangle* THIS, P2tPoint* p)
+{
+ if (p == THIS->points_[0])
+ {
+ return THIS->delaunay_edge[2];
+ }
+ else if (p == THIS->points_[1])
+ {
+ return THIS->delaunay_edge[0];
+ }
+ return THIS->delaunay_edge[1];
+}
+
+gboolean
+p2t_triangle_get_delunay_edge_cw (P2tTriangle* THIS, P2tPoint* p)
+{
+ if (p == THIS->points_[0])
+ {
+ return THIS->delaunay_edge[1];
+ }
+ else if (p == THIS->points_[1])
+ {
+ return THIS->delaunay_edge[2];
+ }
+ return THIS->delaunay_edge[0];
+}
+
+void
+p2t_triangle_set_delunay_edge_ccw (P2tTriangle* THIS, P2tPoint* p, gboolean e)
+{
+ if (p == THIS->points_[0])
+ {
+ THIS->delaunay_edge[2] = e;
+ }
+ else if (p == THIS->points_[1])
+ {
+ THIS->delaunay_edge[0] = e;
+ }
+ else
+ {
+ THIS->delaunay_edge[1] = e;
+ }
+}
+
+void
+p2t_triangle_set_delunay_edge_cw (P2tTriangle* THIS, P2tPoint* p, gboolean e)
+{
+ if (p == THIS->points_[0])
+ {
+ THIS->delaunay_edge[1] = e;
+ }
+ else if (p == THIS->points_[1])
+ {
+ THIS->delaunay_edge[2] = e;
+ }
+ else
+ {
+ THIS->delaunay_edge[0] = e;
+ }
+}
+
+/* The neighbor across to given point */
+
+P2tTriangle*
+p2t_triangle_neighbor_across (P2tTriangle* THIS, P2tPoint* opoint)
+{
+ if (opoint == THIS->points_[0])
+ {
+ return THIS->neighbors_[0];
+ }
+ else if (opoint == THIS->points_[1])
+ {
+ return THIS->neighbors_[1];
+ }
+ return THIS->neighbors_[2];
+}
+
+void
+p2t_triangle_debug_print (P2tTriangle* THIS)
+{
+ printf ("%f,%f ", THIS->points_[0]->x, THIS->points_[0]->y);
+ printf ("%f,%f ", THIS->points_[1]->x, THIS->points_[1]->y);
+ printf ("%f,%f\n", THIS->points_[2]->x, THIS->points_[2]->y);
+}
+
+/* WARNING! the function for sorting a g_ptr_array expects to recieve
+ * pointers to the pointers (double indirection)! */
+
+gint
+p2t_point_cmp (gconstpointer a, gconstpointer b)
+{
+ P2tPoint *ap = *((P2tPoint**) a), *bp = *((P2tPoint**) b);
+ if (ap->y < bp->y)
+ {
+ return -1;
+ }
+ else if (ap->y == bp->y)
+ {
+ /* Make sure q is point with greater x value */
+ if (ap->x < bp->x)
+ {
+ return -1;
+ }
+ else if (ap->x == bp->x)
+ return 0;
+ }
+ return 1;
+}
+
+/* gboolean operator == (const Point& a, const Point& b) */
+
+gboolean
+p2t_point_equals (const P2tPoint* a, const P2tPoint* b)
+{
+ return a->x == b->x && a->y == b->y;
+}
+
+P2tPoint*
+p2t_triangle_get_point (P2tTriangle* THIS, const int index)
+{
+ return THIS->points_[index];
+}
+
+P2tTriangle*
+p2t_triangle_get_neighbor (P2tTriangle* THIS, const int index)
+{
+ return THIS->neighbors_[index];
+}
+
+gboolean
+p2t_triangle_contains_pt (P2tTriangle* THIS, P2tPoint* p)
+{
+ return p == THIS->points_[0] || p == THIS->points_[1] || p == THIS->points_[2];
+}
+
+gboolean
+p2t_triangle_contains_ed (P2tTriangle* THIS, const P2tEdge* e)
+{
+ return p2t_triangle_contains_pt (THIS, e->p) && p2t_triangle_contains_pt (THIS, e->q);
+}
+
+gboolean
+p2t_triangle_contains_pt_pt (P2tTriangle* THIS, P2tPoint* p, P2tPoint* q)
+{
+ return p2t_triangle_contains_pt (THIS, p) && p2t_triangle_contains_pt (THIS, q);
+}
+
+gboolean
+p2t_triangle_is_interior (P2tTriangle* THIS)
+{
+ return THIS->interior_;
+}
+
+void
+p2t_triangle_is_interior_b (P2tTriangle* THIS, gboolean b)
+{
+ THIS->interior_ = b;
+}
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/common/shapes.h b/libs/poly2tri-c/poly2tri-c/p2t/common/shapes.h
new file mode 100644
index 0000000..914b37a
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/common/shapes.h
@@ -0,0 +1,262 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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_P2T_SHAPES_H__
+#define __P2TC_P2T_SHAPES_H__
+
+#include <stddef.h>
+#include <assert.h>
+#include <math.h>
+#include "poly2tri-private.h"
+#include "cutils.h"
+
+/**
+ * P2tPoint:
+ * @x: The x coordinate of the point
+ * @y: The y coordinate of the point
+ * @edge_list: The edges this point constitutes an upper ending point
+ *
+ * A struct to represent 2D points with double precision, and to keep track
+ * of the edges this point constitutes an upper ending point
+ */
+struct _P2tPoint
+{
+ /*< public >*/
+ P2tEdgePtrArray edge_list;
+ double x, y;
+};
+
+/**
+ * p2t_point_init_dd:
+ * @THIS: The #P2tPoint to initialize
+ * @x: The desired x coordinate of the point
+ * @y: The desired y coordinate of the point
+ *
+ * A function to initialize a #P2tPoint struct with the given coordinates. The
+ * struct must later be finalized by a call to #p2t_point_destroy
+ */
+void p2t_point_init_dd (P2tPoint* THIS, double x, double y);
+
+/**
+ * p2t_point_new_dd:
+ * @x: The desired x coordinate of the point
+ * @y: The desired y coordinate of the point
+ *
+ * A utility function to alloacte and initialize a #P2tPoint.
+ * See #p2t_point_init_dd. Note that when finished using the point, it must be
+ * freed by a call to #p2t_point_free and can not be freed like regular memory.
+ *
+ * Returns: The allocated and initialized point
+ */
+P2tPoint* p2t_point_new_dd (double x, double y);
+
+/**
+ * p2t_point_init:
+ * @THIS: The #P2tPoint to initialize
+ *
+ * A function to initialize a #P2tPoint struct to (0,0). The struct must later
+ * be finalized by a call to #p2t_point_destroy
+ */
+void p2t_point_init (P2tPoint* THIS);
+
+/**
+ * p2t_point_new:
+ *
+ * A utility function to alloacte and initialize a #P2tPoint.
+ * See #p2t_point_init. Note that when finished using the point, it must be
+ * freed by a call to #p2t_point_free and can not be freed like regular memory.
+ */
+P2tPoint* p2t_point_new ();
+
+/**
+ * p2t_point_destroy:
+ * @THIS: The #P2tPoint whose resources should be freed
+ *
+ * This function will free all the resources allocated by a #P2tPoint, without
+ * freeing the #P2tPoint pointed by @THIS
+ */
+void p2t_point_destroy (P2tPoint* THIS);
+
+/**
+ * p2t_point_free:
+ * @THIS: The #P2tPoint to free
+ *
+ * This function will free all the resources allocated by a #P2tPoint, and will
+ * also free the #P2tPoint pointed by @THIS
+ */
+void p2t_point_free (P2tPoint* THIS);
+
+/**
+ * P2tEdge:
+ * @p: The top right point of the edge
+ * @q: The bottom left point of the edge
+ *
+ * Represents a simple polygon's edge
+ */
+struct _P2tEdge
+{
+ P2tPoint *p, *q;
+};
+
+/**
+ * p2t_edge_init:
+ * @THIS: The #P2tEdge to initialize
+ * @p1: One of the two points that form the edge
+ * @p2: The other point of the two points that form the edge
+ *
+ * A function to initialize a #P2tEdge struct from the given points. The
+ * struct must later be finalized by a call to #p2t_point_destroy.
+ *
+ * Warning: The points must be geometrically not-equal! This means that they
+ * must differ by at least one of their coordinates. Otherwise, a runtime error
+ * would be raised!
+ */
+void p2t_edge_init (P2tEdge* THIS, P2tPoint* p1, P2tPoint* p2);
+
+/**
+ * p2t_edge_new:
+ *
+ * A utility function to alloacte and initialize a #P2tEdge.
+ * See #p2t_edge_init. Note that when finished using the point, it must be freed
+ * by a call to #p2t_point_free and can not be freed like regular memory.
+ *
+ * Returns: The allocated and initialized edge
+ */
+P2tEdge* p2t_edge_new (P2tPoint* p1, P2tPoint* p2);
+
+/**
+ * p2t_edge_destroy:
+ * @THIS: The #P2tEdge whose resources should be freed
+ *
+ * This function will free all the resources allocated by a #P2tEdge, without
+ * freeing the #P2tPoint pointed by @THIS
+ */
+void p2t_edge_destroy (P2tEdge* THIS);
+
+/**
+ * p2t_edge_free:
+ * @THIS: The #P2tEdge to free
+ *
+ * This function will free all the resources allocated by a #P2tEdge, and will
+ * also free the #P2tEdge pointed by @THIS
+ */
+void p2t_edge_free (P2tEdge* THIS);
+
+
+/* Triangle-based data structures are know to have better performance than quad-edge structures
+ * See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator"
+ * "Triangulations in CGAL"
+ */
+
+/**
+ * P2tTriangle:
+ * @constrained_edge: Flags to determine if an edge is a Constrained edge
+ * @delaunay_edg: Flags to determine if an edge is a Delauney edge
+ * @points_: Triangle points
+ * @neighbors_: Neighbor list
+ * @interior_: Has this triangle been marked as an interior triangle?
+ *
+ * A data structure for representing a triangle, while keeping information about
+ * neighbor triangles, etc.
+ */
+struct _P2tTriangle
+{
+ /*< public >*/
+ gboolean constrained_edge[3];
+ gboolean delaunay_edge[3];
+
+ /*< private >*/
+ P2tPoint * points_[3];
+ struct _P2tTriangle * neighbors_[3];
+ gboolean interior_;
+};
+
+P2tTriangle* p2t_triangle_new (P2tPoint* a, P2tPoint* b, P2tPoint* c);
+void p2t_triangle_init (P2tTriangle* THIS, P2tPoint* a, P2tPoint* b, P2tPoint* c);
+P2tPoint* p2t_triangle_get_point (P2tTriangle* THIS, const int index);
+P2tPoint* p2t_triangle_point_cw (P2tTriangle* THIS, P2tPoint* point);
+P2tPoint* p2t_triangle_point_ccw (P2tTriangle* THIS, P2tPoint* point);
+P2tPoint* p2t_triangle_opposite_point (P2tTriangle* THIS, P2tTriangle* t, P2tPoint* p);
+
+P2tTriangle* p2t_triangle_get_neighbor (P2tTriangle* THIS, const int index);
+void p2t_triangle_mark_neighbor_pt_pt_tr (P2tTriangle* THIS, P2tPoint* p1, P2tPoint* p2, P2tTriangle* t);
+void p2t_triangle_mark_neighbor_tr (P2tTriangle* THIS, P2tTriangle *t);
+
+void p2t_triangle_mark_constrained_edge_i (P2tTriangle* THIS, const int index);
+void p2t_triangle_mark_constrained_edge_ed (P2tTriangle* THIS, P2tEdge* edge);
+void p2t_triangle_mark_constrained_edge_pt_pt (P2tTriangle* THIS, P2tPoint* p, P2tPoint* q);
+
+int p2t_triangle_index (P2tTriangle* THIS, const P2tPoint* p);
+int p2t_triangle_edge_index (P2tTriangle* THIS, const P2tPoint* p1, const P2tPoint* p2);
+
+P2tTriangle* p2t_triangle_neighbor_cw (P2tTriangle* THIS, P2tPoint* point);
+P2tTriangle* p2t_triangle_neighbor_ccw (P2tTriangle* THIS, P2tPoint* point);
+gboolean p2t_triangle_get_constrained_edge_ccw (P2tTriangle* THIS, P2tPoint* p);
+gboolean p2t_triangle_get_constrained_edge_cw (P2tTriangle* THIS, P2tPoint* p);
+void p2t_triangle_set_constrained_edge_ccw (P2tTriangle* THIS, P2tPoint* p, gboolean ce);
+void p2t_triangle_set_constrained_edge_cw (P2tTriangle* THIS, P2tPoint* p, gboolean ce);
+gboolean p2t_triangle_get_delunay_edge_ccw (P2tTriangle* THIS, P2tPoint* p);
+gboolean p2t_triangle_get_delunay_edge_cw (P2tTriangle* THIS, P2tPoint* p);
+void p2t_triangle_set_delunay_edge_ccw (P2tTriangle* THIS, P2tPoint* p, gboolean e);
+void p2t_triangle_set_delunay_edge_cw (P2tTriangle* THIS, P2tPoint* p, gboolean e);
+
+gboolean p2t_triangle_contains_pt (P2tTriangle* THIS, P2tPoint* p);
+gboolean p2t_triangle_contains_ed (P2tTriangle* THIS, const P2tEdge* e);
+gboolean p2t_triangle_contains_pt_pt (P2tTriangle* THIS, P2tPoint* p, P2tPoint* q);
+void p2t_triangle_legalize_pt (P2tTriangle* THIS, P2tPoint* point);
+void p2t_triangle_legalize_pt_pt (P2tTriangle* THIS, P2tPoint* opoint, P2tPoint* npoint);
+/**
+ * Clears all references to all other triangles and points
+ */
+void p2t_triangle_clear (P2tTriangle* THIS);
+void p2t_triangle_clear_neighbor_tr (P2tTriangle* THIS, P2tTriangle *triangle);
+void p2t_triangle_clear_neighbors (P2tTriangle* THIS);
+void p2t_triangle_clear_delunay_edges (P2tTriangle* THIS);
+
+gboolean p2t_triangle_is_interior (P2tTriangle* THIS);
+void p2t_triangle_is_interior_b (P2tTriangle* THIS, gboolean b);
+
+P2tTriangle* p2t_triangle_neighbor_across (P2tTriangle* THIS, P2tPoint* opoint);
+
+void p2t_triangle_debug_print (P2tTriangle* THIS);
+
+gint p2t_point_cmp (gconstpointer a, gconstpointer b);
+
+/* gboolean operator == (const Point& a, const Point& b); */
+gboolean p2t_point_equals (const P2tPoint* a, const P2tPoint* b);
+
+#endif
+
+
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/common/utils.c b/libs/poly2tri-c/poly2tri-c/p2t/common/utils.c
new file mode 100644
index 0000000..bc186fc
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/common/utils.c
@@ -0,0 +1,114 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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 <math.h>
+#include "utils.h"
+
+/**
+ * Forumla to calculate signed area<br>
+ * Positive if CCW<br>
+ * Negative if CW<br>
+ * 0 if collinear<br>
+ * <pre>
+ * A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
+ * = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
+ * </pre>
+ */
+P2tOrientation
+p2t_orient2d (P2tPoint* pa, P2tPoint* pb, P2tPoint* pc)
+{
+ double detleft = (pa->x - pc->x) * (pb->y - pc->y);
+ double detright = (pa->y - pc->y) * (pb->x - pc->x);
+ double val = detleft - detright;
+ if (val > -EPSILON && val < EPSILON)
+ {
+ return COLLINEAR;
+ }
+ else if (val > 0)
+ {
+ return CCW;
+ }
+ return CW;
+}
+
+gboolean
+p2t_utils_in_scan_area (P2tPoint* pa, P2tPoint* pb, P2tPoint* pc, P2tPoint* pd)
+{
+#if FALSE
+ double pdx = pd->x;
+ double pdy = pd->y;
+ double adx = pa->x - pdx;
+ double ady = pa->y - pdy;
+ double bdx = pb->x - pdx;
+ double bdy = pb->y - pdy;
+
+ double adxbdy = adx * bdy;
+ double bdxady = bdx * ady;
+ double oabd = adxbdy - bdxady;
+
+ double cdx, cdy;
+ double cdxady, adxcdy, ocad;
+
+ if (oabd <= EPSILON)
+ {
+ return FALSE;
+ }
+
+ cdx = pc->x - pdx;
+ cdy = pc->y - pdy;
+
+ cdxady = cdx * ady;
+ adxcdy = adx * cdy;
+ ocad = cdxady - adxcdy;
+
+ if (ocad <= EPSILON)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+#else
+ gdouble oadc, oadb = (pa->x - pb->x)*(pd->y - pb->y) - (pd->x - pb->x)*(pa->y - pb->y);
+ if (oadb >= -EPSILON) {
+ return FALSE;
+ }
+
+ oadc = (pa->x - pc->x)*(pd->y - pc->y) - (pd->x - pc->x)*(pa->y - pc->y);
+ if (oadc <= EPSILON) {
+ return FALSE;
+ }
+ return TRUE;
+#endif
+}
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/common/utils.h b/libs/poly2tri-c/poly2tri-c/p2t/common/utils.h
new file mode 100644
index 0000000..18688bb
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/common/utils.h
@@ -0,0 +1,67 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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_P2T_UTILS_H__
+#define __P2TC_P2T_UTILS_H__
+
+#include <glib.h>
+#include "poly2tri-private.h"
+#include "cutils.h"
+#include "shapes.h"
+
+#define PI_3div4 (3 * G_PI / 4)
+#define EPSILON (1e-6)
+
+typedef enum
+{
+ CW, CCW, COLLINEAR
+} P2tOrientation;
+
+/**
+ * Forumla to calculate signed area<br>
+ * Positive if CCW<br>
+ * Negative if CW<br>
+ * 0 if collinear<br>
+ * <pre>
+ * A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
+ * = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
+ * </pre>
+ */
+P2tOrientation p2t_orient2d (P2tPoint* pa, P2tPoint* pb, P2tPoint* pc);
+
+gboolean p2t_utils_in_scan_area (P2tPoint* pa, P2tPoint* pb, P2tPoint* pc, P2tPoint* pd);
+
+#endif
+
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/poly2tri.h b/libs/poly2tri-c/poly2tri-c/p2t/poly2tri.h
new file mode 100644
index 0000000..d34d5f6
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/poly2tri.h
@@ -0,0 +1,43 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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_P2T_POLY2TRI_H__
+#define __P2TC_P2T_POLY2TRI_H__
+
+#include "common/shapes.h"
+#include "sweep/cdt.h"
+
+#endif
+
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/sweep/Makefile.am b/libs/poly2tri-c/poly2tri-c/p2t/sweep/Makefile.am
new file mode 100644
index 0000000..5cf18ca
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/sweep/Makefile.am
@@ -0,0 +1,5 @@
+noinst_LTLIBRARIES = libp2tc-sweep.la
+libp2tc_sweep_la_SOURCES = advancing_front.c advancing_front.h cdt.c cdt.h sweep.c sweep_context.c sweep_context.h sweep.h
+
+P2TC_P2T_SWEEP_publicdir = $(P2TC_P2T_publicdir)/sweep
+P2TC_P2T_SWEEP_public_HEADERS = advancing_front.h cdt.h sweep_context.h sweep.h
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/sweep/advancing_front.c b/libs/poly2tri-c/poly2tri-c/p2t/sweep/advancing_front.c
new file mode 100644
index 0000000..c9ab8f9
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/sweep/advancing_front.c
@@ -0,0 +1,229 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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 "advancing_front.h"
+
+void
+p2t_node_init_pt (P2tNode* THIS, P2tPoint* p)
+{
+ THIS->point = p;
+ THIS->triangle = NULL;
+ THIS->value = p->x;
+ THIS->next = NULL;
+ THIS->prev = NULL;
+}
+
+P2tNode*
+p2t_node_new_pt (P2tPoint* p)
+{
+ P2tNode* THIS = g_slice_new (P2tNode);
+ p2t_node_init_pt (THIS, p);
+ return THIS;
+}
+
+void
+p2t_node_init_pt_tr (P2tNode* THIS, P2tPoint* p, P2tTriangle* t)
+{
+ THIS->point = p;
+ THIS->triangle = t;
+ THIS->value = p->x;
+ THIS->next = NULL;
+ THIS->prev = NULL;
+}
+
+P2tNode*
+p2t_node_new_pt_tr (P2tPoint* p, P2tTriangle* t)
+{
+ P2tNode* THIS = g_slice_new (P2tNode);
+ p2t_node_init_pt_tr (THIS, p, t);
+ return THIS;
+}
+
+void p2t_node_destroy (P2tNode* THIS)
+{
+}
+void p2t_node_free (P2tNode* THIS)
+{
+ p2t_node_destroy (THIS);
+ g_slice_free (P2tNode, THIS);
+}
+
+void
+p2t_advancingfront_init (P2tAdvancingFront* THIS, P2tNode* head, P2tNode* tail)
+{
+ THIS->head_ = head;
+ THIS->tail_ = tail;
+ THIS->search_node_ = head;
+}
+
+P2tAdvancingFront*
+p2t_advancingfront_new (P2tNode* head, P2tNode* tail)
+{
+ P2tAdvancingFront* THIS = g_slice_new (P2tAdvancingFront);
+ p2t_advancingfront_init (THIS, head, tail);
+ return THIS;
+}
+
+void
+p2t_advancingfront_destroy (P2tAdvancingFront* THIS) { }
+
+void
+p2t_advancingfront_free (P2tAdvancingFront* THIS)
+{
+ p2t_advancingfront_destroy (THIS);
+ g_slice_free (P2tAdvancingFront, THIS);
+}
+
+P2tNode*
+p2t_advancingfront_locate_node (P2tAdvancingFront *THIS, const double x)
+{
+ P2tNode* node = THIS->search_node_;
+
+ if (x < node->value)
+ {
+ while ((node = node->prev) != NULL)
+ {
+ if (x >= node->value)
+ {
+ THIS->search_node_ = node;
+ return node;
+ }
+ }
+ }
+ else
+ {
+ while ((node = node->next) != NULL)
+ {
+ if (x < node->value)
+ {
+ THIS->search_node_ = node->prev;
+ return node->prev;
+ }
+ }
+ }
+ return NULL;
+}
+
+P2tNode*
+p2t_advancingfront_find_search_node (P2tAdvancingFront *THIS, const double x)
+{
+ /* TODO: implement BST index */
+ return THIS->search_node_;
+}
+
+P2tNode*
+p2t_advancingfront_locate_point (P2tAdvancingFront *THIS, const P2tPoint* point)
+{
+ const double px = point->x;
+ P2tNode* node = p2t_advancingfront_find_search_node (THIS, px);
+ const double nx = node->point->x;
+
+ if (px == nx)
+ {
+ if (point != node->point)
+ {
+ /* We might have two nodes with same x value for a short time */
+ if (point == node->prev->point)
+ {
+ node = node->prev;
+ }
+ else if (point == node->next->point)
+ {
+ node = node->next;
+ }
+ else
+ {
+ assert (0);
+ }
+ }
+ }
+ else if (px < nx)
+ {
+ while ((node = node->prev) != NULL)
+ {
+ if (point == node->point)
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ while ((node = node->next) != NULL)
+ {
+ if (point == node->point)
+ break;
+ }
+ }
+ if (node) THIS->search_node_ = node;
+ return node;
+}
+
+P2tNode*
+p2t_advancingfront_head (P2tAdvancingFront *THIS)
+{
+ return THIS->head_;
+}
+
+void
+AdvancingFront_set_head (P2tAdvancingFront *THIS, P2tNode* node)
+{
+ THIS->head_ = node;
+}
+
+P2tNode*
+p2t_advancingfront_tail (P2tAdvancingFront *THIS)
+{
+ return THIS->tail_;
+}
+
+void
+p2t_advancingfront_set_tail (P2tAdvancingFront *THIS, P2tNode* node)
+{
+ THIS->tail_ = node;
+}
+
+P2tNode*
+p2t_advancingfront_search (P2tAdvancingFront *THIS)
+{
+ return THIS->search_node_;
+}
+
+void
+p2t_advancingfront_set_search (P2tAdvancingFront *THIS, P2tNode* node)
+{
+ THIS->search_node_ = node;
+}
+
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/sweep/advancing_front.h b/libs/poly2tri-c/poly2tri-c/p2t/sweep/advancing_front.h
new file mode 100644
index 0000000..43f943e
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/sweep/advancing_front.h
@@ -0,0 +1,92 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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_P2T_ADVANCING_FRONT_H__
+#define __P2TC_P2T_ADVANCING_FRONT_H__
+
+#include "../common/poly2tri-private.h"
+#include "../common/shapes.h"
+
+/* Advancing front node */
+
+struct _P2tNode
+{
+ P2tPoint* point;
+ P2tTriangle* triangle;
+
+ struct _P2tNode* next;
+ struct _P2tNode* prev;
+
+ double value;
+};
+
+void p2t_node_init_pt (P2tNode* THIS, P2tPoint* p);
+P2tNode* p2t_node_new_pt (P2tPoint* p);
+void p2t_node_init_pt_tr (P2tNode* THIS, P2tPoint* p, P2tTriangle* t);
+P2tNode* p2t_node_new_pt_tr (P2tPoint* p, P2tTriangle* t);
+void p2t_node_destroy (P2tNode* THIS);
+void p2t_node_free (P2tNode* THIS);
+
+/* Advancing front */
+
+struct AdvancingFront_
+{
+ /* private: */
+
+ P2tNode* head_, *tail_, *search_node_;
+
+};
+
+void p2t_advancingfront_init (P2tAdvancingFront* THIS, P2tNode* head, P2tNode* tail);
+P2tAdvancingFront* p2t_advancingfront_new (P2tNode* head, P2tNode* tail);
+
+void p2t_advancingfront_destroy (P2tAdvancingFront* THIS);
+void p2t_advancingfront_free (P2tAdvancingFront* THIS);
+
+P2tNode* p2t_advancingfront_head (P2tAdvancingFront *THIS);
+void AdvancingFront_set_head (P2tAdvancingFront *THIS, P2tNode* node);
+P2tNode* p2t_advancingfront_tail (P2tAdvancingFront *THIS);
+void p2t_advancingfront_set_tail (P2tAdvancingFront *THIS, P2tNode* node);
+P2tNode* p2t_advancingfront_search (P2tAdvancingFront *THIS);
+void p2t_advancingfront_set_search (P2tAdvancingFront *THIS, P2tNode* node);
+
+/** Locate insertion point along advancing front */
+P2tNode* p2t_advancingfront_locate_node (P2tAdvancingFront *THIS, const double x);
+
+P2tNode* p2t_advancingfront_locate_point (P2tAdvancingFront *THIS, const P2tPoint* point);
+
+P2tNode* p2t_advancingfront_find_search_node (P2tAdvancingFront *THIS, const double x);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/sweep/cdt.c b/libs/poly2tri-c/poly2tri-c/p2t/sweep/cdt.c
new file mode 100644
index 0000000..738d72e
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/sweep/cdt.c
@@ -0,0 +1,95 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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 "cdt.h"
+
+void
+p2t_cdt_init (P2tCDT* THIS, P2tPointPtrArray polyline)
+{
+ THIS->sweep_context_ = p2t_sweepcontext_new (polyline);
+ THIS->sweep_ = p2t_sweep_new ();
+}
+
+P2tCDT*
+p2t_cdt_new (P2tPointPtrArray polyline)
+{
+ P2tCDT* THIS = g_slice_new (P2tCDT);
+ p2t_cdt_init (THIS, polyline);
+ return THIS;
+}
+
+void
+p2t_cdt_destroy (P2tCDT* THIS)
+{
+ p2t_sweepcontext_delete (THIS->sweep_context_);
+ p2t_sweep_free (THIS->sweep_);
+}
+
+void
+p2t_cdt_free (P2tCDT* THIS)
+{
+ p2t_cdt_destroy (THIS);
+ g_slice_free (P2tCDT, THIS);
+}
+
+void
+p2t_cdt_add_hole (P2tCDT *THIS, P2tPointPtrArray polyline)
+{
+ p2t_sweepcontext_add_hole (THIS->sweep_context_, polyline);
+}
+
+void
+p2t_cdt_add_point (P2tCDT *THIS, P2tPoint* point)
+{
+ p2t_sweepcontext_add_point (THIS->sweep_context_, point);
+}
+
+void
+p2t_cdt_triangulate (P2tCDT *THIS)
+{
+ p2t_sweep_triangulate (THIS->sweep_, THIS->sweep_context_);
+}
+
+P2tTrianglePtrArray
+p2t_cdt_get_triangles (P2tCDT *THIS)
+{
+ return p2t_sweepcontext_get_triangles (THIS->sweep_context_);
+}
+
+P2tTrianglePtrList
+p2t_cdt_get_map (P2tCDT *THIS)
+{
+ return p2t_sweepcontext_get_map (THIS->sweep_context_);
+}
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/sweep/cdt.h b/libs/poly2tri-c/poly2tri-c/p2t/sweep/cdt.h
new file mode 100644
index 0000000..d21b5ed
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/sweep/cdt.h
@@ -0,0 +1,105 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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_P2T_CDT_H__
+#define __P2TC_P2T_CDT_H__
+
+#include "../common/poly2tri-private.h"
+#include "advancing_front.h"
+#include "sweep_context.h"
+#include "sweep.h"
+
+/**
+ *
+ * @author Mason Green <mason green gmail com>
+ *
+ */
+
+struct CDT_
+{
+ /*private: */
+
+ /**
+ * Internals
+ */
+
+ P2tSweepContext* sweep_context_;
+ P2tSweep* sweep_;
+
+};
+/**
+ * Constructor - add polyline with non repeating points
+ *
+ * @param polyline
+ */
+void p2t_cdt_init (P2tCDT* THIS, P2tPointPtrArray polyline);
+P2tCDT* p2t_cdt_new (P2tPointPtrArray polyline);
+
+/**
+ * Destructor - clean up memory
+ */
+void p2t_cdt_destroy (P2tCDT* THIS);
+void p2t_cdt_free (P2tCDT* THIS);
+
+/**
+ * Add a hole
+ *
+ * @param polyline
+ */
+void p2t_cdt_add_hole (P2tCDT *THIS, P2tPointPtrArray polyline);
+
+/**
+ * Add a steiner point
+ *
+ * @param point
+ */
+void p2t_cdt_add_point (P2tCDT *THIS, P2tPoint* point);
+
+/**
+ * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points
+ */
+void p2t_cdt_triangulate (P2tCDT *THIS);
+
+/**
+ * Get CDT triangles
+ */
+P2tTrianglePtrArray p2t_cdt_get_triangles (P2tCDT *THIS);
+
+/**
+ * Get triangle map
+ */
+P2tTrianglePtrList p2t_cdt_get_map (P2tCDT *THIS);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep.c b/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep.c
new file mode 100644
index 0000000..7680075
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep.c
@@ -0,0 +1,1024 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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 <math.h>
+
+#include "sweep.h"
+#include "sweep_context.h"
+#include "advancing_front.h"
+#include "../common/utils.h"
+#include "../common/shapes.h"
+
+void
+p2t_sweep_init (P2tSweep* THIS)
+{
+ THIS->nodes_ = g_ptr_array_new ();
+}
+
+P2tSweep*
+p2t_sweep_new ()
+{
+ P2tSweep* THIS = g_new (P2tSweep, 1);
+ p2t_sweep_init (THIS);
+ return THIS;
+}
+
+/**
+ * Destructor - clean up memory
+ */
+void
+p2t_sweep_destroy (P2tSweep* THIS)
+{
+ int i;
+ /* Clean up memory */
+ for (i = 0; i < THIS->nodes_->len; i++)
+ {
+ p2t_node_free (node_index (THIS->nodes_, i));
+ }
+
+ g_ptr_array_free (THIS->nodes_, TRUE);
+}
+
+void
+p2t_sweep_free (P2tSweep* THIS)
+{
+ p2t_sweep_destroy (THIS);
+ g_free (THIS);
+}
+
+/* Triangulate simple polygon with holes */
+
+void
+p2t_sweep_triangulate (P2tSweep *THIS, P2tSweepContext *tcx)
+{
+ p2t_sweepcontext_init_triangulation (tcx);
+ p2t_sweepcontext_create_advancingfront (tcx, THIS->nodes_);
+ /* Sweep points; build mesh */
+ p2t_sweep_sweep_points (THIS, tcx);
+ /* Clean up */
+ p2t_sweep_finalization_polygon (THIS, tcx);
+}
+
+void
+p2t_sweep_sweep_points (P2tSweep *THIS, P2tSweepContext *tcx)
+{
+ int i, j;
+ for (i = 1; i < p2t_sweepcontext_point_count (tcx); i++)
+ {
+ P2tPoint* point = p2t_sweepcontext_get_point (tcx, i);
+ P2tNode* node = p2t_sweep_point_event (THIS, tcx, point);
+ for (j = 0; j < point->edge_list->len; j++)
+ {
+ p2t_sweep_edge_event_ed_n (THIS, tcx, edge_index (point->edge_list, j), node);
+ }
+ }
+}
+
+void
+p2t_sweep_finalization_polygon (P2tSweep *THIS, P2tSweepContext *tcx)
+{
+ /* Get an Internal triangle to start with */
+ P2tTriangle* t = p2t_advancingfront_head (p2t_sweepcontext_front (tcx))->next->triangle;
+ P2tPoint* p = p2t_advancingfront_head (p2t_sweepcontext_front (tcx))->next->point;
+ while (!p2t_triangle_get_constrained_edge_cw (t, p))
+ {
+ t = p2t_triangle_neighbor_ccw (t, p);
+ }
+
+ /* Collect interior triangles constrained by edges */
+ p2t_sweepcontext_mesh_clean (tcx, t);
+}
+
+P2tNode*
+p2t_sweep_point_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tPoint* point)
+{
+ P2tNode* node = p2t_sweepcontext_locate_node (tcx, point);
+ P2tNode* new_node = p2t_sweep_new_front_triangle (THIS, tcx, point, node);
+
+ /* Only need to check +epsilon since point never have smaller
+ * x value than node due to how we fetch nodes from the front */
+ if (point->x <= node->point->x + EPSILON)
+ {
+ p2t_sweep_fill (THIS, tcx, node);
+ }
+
+ /*tcx.AddNode(new_node); */
+
+ p2t_sweep_fill_advancingfront (THIS, tcx, new_node);
+ return new_node;
+}
+
+void
+p2t_sweep_edge_event_ed_n (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node)
+{
+ tcx->edge_event.constrained_edge = edge;
+ tcx->edge_event.right = (edge->p->x > edge->q->x);
+
+ if (p2t_sweep_is_edge_side_of_triangle (THIS, node->triangle, edge->p, edge->q))
+ {
+ return;
+ }
+
+ /* For now we will do all needed filling
+ * TODO: integrate with flip process might give some better performance
+ * but for now this avoid the issue with cases that needs both flips and fills
+ */
+ p2t_sweep_fill_edge_event (THIS, tcx, edge, node);
+ p2t_sweep_edge_event_pt_pt_tr_pt (THIS, tcx, edge->p, edge->q, node->triangle, edge->q);
+}
+
+void
+p2t_sweep_edge_event_pt_pt_tr_pt (P2tSweep *THIS, P2tSweepContext *tcx, P2tPoint* ep, P2tPoint* eq, P2tTriangle* triangle, P2tPoint* point)
+{
+ P2tPoint *p1, *p2;
+ P2tOrientation o1, o2;
+
+ if (p2t_sweep_is_edge_side_of_triangle (THIS, triangle, ep, eq))
+ {
+ return;
+ }
+
+ p1 = p2t_triangle_point_ccw (triangle, point);
+ o1 = p2t_orient2d (eq, p1, ep);
+ if (o1 == COLLINEAR)
+ {
+ if (p2t_triangle_contains_pt_pt (triangle, eq, p1))
+ {
+ p2t_triangle_mark_constrained_edge_pt_pt (triangle, eq, p1);
+ /* We are modifying the constraint maybe it would be better to
+ * not change the given constraint and just keep a variable for the new constraint
+ */
+ tcx->edge_event.constrained_edge->q = p1;
+ triangle = p2t_triangle_neighbor_across (triangle, point);
+ p2t_sweep_edge_event_pt_pt_tr_pt (THIS, tcx, ep, p1, triangle, p1);
+ }
+ else
+ {
+ g_error ("EdgeEvent - collinear points not supported");
+ }
+ return;
+ }
+
+ p2 = p2t_triangle_point_cw (triangle, point);
+ o2 = p2t_orient2d (eq, p2, ep);
+ if (o2 == COLLINEAR)
+ {
+ if (p2t_triangle_contains_pt_pt (triangle, eq, p2))
+ {
+ p2t_triangle_mark_constrained_edge_pt_pt (triangle, eq, p2);
+ /* We are modifying the constraint maybe it would be better to
+ * not change the given constraint and just keep a variable for the new constraint
+ */
+ tcx->edge_event.constrained_edge->q = p2;
+ triangle = p2t_triangle_neighbor_across (triangle, point);
+ p2t_sweep_edge_event_pt_pt_tr_pt (THIS, tcx, ep, p2, triangle, p2);
+ }
+ else
+ {
+ g_error ("EdgeEvent - collinear points not supported");
+ }
+ return;
+ }
+
+ if (o1 == o2)
+ {
+ /* Need to decide if we are rotating CW or CCW to get to a triangle
+ * that will cross edge */
+ if (o1 == CW)
+ {
+ triangle = p2t_triangle_neighbor_ccw (triangle, point);
+ }
+ else
+ {
+ triangle = p2t_triangle_neighbor_cw (triangle, point);
+ }
+ p2t_sweep_edge_event_pt_pt_tr_pt (THIS, tcx, ep, eq, triangle, point);
+ }
+ else
+ {
+ /* This triangle crosses constraint so lets flippin start! */
+ p2t_sweep_flip_edge_event (THIS, tcx, ep, eq, triangle, point);
+ }
+}
+
+gboolean
+p2t_sweep_is_edge_side_of_triangle (P2tSweep *THIS, P2tTriangle *triangle, P2tPoint* ep, P2tPoint* eq)
+{
+ int index = p2t_triangle_edge_index (triangle, ep, eq);
+
+ if (index != -1)
+ {
+ P2tTriangle *t;
+ p2t_triangle_mark_constrained_edge_i (triangle, index);
+ t = p2t_triangle_get_neighbor (triangle, index);
+ if (t)
+ {
+ p2t_triangle_mark_constrained_edge_pt_pt (t, ep, eq);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+P2tNode*
+p2t_sweep_new_front_triangle (P2tSweep *THIS, P2tSweepContext *tcx, P2tPoint* point, P2tNode *node)
+{
+ P2tTriangle* triangle = p2t_triangle_new (point, node->point, node->next->point);
+ P2tNode *new_node;
+
+ p2t_triangle_mark_neighbor_tr (triangle, node->triangle);
+ p2t_sweepcontext_add_to_map (tcx, triangle);
+
+ new_node = p2t_node_new_pt (point);
+ g_ptr_array_add (THIS->nodes_, new_node);
+
+ new_node->next = node->next;
+ new_node->prev = node;
+ node->next->prev = new_node;
+ node->next = new_node;
+
+ if (!p2t_sweep_legalize (THIS, tcx, triangle))
+ {
+ p2t_sweepcontext_map_triangle_to_nodes (tcx, triangle);
+ }
+
+ return new_node;
+}
+
+void
+p2t_sweep_fill (P2tSweep *THIS, P2tSweepContext *tcx, P2tNode* node)
+{
+ P2tTriangle* triangle = p2t_triangle_new (node->prev->point, node->point, node->next->point);
+
+ /* TODO: should copy the constrained_edge value from neighbor triangles
+ * for now constrained_edge values are copied during the legalize */
+ p2t_triangle_mark_neighbor_tr (triangle, node->prev->triangle);
+ p2t_triangle_mark_neighbor_tr (triangle, node->triangle);
+
+ p2t_sweepcontext_add_to_map (tcx, triangle);
+
+ /* Update the advancing front */
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+
+ /* If it was legalized the triangle has already been mapped */
+ if (!p2t_sweep_legalize (THIS, tcx, triangle))
+ {
+ p2t_sweepcontext_map_triangle_to_nodes (tcx, triangle);
+ }
+
+}
+
+void
+p2t_sweep_fill_advancingfront (P2tSweep *THIS, P2tSweepContext *tcx, P2tNode* n)
+{
+
+ /* Fill right holes */
+ P2tNode* node = n->next;
+
+ while (node->next)
+ {
+ /* if HoleAngle exceeds 90 degrees then break. */
+ if (p2t_sweep_large_hole_dont_fill (THIS, node)) break;
+ p2t_sweep_fill (THIS, tcx, node);
+ node = node->next;
+ }
+
+ /* Fill left holes */
+ node = n->prev;
+
+ while (node->prev)
+ {
+ /* if HoleAngle exceeds 90 degrees then break. */
+ if (p2t_sweep_large_hole_dont_fill (THIS, node)) break;
+ p2t_sweep_fill (THIS, tcx, node);
+ node = node->prev;
+ }
+
+ /* Fill right basins */
+ if (n->next && n->next->next)
+ {
+ double angle = p2t_sweep_basin_angle (THIS, n);
+ if (angle < PI_3div4)
+ {
+ p2t_sweep_fill_basin (THIS, tcx, n);
+ }
+ }
+}
+
+/* True if HoleAngle exceeds 90 degrees. */
+gboolean
+p2t_sweep_large_hole_dont_fill (P2tSweep *THIS, P2tNode* node)
+{
+ P2tNode* nextNode = node->next;
+ P2tNode* prevNode = node->prev;
+ P2tNode *next2Node, *prev2Node;
+ if (! p2t_sweep_angle_exceeds_90_degrees (THIS, node->point, nextNode->point, prevNode->point))
+ return FALSE;
+
+ /* Check additional points on front. */
+ next2Node = nextNode->next;
+ /* "..Plus.." because only want angles on same side as point being added. */
+ if ((next2Node != NULL) && !p2t_sweep_angle_exceeds_plus_90_degrees_or_is_negative (THIS, node->point, next2Node->point, prevNode->point))
+ return FALSE;
+
+ prev2Node = prevNode->prev;
+ /* "..Plus.." because only want angles on same side as point being added. */
+ if ((prev2Node != NULL) && !p2t_sweep_angle_exceeds_plus_90_degrees_or_is_negative (THIS, node->point, nextNode->point, prev2Node->point))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+p2t_sweep_angle_exceeds_90_degrees(P2tSweep* THIS, P2tPoint* origin, P2tPoint* pa, P2tPoint* pb)
+{
+ gdouble angle = p2t_sweep_angle (THIS, origin, pa, pb);
+ gboolean exceeds90Degrees = ((angle > G_PI_2) || (angle < -G_PI_2));
+ return exceeds90Degrees;
+}
+
+gboolean
+p2t_sweep_angle_exceeds_plus_90_degrees_or_is_negative (P2tSweep* THIS, P2tPoint* origin, P2tPoint* pa, P2tPoint* pb)
+{
+ gdouble angle = p2t_sweep_angle (THIS, origin, pa, pb);
+ gboolean exceedsPlus90DegreesOrIsNegative = (angle > G_PI_2) || (angle < 0);
+ return exceedsPlus90DegreesOrIsNegative;
+}
+
+gdouble
+p2t_sweep_angle (P2tSweep* THIS, P2tPoint* origin, P2tPoint* pa, P2tPoint* pb) {
+ /* Complex plane
+ * ab = cosA +i*sinA
+ * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
+ * atan2(y,x) computes the principal value of the argument function
+ * applied to the complex number x+iy
+ * Where x = ax*bx + ay*by
+ * y = ax*by - ay*bx
+ */
+ double px = origin->x;
+ double py = origin->y;
+ double ax = pa->x - px;
+ double ay = pa->y - py;
+ double bx = pb->x - px;
+ double by = pb->y - py;
+ double x = ax * by - ay * bx;
+ double y = ax * bx + ay * by;
+ double angle = atan2(x, y);
+ return angle;
+}
+
+double
+p2t_sweep_basin_angle (P2tSweep *THIS, P2tNode* node)
+{
+ double ax = node->point->x - node->next->next->point->x;
+ double ay = node->point->y - node->next->next->point->y;
+ return atan2 (ay, ax);
+}
+
+double
+p2t_sweep_hole_angle (P2tSweep *THIS, P2tNode* node)
+{
+ /* Complex plane
+ * ab = cosA +i*sinA
+ * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
+ * atan2(y,x) computes the principal value of the argument function
+ * applied to the complex number x+iy
+ * Where x = ax*bx + ay*by
+ * y = ax*by - ay*bx
+ */
+ double ax = node->next->point->x - node->point->x;
+ double ay = node->next->point->y - node->point->y;
+ double bx = node->prev->point->x - node->point->x;
+ double by = node->prev->point->y - node->point->y;
+ return atan2 (ax * by - ay * bx, ax * bx + ay * by);
+}
+
+gboolean
+p2t_sweep_legalize (P2tSweep *THIS, P2tSweepContext *tcx, P2tTriangle *t)
+{
+ int i;
+ /* To legalize a triangle we start by finding if any of the three edges
+ * violate the Delaunay condition */
+ for (i = 0; i < 3; i++)
+ {
+ P2tTriangle *ot;
+
+ if (t->delaunay_edge[i])
+ continue;
+
+ ot = p2t_triangle_get_neighbor (t, i);
+
+ if (ot)
+ {
+ P2tPoint* p = p2t_triangle_get_point (t, i);
+ P2tPoint* op = p2t_triangle_opposite_point (ot, t, p);
+ int oi = p2t_triangle_index (ot, op);
+ gboolean inside;
+
+ /* If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)
+ * then we should not try to legalize */
+ if (ot->constrained_edge[oi] || ot->delaunay_edge[oi])
+ {
+ t->constrained_edge[i] = ot->constrained_edge[oi];
+ continue;
+ }
+
+ inside = p2t_sweep_incircle (THIS, p, p2t_triangle_point_ccw (t, p), p2t_triangle_point_cw (t, p), op);
+
+ if (inside)
+ {
+ gboolean not_legalized;
+ /* Lets mark this shared edge as Delaunay */
+ t->delaunay_edge[i] = TRUE;
+ ot->delaunay_edge[oi] = TRUE;
+
+ /* Lets rotate shared edge one vertex CW to legalize it */
+ p2t_sweep_rotate_triangle_pair (THIS, t, p, ot, op);
+
+ /* We now got one valid Delaunay Edge shared by two triangles
+ * This gives us 4 new edges to check for Delaunay */
+
+ /* Make sure that triangle to node mapping is done only one time for a specific triangle */
+ not_legalized = !p2t_sweep_legalize (THIS, tcx, t);
+ if (not_legalized)
+ {
+ p2t_sweepcontext_map_triangle_to_nodes (tcx, t);
+ }
+
+ not_legalized = !p2t_sweep_legalize (THIS, tcx, ot);
+ if (not_legalized)
+ p2t_sweepcontext_map_triangle_to_nodes (tcx, ot);
+
+ /* Reset the Delaunay edges, since they only are valid Delaunay edges
+ * until we add a new triangle or point.
+ * XXX: need to think about this. Can these edges be tried after we
+ * return to previous recursive level? */
+ t->delaunay_edge[i] = FALSE;
+ ot->delaunay_edge[oi] = FALSE;
+
+ /* If triangle have been legalized no need to check the other edges since
+ * the recursive legalization will handles those so we can end here.*/
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+gboolean
+p2t_sweep_incircle (P2tSweep *THIS, P2tPoint* pa, P2tPoint* pb, P2tPoint* pc, P2tPoint* pd)
+{
+ double adx = pa->x - pd->x;
+ double ady = pa->y - pd->y;
+ double bdx = pb->x - pd->x;
+ double bdy = pb->y - pd->y;
+
+ double adxbdy = adx * bdy;
+ double bdxady = bdx * ady;
+ double oabd = adxbdy - bdxady;
+
+ double cdx, cdy;
+ double cdxady, adxcdy, ocad;
+
+ double bdxcdy, cdxbdy;
+ double alift, blift, clift;
+ double det;
+
+ if (oabd <= 0)
+ return FALSE;
+
+ cdx = pc->x - pd->x;
+ cdy = pc->y - pd->y;
+
+ cdxady = cdx * ady;
+ adxcdy = adx * cdy;
+ ocad = cdxady - adxcdy;
+
+ if (ocad <= 0)
+ return FALSE;
+
+ bdxcdy = bdx * cdy;
+ cdxbdy = cdx * bdy;
+
+ alift = adx * adx + ady * ady;
+ blift = bdx * bdx + bdy * bdy;
+ clift = cdx * cdx + cdy * cdy;
+
+ det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
+
+ return det > 0;
+}
+
+void
+p2t_sweep_rotate_triangle_pair (P2tSweep *THIS, P2tTriangle *t, P2tPoint* p, P2tTriangle *ot, P2tPoint* op)
+{
+ P2tTriangle *n1, *n2, *n3, *n4;
+ gboolean ce1, ce2, ce3, ce4;
+ gboolean de1, de2, de3, de4;
+
+ n1 = p2t_triangle_neighbor_ccw (t, p);
+ n2 = p2t_triangle_neighbor_cw (t, p);
+ n3 = p2t_triangle_neighbor_ccw (ot, op);
+ n4 = p2t_triangle_neighbor_cw (ot, op);
+
+ ce1 = p2t_triangle_get_constrained_edge_ccw (t, p);
+ ce2 = p2t_triangle_get_constrained_edge_cw (t, p);
+ ce3 = p2t_triangle_get_constrained_edge_ccw (ot, op);
+ ce4 = p2t_triangle_get_constrained_edge_cw (ot, op);
+
+ de1 = p2t_triangle_get_delunay_edge_ccw (t, p);
+ de2 = p2t_triangle_get_delunay_edge_cw (t, p);
+ de3 = p2t_triangle_get_delunay_edge_ccw (ot, op);
+ de4 = p2t_triangle_get_delunay_edge_cw (ot, op);
+
+ p2t_triangle_legalize_pt_pt (t, p, op);
+ p2t_triangle_legalize_pt_pt (ot, op, p);
+
+ /* Remap delaunay_edge */
+ p2t_triangle_set_delunay_edge_ccw (ot, p, de1);
+ p2t_triangle_set_delunay_edge_cw (t, p, de2);
+ p2t_triangle_set_delunay_edge_ccw (t, op, de3);
+ p2t_triangle_set_delunay_edge_cw (ot, op, de4);
+
+ /* Remap constrained_edge */
+ p2t_triangle_set_constrained_edge_ccw (ot, p, ce1);
+ p2t_triangle_set_constrained_edge_cw (t, p, ce2);
+ p2t_triangle_set_constrained_edge_ccw (t, op, ce3);
+ p2t_triangle_set_constrained_edge_cw (ot, op, ce4);
+
+ /* Remap neighbors
+ * XXX: might optimize the markNeighbor by keeping track of
+ * what side should be assigned to what neighbor after the
+ * rotation. Now mark neighbor does lots of testing to find
+ * the right side. */
+ p2t_triangle_clear_neighbors (t);
+ p2t_triangle_clear_neighbors (ot);
+ if (n1) p2t_triangle_mark_neighbor_tr (ot, n1);
+ if (n2) p2t_triangle_mark_neighbor_tr (t, n2);
+ if (n3) p2t_triangle_mark_neighbor_tr (t, n3);
+ if (n4) p2t_triangle_mark_neighbor_tr (ot, n4);
+ p2t_triangle_mark_neighbor_tr (t, ot);
+}
+
+void
+p2t_sweep_fill_basin (P2tSweep *THIS, P2tSweepContext *tcx, P2tNode* node)
+{
+ if (p2t_orient2d (node->point, node->next->point, node->next->next->point) == CCW)
+ {
+ tcx->basin.left_node = node->next->next;
+ }
+ else
+ {
+ tcx->basin.left_node = node->next;
+ }
+
+ /* Find the bottom and right node */
+ tcx->basin.bottom_node = tcx->basin.left_node;
+ while (tcx->basin.bottom_node->next
+ && tcx->basin.bottom_node->point->y >= tcx->basin.bottom_node->next->point->y)
+ {
+ tcx->basin.bottom_node = tcx->basin.bottom_node->next;
+ }
+ if (tcx->basin.bottom_node == tcx->basin.left_node)
+ {
+ /* No valid basin */
+ return;
+ }
+
+ tcx->basin.right_node = tcx->basin.bottom_node;
+ while (tcx->basin.right_node->next
+ && tcx->basin.right_node->point->y < tcx->basin.right_node->next->point->y)
+ {
+ tcx->basin.right_node = tcx->basin.right_node->next;
+ }
+ if (tcx->basin.right_node == tcx->basin.bottom_node)
+ {
+ /* No valid basins */
+ return;
+ }
+
+ tcx->basin.width = tcx->basin.right_node->point->x - tcx->basin.left_node->point->x;
+ tcx->basin.left_highest = tcx->basin.left_node->point->y > tcx->basin.right_node->point->y;
+
+ p2t_sweep_fill_basin_req (THIS, tcx, tcx->basin.bottom_node);
+}
+
+void
+p2t_sweep_fill_basin_req (P2tSweep *THIS, P2tSweepContext *tcx, P2tNode* node)
+{
+ /* if shallow stop filling */
+ if (p2t_sweep_is_shallow (THIS, tcx, node))
+ {
+ return;
+ }
+
+ p2t_sweep_fill (THIS, tcx, node);
+
+ if (node->prev == tcx->basin.left_node && node->next == tcx->basin.right_node)
+ {
+ return;
+ }
+ else if (node->prev == tcx->basin.left_node)
+ {
+ P2tOrientation o = p2t_orient2d (node->point, node->next->point, node->next->next->point);
+ if (o == CW)
+ {
+ return;
+ }
+ node = node->next;
+ }
+ else if (node->next == tcx->basin.right_node)
+ {
+ P2tOrientation o = p2t_orient2d (node->point, node->prev->point, node->prev->prev->point);
+ if (o == CCW)
+ {
+ return;
+ }
+ node = node->prev;
+ }
+ else
+ {
+ /* Continue with the neighbor node with lowest Y value */
+ if (node->prev->point->y < node->next->point->y)
+ {
+ node = node->prev;
+ }
+ else
+ {
+ node = node->next;
+ }
+ }
+
+ p2t_sweep_fill_basin_req (THIS, tcx, node);
+}
+
+gboolean
+p2t_sweep_is_shallow (P2tSweep *THIS, P2tSweepContext *tcx, P2tNode* node)
+{
+ double height;
+
+ if (tcx->basin.left_highest)
+ {
+ height = tcx->basin.left_node->point->y - node->point->y;
+ }
+ else
+ {
+ height = tcx->basin.right_node->point->y - node->point->y;
+ }
+
+ /* if shallow stop filling */
+ if (tcx->basin.width > height)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+p2t_sweep_fill_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node)
+{
+ if (tcx->edge_event.right)
+ {
+ p2t_sweep_fill_right_above_edge_event (THIS, tcx, edge, node);
+ }
+ else
+ {
+ p2t_sweep_fill_left_above_edge_event (THIS, tcx, edge, node);
+ }
+}
+
+void
+p2t_sweep_fill_right_above_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node)
+{
+ while (node->next->point->x < edge->p->x)
+ {
+ /* Check if next node is below the edge */
+ if (p2t_orient2d (edge->q, node->next->point, edge->p) == CCW)
+ {
+ p2t_sweep_fill_right_below_edge_event (THIS, tcx, edge, node);
+ }
+ else
+ {
+ node = node->next;
+ }
+ }
+}
+
+void
+p2t_sweep_fill_right_below_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node)
+{
+ if (node->point->x < edge->p->x)
+ {
+ if (p2t_orient2d (node->point, node->next->point, node->next->next->point) == CCW)
+ {
+ /* Concave */
+ p2t_sweep_fill_right_concave_edge_event (THIS, tcx, edge, node);
+ }
+ else
+ {
+ /* Convex */
+ p2t_sweep_fill_right_convex_edge_event (THIS, tcx, edge, node);
+ /* Retry this one */
+ p2t_sweep_fill_right_below_edge_event (THIS, tcx, edge, node);
+ }
+ }
+}
+
+void
+p2t_sweep_fill_right_concave_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node)
+{
+ p2t_sweep_fill (THIS, tcx, node->next);
+ if (node->next->point != edge->p)
+ {
+ /* Next above or below edge? */
+ if (p2t_orient2d (edge->q, node->next->point, edge->p) == CCW)
+ {
+ /* Below */
+ if (p2t_orient2d (node->point, node->next->point, node->next->next->point) == CCW)
+ {
+ /* Next is concave */
+ p2t_sweep_fill_right_concave_edge_event (THIS, tcx, edge, node);
+ }
+ else
+ {
+ /* Next is convex */
+ }
+ }
+ }
+
+}
+
+void
+p2t_sweep_fill_right_convex_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node)
+{
+ /* Next concave or convex? */
+ if (p2t_orient2d (node->next->point, node->next->next->point, node->next->next->next->point) == CCW)
+ {
+ /* Concave */
+ p2t_sweep_fill_right_concave_edge_event (THIS, tcx, edge, node->next);
+ }
+ else
+ {
+ /* Convex
+ * Next above or below edge? */
+ if (p2t_orient2d (edge->q, node->next->next->point, edge->p) == CCW)
+ {
+ /* Below */
+ p2t_sweep_fill_right_convex_edge_event (THIS, tcx, edge, node->next);
+ }
+ else
+ {
+ /* Above */
+ }
+ }
+}
+
+void
+p2t_sweep_fill_left_above_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node)
+{
+ while (node->prev->point->x > edge->p->x)
+ {
+ /* Check if next node is below the edge */
+ if (p2t_orient2d (edge->q, node->prev->point, edge->p) == CW)
+ {
+ p2t_sweep_fill_left_below_edge_event (THIS, tcx, edge, node);
+ }
+ else
+ {
+ node = node->prev;
+ }
+ }
+}
+
+void
+p2t_sweep_fill_left_below_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node)
+{
+ if (node->point->x > edge->p->x)
+ {
+ if (p2t_orient2d (node->point, node->prev->point, node->prev->prev->point) == CW)
+ {
+ /* Concave */
+ p2t_sweep_fill_left_concave_edge_event (THIS, tcx, edge, node);
+ }
+ else
+ {
+ /* Convex */
+ p2t_sweep_fill_left_convex_edge_event (THIS, tcx, edge, node);
+ /* Retry this one */
+ p2t_sweep_fill_left_below_edge_event (THIS, tcx, edge, node);
+ }
+ }
+}
+
+void
+p2t_sweep_fill_left_convex_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node)
+{
+ /* Next concave or convex? */
+ if (p2t_orient2d (node->prev->point, node->prev->prev->point, node->prev->prev->prev->point) == CW)
+ {
+ /* Concave */
+ p2t_sweep_fill_left_concave_edge_event (THIS, tcx, edge, node->prev);
+ }
+ else
+ {
+ /* Convex
+ * Next above or below edge? */
+ if (p2t_orient2d (edge->q, node->prev->prev->point, edge->p) == CW)
+ {
+ /* Below */
+ p2t_sweep_fill_left_convex_edge_event (THIS, tcx, edge, node->prev);
+ }
+ else
+ {
+ /* Above */
+ }
+ }
+}
+
+void
+p2t_sweep_fill_left_concave_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node)
+{
+ p2t_sweep_fill (THIS, tcx, node->prev);
+ if (node->prev->point != edge->p)
+ {
+ /* Next above or below edge? */
+ if (p2t_orient2d (edge->q, node->prev->point, edge->p) == CW)
+ {
+ /* Below */
+ if (p2t_orient2d (node->point, node->prev->point, node->prev->prev->point) == CW)
+ {
+ /* Next is concave */
+ p2t_sweep_fill_left_concave_edge_event (THIS, tcx, edge, node);
+ }
+ else
+ {
+ /* Next is convex */
+ }
+ }
+ }
+
+}
+
+void
+p2t_sweep_flip_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tPoint* ep, P2tPoint* eq, P2tTriangle* t, P2tPoint* p)
+{
+ P2tTriangle* ot = p2t_triangle_neighbor_across (t, p);
+ P2tPoint* op = p2t_triangle_opposite_point (ot, t, p);
+
+ if (ot == NULL)
+ {
+ /* If we want to integrate the fillEdgeEvent do it here
+ * With current implementation we should never get here
+ *throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle");
+ */
+ assert (0);
+ }
+
+ if (p2t_utils_in_scan_area (p, p2t_triangle_point_ccw (t, p), p2t_triangle_point_cw (t, p), op))
+ {
+ /* Lets rotate shared edge one vertex CW */
+ p2t_sweep_rotate_triangle_pair (THIS, t, p, ot, op);
+ p2t_sweepcontext_map_triangle_to_nodes (tcx, t);
+ p2t_sweepcontext_map_triangle_to_nodes (tcx, ot);
+
+ if (p == eq && op == ep)
+ {
+ if (p2t_point_equals (eq, tcx->edge_event.constrained_edge->q) && p2t_point_equals (ep, tcx->edge_event.constrained_edge->p))
+ {
+ p2t_triangle_mark_constrained_edge_pt_pt (t, ep, eq);
+ p2t_triangle_mark_constrained_edge_pt_pt (ot, ep, eq);
+ p2t_sweep_legalize (THIS, tcx, t);
+ p2t_sweep_legalize (THIS, tcx, ot);
+ }
+ else
+ {
+ /* XXX: I think one of the triangles should be legalized here? */
+ }
+ }
+ else
+ {
+ P2tOrientation o = p2t_orient2d (eq, op, ep);
+ t = p2t_sweep_next_flip_triangle (THIS, tcx, (int) o, t, ot, p, op);
+ p2t_sweep_flip_edge_event (THIS, tcx, ep, eq, t, p);
+ }
+ }
+ else
+ {
+ P2tPoint* newP = p2t_sweep_next_flip_point (THIS, ep, eq, ot, op);
+ p2t_sweep_flip_scan_edge_event (THIS, tcx, ep, eq, t, ot, newP);
+ p2t_sweep_edge_event_pt_pt_tr_pt (THIS, tcx, ep, eq, t, p);
+ }
+}
+
+P2tTriangle*
+p2t_sweep_next_flip_triangle (P2tSweep *THIS, P2tSweepContext *tcx, int o, P2tTriangle *t, P2tTriangle *ot, P2tPoint* p, P2tPoint* op)
+{
+ int edge_index;
+
+ if (o == CCW)
+ {
+ /* ot is not crossing edge after flip */
+ int edge_index = p2t_triangle_edge_index (ot, p, op);
+ ot->delaunay_edge[edge_index] = TRUE;
+ p2t_sweep_legalize (THIS, tcx, ot);
+ p2t_triangle_clear_delunay_edges (ot);
+ return t;
+ }
+
+ /* t is not crossing edge after flip */
+ edge_index = p2t_triangle_edge_index (t, p, op);
+
+ t->delaunay_edge[edge_index] = TRUE;
+ p2t_sweep_legalize (THIS, tcx, t);
+ p2t_triangle_clear_delunay_edges (t);
+ return ot;
+}
+
+P2tPoint*
+p2t_sweep_next_flip_point (P2tSweep *THIS, P2tPoint* ep, P2tPoint* eq, P2tTriangle *ot, P2tPoint* op)
+{
+ P2tOrientation o2d = p2t_orient2d (eq, op, ep);
+ if (o2d == CW)
+ {
+ /* Right */
+ return p2t_triangle_point_ccw (ot, op);
+ }
+ else if (o2d == CCW)
+ {
+ /* Left */
+ return p2t_triangle_point_cw (ot, op);
+ }
+ else
+ {
+ /*throw new RuntimeException("[Unsupported] Opposing point on constrained edge");*/
+ assert (0);
+ }
+}
+
+void
+p2t_sweep_flip_scan_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tPoint* ep, P2tPoint* eq, P2tTriangle *flip_triangle,
+ P2tTriangle *t, P2tPoint* p)
+{
+ P2tTriangle* ot = p2t_triangle_neighbor_across (t, p);
+ P2tPoint* op = p2t_triangle_opposite_point (ot, t, p);
+
+ if (p2t_triangle_neighbor_across (t, p) == NULL)
+ {
+ /* If we want to integrate the fillEdgeEvent do it here
+ * With current implementation we should never get here
+ *throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle");
+ */
+ assert (0);
+ }
+
+ if (p2t_utils_in_scan_area (eq, p2t_triangle_point_ccw (flip_triangle, eq), p2t_triangle_point_cw (flip_triangle, eq), op))
+ {
+ /* flip with new edge op->eq */
+ p2t_sweep_flip_edge_event (THIS, tcx, eq, op, ot, op);
+ /* TODO: Actually I just figured out that it should be possible to
+ * improve this by getting the next ot and op before the the above
+ * flip and continue the flipScanEdgeEvent here
+ * set new ot and op here and loop back to inScanArea test
+ * also need to set a new flip_triangle first
+ * Turns out at first glance that this is somewhat complicated
+ * so it will have to wait. */
+ }
+ else
+ {
+ P2tPoint* newP = p2t_sweep_next_flip_point (THIS, ep, eq, ot, op);
+ p2t_sweep_flip_scan_edge_event (THIS, tcx, ep, eq, flip_triangle, ot, newP);
+ }
+}
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep.h b/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep.h
new file mode 100644
index 0000000..7105fc4
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep.h
@@ -0,0 +1,282 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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.
+ */
+
+/**
+ * Sweep-line, Constrained Delauney Triangulation (CDT) See: Domiter, V. and
+ * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
+ * International Journal of Geographical Information Science
+ *
+ * "FlipScan" Constrained Edge Algorithm invented by Thomas ïhlïn, thahlen gmail com
+ */
+
+#ifndef __P2TC_P2T_SWEEP_H__
+#define __P2TC_P2T_SWEEP_H__
+
+#include "../common/poly2tri-private.h"
+#include "../common/shapes.h"
+
+struct Sweep_
+{
+/* private: */
+P2tNodePtrArray nodes_;
+
+};
+
+void p2t_sweep_init (P2tSweep* THIS);
+P2tSweep* p2t_sweep_new ();
+
+/**
+ * Destructor - clean up memory
+ */
+void p2t_sweep_destroy (P2tSweep* THIS);
+void p2t_sweep_free (P2tSweep* THIS);
+
+/**
+ * Triangulate
+ *
+ * @param tcx
+ */
+void p2t_sweep_triangulate (P2tSweep *THIS, P2tSweepContext *tcx);
+
+/**
+ * Start sweeping the Y-sorted point set from bottom to top
+ *
+ * @param tcx
+ */
+void p2t_sweep_sweep_points (P2tSweep *THIS, P2tSweepContext *tcx);
+
+/**
+ * Find closes node to the left of the new point and
+ * create a new triangle. If needed new holes and basins
+ * will be filled to.
+ *
+ * @param tcx
+ * @param point
+ * @return
+ */
+P2tNode* p2t_sweep_point_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tPoint* point);
+
+/**
+ *
+ *
+ * @param tcx
+ * @param edge
+ * @param node
+ */
+void p2t_sweep_edge_event_ed_n (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node);
+
+void p2t_sweep_edge_event_pt_pt_tr_pt (P2tSweep *THIS, P2tSweepContext *tcx, P2tPoint* ep, P2tPoint* eq, P2tTriangle* triangle, P2tPoint* point);
+
+/**
+ * Creates a new front triangle and legalize it
+ *
+ * @param tcx
+ * @param point
+ * @param node
+ * @return
+ */
+P2tNode* p2t_sweep_new_front_triangle (P2tSweep *THIS, P2tSweepContext *tcx, P2tPoint* point, P2tNode* node);
+
+/**
+ * Adds a triangle to the advancing front to fill a hole.
+ * @param tcx
+ * @param node - middle node, that is the bottom of the hole
+ */
+void p2t_sweep_fill (P2tSweep *THIS, P2tSweepContext *tcx, P2tNode* node);
+
+/**
+ * Returns true if triangle was legalized
+ */
+gboolean p2t_sweep_legalize (P2tSweep *THIS, P2tSweepContext *tcx, P2tTriangle *t);
+
+/**
+ * <b>Requirement</b>:<br>
+ * 1. a,b and c form a triangle.<br>
+ * 2. a and d is know to be on opposite side of bc<br>
+ * <pre>
+ * a
+ * +
+ * / \
+ * / \
+ * b/ \c
+ * +-------+
+ * / d \
+ * / \
+ * </pre>
+ * <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by
+ * a,b and c<br>
+ * d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW<br>
+ * This preknowledge gives us a way to optimize the incircle test
+ * @param a - triangle point, opposite d
+ * @param b - triangle point
+ * @param c - triangle point
+ * @param d - point opposite a
+ * @return true if d is inside circle, false if on circle edge
+ */
+gboolean p2t_sweep_incircle (P2tSweep *THIS, P2tPoint* pa, P2tPoint* pb, P2tPoint* pc, P2tPoint* pd);
+
+/**
+ * Rotates a triangle pair one vertex CW
+ *<pre>
+ * n2 n2
+ * P +-----+ P +-----+
+ * | t /| |\ t |
+ * | / | | \ |
+ * n1| / |n3 n1| \ |n3
+ * | / | after CW | \ |
+ * |/ oT | | oT \|
+ * +-----+ oP +-----+
+ * n4 n4
+ * </pre>
+ */
+void p2t_sweep_rotate_triangle_pair (P2tSweep *THIS, P2tTriangle *t, P2tPoint* p, P2tTriangle *ot, P2tPoint* op);
+
+/**
+ * Fills holes in the Advancing Front
+ *
+ *
+ * @param tcx
+ * @param n
+ */
+void p2t_sweep_fill_advancingfront (P2tSweep *THIS, P2tSweepContext *tcx, P2tNode* n);
+
+/* Decision-making about when to Fill hole.
+ * Contributed by ToolmakerSteve2 */
+gboolean p2t_sweep_large_hole_dont_fill (P2tSweep* THIS, P2tNode* node);
+gboolean p2t_sweep_angle_exceeds_90_degrees (P2tSweep* THIS, P2tPoint* origin, P2tPoint* pa, P2tPoint* pb);
+gboolean p2t_sweep_angle_exceeds_plus_90_degrees_or_is_negative (P2tSweep* THIS, P2tPoint* origin, P2tPoint* pa, P2tPoint* pb);
+gdouble p2t_sweep_angle (P2tSweep* THIS, P2tPoint* origin, P2tPoint* pa, P2tPoint* pb);
+
+/**
+ *
+ * @param node - middle node
+ * @return the angle between 3 front nodes
+ */
+double p2t_sweep_hole_angle (P2tSweep *THIS, P2tNode* node);
+
+/**
+ * The basin angle is decided against the horizontal line [1,0]
+ */
+double p2t_sweep_basin_angle (P2tSweep *THIS, P2tNode* node);
+
+/**
+ * Fills a basin that has formed on the Advancing Front to the right
+ * of given node.<br>
+ * First we decide a left,bottom and right node that forms the
+ * boundaries of the basin. Then we do a reqursive fill.
+ *
+ * @param tcx
+ * @param node - starting node, this or next node will be left node
+ */
+void p2t_sweep_fill_basin (P2tSweep *THIS, P2tSweepContext *tcx, P2tNode* node);
+
+/**
+ * Recursive algorithm to fill a Basin with triangles
+ *
+ * @param tcx
+ * @param node - bottom_node
+ * @param cnt - counter used to alternate on even and odd numbers
+ */
+void p2t_sweep_fill_basin_req (P2tSweep *THIS, P2tSweepContext *tcx, P2tNode* node);
+
+gboolean p2t_sweep_is_shallow (P2tSweep *THIS, P2tSweepContext *tcx, P2tNode* node);
+
+gboolean p2t_sweep_is_edge_side_of_triangle (P2tSweep *THIS, P2tTriangle *triangle, P2tPoint* ep, P2tPoint* eq);
+
+void p2t_sweep_fill_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node);
+
+void p2t_sweep_fill_right_above_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node);
+
+void p2t_sweep_fill_right_below_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node);
+
+void p2t_sweep_fill_right_concave_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node);
+
+void p2t_sweep_fill_right_convex_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node);
+
+void p2t_sweep_fill_left_above_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node);
+
+void p2t_sweep_fill_left_below_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node);
+
+void p2t_sweep_fill_left_concave_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node);
+
+void p2t_sweep_fill_left_convex_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tEdge* edge, P2tNode* node);
+
+void p2t_sweep_flip_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tPoint* ep, P2tPoint* eq, P2tTriangle* t, P2tPoint* p);
+
+/**
+ * After a flip we have two triangles and know that only one will still be
+ * intersecting the edge. So decide which to contiune with and legalize the other
+ *
+ * @param tcx
+ * @param o - should be the result of an orient2d( eq, op, ep )
+ * @param t - triangle 1
+ * @param ot - triangle 2
+ * @param p - a point shared by both triangles
+ * @param op - another point shared by both triangles
+ * @return returns the triangle still intersecting the edge
+ */
+P2tTriangle* p2t_sweep_next_flip_triangle (P2tSweep *THIS, P2tSweepContext *tcx, int o, P2tTriangle *t, P2tTriangle *ot, P2tPoint* p, P2tPoint* op);
+
+/**
+ * When we need to traverse from one triangle to the next we need
+ * the point in current triangle that is the opposite point to the next
+ * triangle.
+ *
+ * @param ep
+ * @param eq
+ * @param ot
+ * @param op
+ * @return
+ */
+P2tPoint* p2t_sweep_next_flip_point (P2tSweep *THIS, P2tPoint* ep, P2tPoint* eq, P2tTriangle *ot, P2tPoint* op);
+
+/**
+ * Scan part of the FlipScan algorithm<br>
+ * When a triangle pair isn't flippable we will scan for the next
+ * point that is inside the flip triangle scan area. When found
+ * we generate a new flipEdgeEvent
+ *
+ * @param tcx
+ * @param ep - last point on the edge we are traversing
+ * @param eq - first point on the edge we are traversing
+ * @param flipTriangle - the current triangle sharing the point eq with edge
+ * @param t
+ * @param p
+ */
+void p2t_sweep_flip_scan_edge_event (P2tSweep *THIS, P2tSweepContext *tcx, P2tPoint* ep, P2tPoint* eq, P2tTriangle *flip_triangle, P2tTriangle *t, P2tPoint* p);
+
+void p2t_sweep_finalization_polygon (P2tSweep *THIS, P2tSweepContext *tcx);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep_context.c b/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep_context.c
new file mode 100644
index 0000000..9ed52d5
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep_context.c
@@ -0,0 +1,319 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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 "sweep_context.h"
+#include "advancing_front.h"
+
+void
+p2t_sweepcontext_basin_init (P2tSweepContextBasin* THIS)
+{
+ p2t_sweepcontext_basin_clear (THIS);
+}
+
+void
+p2t_sweepcontext_basin_clear (P2tSweepContextBasin* THIS)
+{
+ THIS->left_node = NULL;
+ THIS->bottom_node = NULL;
+ THIS->right_node = NULL;
+ THIS->width = 0.0;
+ THIS->left_highest = FALSE;
+}
+
+void
+p2t_sweepcontext_edgeevent_init (P2tSweepContextEdgeEvent* THIS)
+{
+ THIS->constrained_edge = NULL;
+ THIS->right = FALSE;
+}
+
+void
+p2t_sweepcontext_init (P2tSweepContext* THIS, P2tPointPtrArray polyline)
+{
+ int i;
+ THIS->edge_list = g_ptr_array_new ();
+ THIS->triangles_ = g_ptr_array_new ();
+ THIS->map_ = NULL;
+
+ p2t_sweepcontext_basin_init (&THIS->basin);
+ p2t_sweepcontext_edgeevent_init (&THIS->edge_event);
+
+ THIS->points_ = g_ptr_array_sized_new (polyline->len);
+ for (i = 0; i < polyline->len; i++)
+ g_ptr_array_add (THIS->points_, point_index (polyline, i));
+
+ p2t_sweepcontext_init_edges (THIS, THIS->points_);
+}
+
+P2tSweepContext*
+p2t_sweepcontext_new (P2tPointPtrArray polyline)
+{
+ P2tSweepContext* THIS = g_new (P2tSweepContext, 1);
+ p2t_sweepcontext_init (THIS, polyline);
+ return THIS;
+}
+
+void
+p2t_sweepcontext_destroy (P2tSweepContext* THIS)
+{
+ GList* iter;
+ int i;
+ /* Clean up memory */
+
+ p2t_point_free (THIS->head_);
+ p2t_point_free (THIS->tail_);
+ p2t_advancingfront_free (THIS->front_);
+ p2t_node_free (THIS->af_head_);
+ p2t_node_free (THIS->af_middle_);
+ p2t_node_free (THIS->af_tail_);
+
+ g_ptr_array_free (THIS->points_, TRUE);
+ g_ptr_array_free (THIS->triangles_, TRUE);
+
+ for (iter = g_list_first (THIS->map_); iter != NULL; iter = g_list_next (iter))
+ {
+ P2tTriangle* ptr = triangle_val (iter);
+ g_free (ptr);
+ }
+
+ g_list_free (THIS->map_);
+
+ for (i = 0; i < THIS->edge_list->len; i++)
+ {
+ p2t_edge_free (edge_index (THIS->edge_list, i));
+ }
+
+ g_ptr_array_free (THIS->edge_list, TRUE);
+
+}
+
+void
+p2t_sweepcontext_delete (P2tSweepContext* THIS)
+{
+ p2t_sweepcontext_destroy (THIS);
+ g_free(THIS);
+}
+
+void
+p2t_sweepcontext_add_hole (P2tSweepContext *THIS, P2tPointPtrArray polyline)
+{
+ int i;
+ p2t_sweepcontext_init_edges (THIS, polyline);
+ for (i = 0; i < polyline->len; i++)
+ {
+ g_ptr_array_add (THIS->points_, point_index (polyline, i));
+ }
+}
+
+void
+p2t_sweepcontext_add_point (P2tSweepContext *THIS, P2tPoint* point)
+{
+ g_ptr_array_add (THIS->points_, point);
+}
+
+P2tTrianglePtrArray
+p2t_sweepcontext_get_triangles (P2tSweepContext *THIS)
+{
+ return THIS->triangles_;
+}
+
+P2tTrianglePtrList
+p2t_sweepcontext_get_map (P2tSweepContext *THIS)
+{
+ return THIS->map_;
+}
+
+void
+p2t_sweepcontext_init_triangulation (P2tSweepContext *THIS)
+{
+ int i;
+ double xmax = point_index (THIS->points_, 0)->x, xmin = point_index (THIS->points_, 0)->x;
+ double ymax = point_index (THIS->points_, 0)->y, ymin = point_index (THIS->points_, 0)->y;
+ double dx, dy;
+
+ /* Calculate bounds. */
+ for (i = 0; i < THIS->points_->len; i++)
+ {
+ P2tPoint* p = point_index (THIS->points_, i);
+ if (p->x > xmax)
+ xmax = p->x;
+ if (p->x < xmin)
+ xmin = p->x;
+ if (p->y > ymax)
+ ymax = p->y;
+ if (p->y < ymin)
+ ymin = p->y;
+ }
+
+ dx = kAlpha * (xmax - xmin);
+ dy = kAlpha * (ymax - ymin);
+ THIS->head_ = p2t_point_new_dd (xmax + dx, ymin - dy);
+ THIS->tail_ = p2t_point_new_dd (xmin - dx, ymin - dy);
+
+ /* Sort points along y-axis */
+ g_ptr_array_sort (THIS->points_, p2t_point_cmp);
+}
+
+void
+p2t_sweepcontext_init_edges (P2tSweepContext *THIS, P2tPointPtrArray polyline)
+{
+ int i;
+ int num_points = polyline->len;
+ g_ptr_array_set_size (THIS->edge_list, THIS->edge_list->len + num_points); /* C-OPTIMIZATION */
+ for (i = 0; i < num_points; i++)
+ {
+ int j = i < num_points - 1 ? i + 1 : 0;
+ g_ptr_array_add (THIS->edge_list, p2t_edge_new (point_index (polyline, i), point_index (polyline, j)));
+ }
+}
+
+P2tPoint*
+p2t_sweepcontext_get_point (P2tSweepContext *THIS, const int index)
+{
+ return point_index (THIS->points_, index);
+}
+
+void
+p2t_sweepcontext_add_to_map (P2tSweepContext *THIS, P2tTriangle* triangle)
+{
+ THIS->map_ = g_list_append (THIS->map_, triangle);
+}
+
+P2tNode*
+p2t_sweepcontext_locate_node (P2tSweepContext *THIS, P2tPoint* point)
+{
+ /* TODO implement search tree */
+ return p2t_advancingfront_locate_node (THIS->front_, point->x);
+}
+
+void
+p2t_sweepcontext_create_advancingfront (P2tSweepContext *THIS, P2tNodePtrArray nodes)
+{
+ /* Initial triangle */
+ P2tTriangle* triangle = p2t_triangle_new (point_index (THIS->points_, 0), THIS->tail_, THIS->head_);
+
+ THIS->map_ = g_list_append (THIS->map_, triangle);
+
+ THIS->af_head_ = p2t_node_new_pt_tr (p2t_triangle_get_point (triangle, 1), triangle);
+ THIS->af_middle_ = p2t_node_new_pt_tr (p2t_triangle_get_point (triangle, 0), triangle);
+ THIS->af_tail_ = p2t_node_new_pt (p2t_triangle_get_point (triangle, 2));
+ THIS->front_ = p2t_advancingfront_new (THIS->af_head_, THIS->af_tail_);
+
+ /* TODO: More intuitiv if head is middles next and not previous?
+ * so swap head and tail */
+ THIS->af_head_->next = THIS->af_middle_;
+ THIS->af_middle_->next = THIS->af_tail_;
+ THIS->af_middle_->prev = THIS->af_head_;
+ THIS->af_tail_->prev = THIS->af_middle_;
+}
+
+void
+p2t_sweepcontext_remove_node (P2tSweepContext *THIS, P2tNode* node)
+{
+ g_free (node);
+}
+
+void
+p2t_sweepcontext_map_triangle_to_nodes (P2tSweepContext *THIS, P2tTriangle* t)
+{
+ int i;
+ for (i = 0; i < 3; i++)
+ {
+ if (!p2t_triangle_get_neighbor (t, i))
+ {
+ P2tNode* n = p2t_advancingfront_locate_point (THIS->front_, p2t_triangle_point_cw (t, p2t_triangle_get_point (t, i)));
+ if (n)
+ n->triangle = t;
+ }
+ }
+}
+
+void
+p2t_sweepcontext_remove_from_map (P2tSweepContext *THIS, P2tTriangle* triangle)
+{
+ THIS->map_ = g_list_remove (THIS->map_, triangle);
+}
+
+void
+p2t_sweepcontext_mesh_clean (P2tSweepContext *THIS, P2tTriangle* triangle)
+{
+ int i;
+ if (triangle != NULL && !p2t_triangle_is_interior (triangle))
+ {
+ p2t_triangle_is_interior_b (triangle, TRUE);
+ g_ptr_array_add (THIS->triangles_, triangle);
+ for (i = 0; i < 3; i++)
+ {
+ if (!triangle->constrained_edge[i])
+ p2t_sweepcontext_mesh_clean (THIS, p2t_triangle_get_neighbor (triangle, i));
+ }
+ }
+}
+
+P2tAdvancingFront*
+p2t_sweepcontext_front (P2tSweepContext *THIS)
+{
+ return THIS->front_;
+}
+
+int
+p2t_sweepcontext_point_count (P2tSweepContext *THIS)
+{
+ return THIS->points_->len;
+}
+
+void
+p2t_sweepcontext_set_head (P2tSweepContext *THIS, P2tPoint* p1)
+{
+ THIS->head_ = p1;
+}
+
+P2tPoint*
+p2t_sweepcontext_head (P2tSweepContext *THIS)
+{
+ return THIS->head_;
+}
+
+void
+p2t_sweepcontext_set_tail (P2tSweepContext *THIS, P2tPoint* p1)
+{
+ THIS->tail_ = p1;
+}
+
+P2tPoint*
+p2t_sweepcontext_tail (P2tSweepContext *THIS)
+{
+ return THIS->tail_;
+}
diff --git a/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep_context.h b/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep_context.h
new file mode 100644
index 0000000..2c9748f
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/p2t/sweep/sweep_context.h
@@ -0,0 +1,137 @@
+/*
+ * This file is a part of the C port of the Poly2Tri library
+ * Porting to C done by (c) Barak Itkin <lightningismyname gmail com>
+ * http://code.google.com/p/poly2tri-c/
+ *
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * 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_P2T_SWEEP_CONTEXT_H__
+#define __P2TC_P2T_SWEEP_CONTEXT_H__
+
+#include "../common/poly2tri-private.h"
+#include "../common/shapes.h"
+#include "advancing_front.h"
+
+/* Inital triangle factor, seed triangle will extend 30% of
+ * PointSet width to both left and right. */
+#define kAlpha 0.3
+
+struct P2tSweepContextBasin_
+{
+ P2tNode* left_node;
+ P2tNode* bottom_node;
+ P2tNode* right_node;
+ double width;
+ gboolean left_highest;
+};
+
+void p2t_sweepcontext_basin_init (P2tSweepContextBasin* THIS);
+void p2t_sweepcontext_basin_clear (P2tSweepContextBasin* THIS);
+
+struct P2tSweepContextEdgeEvent_
+{
+ P2tEdge* constrained_edge;
+ gboolean right;
+};
+
+void p2t_sweepcontext_edgeevent_init (P2tSweepContextEdgeEvent* THIS);
+
+struct SweepContext_
+{
+ P2tEdgePtrArray edge_list;
+
+ P2tSweepContextBasin basin;
+ P2tSweepContextEdgeEvent edge_event;
+
+ P2tTrianglePtrArray triangles_;
+ P2tTrianglePtrList map_;
+ P2tPointPtrArray points_;
+
+ /** Advancing front */
+ P2tAdvancingFront* front_;
+ /** head point used with advancing front */
+ P2tPoint* head_;
+ /** tail point used with advancing front */
+ P2tPoint* tail_;
+
+ P2tNode *af_head_, *af_middle_, *af_tail_;
+};
+
+/** Constructor */
+void p2t_sweepcontext_init (P2tSweepContext* THIS, P2tPointPtrArray polyline);
+P2tSweepContext* p2t_sweepcontext_new (P2tPointPtrArray polyline);
+
+/** Destructor */
+void p2t_sweepcontext_destroy (P2tSweepContext* THIS);
+void p2t_sweepcontext_delete (P2tSweepContext* THIS);
+
+void p2t_sweepcontext_set_head (P2tSweepContext *THIS, P2tPoint* p1);
+
+P2tPoint* p2t_sweepcontext_head (P2tSweepContext *THIS);
+
+void p2t_sweepcontext_set_tail (P2tSweepContext *THIS, P2tPoint* p1);
+
+P2tPoint* p2t_sweepcontext_tail (P2tSweepContext *THIS);
+
+int p2t_sweepcontext_point_count (P2tSweepContext *THIS);
+
+P2tNode* p2t_sweepcontext_locate_node (P2tSweepContext *THIS, P2tPoint* point);
+
+void p2t_sweepcontext_remove_node (P2tSweepContext *THIS, P2tNode* node);
+
+void p2t_sweepcontext_create_advancingfront (P2tSweepContext *THIS, P2tNodePtrArray nodes);
+
+/** Try to map a node to all sides of this triangle that don't have a neighbor */
+void p2t_sweepcontext_map_triangle_to_nodes (P2tSweepContext *THIS, P2tTriangle* t);
+
+void p2t_sweepcontext_add_to_map (P2tSweepContext *THIS, P2tTriangle* triangle);
+
+P2tPoint* p2t_sweepcontext_get_point (P2tSweepContext *THIS, const int index);
+
+P2tPoint* SweepContext_GetPoints (P2tSweepContext *THIS);
+
+void p2t_sweepcontext_remove_from_map (P2tSweepContext *THIS, P2tTriangle* triangle);
+
+void p2t_sweepcontext_add_hole (P2tSweepContext *THIS, P2tPointPtrArray polyline);
+
+void p2t_sweepcontext_add_point (P2tSweepContext *THIS, P2tPoint* point);
+
+P2tAdvancingFront* p2t_sweepcontext_front (P2tSweepContext *THIS);
+
+void p2t_sweepcontext_mesh_clean (P2tSweepContext *THIS, P2tTriangle* triangle);
+
+P2tTrianglePtrArray p2t_sweepcontext_get_triangles (P2tSweepContext *THIS);
+P2tTrianglePtrList p2t_sweepcontext_get_map (P2tSweepContext *THIS);
+
+void p2t_sweepcontext_init_triangulation (P2tSweepContext *THIS);
+void p2t_sweepcontext_init_edges (P2tSweepContext *THIS, P2tPointPtrArray polyline);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/Makefile.am b/libs/poly2tri-c/poly2tri-c/refine/Makefile.am
new file mode 100644
index 0000000..8701b0d
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/Makefile.am
@@ -0,0 +1,6 @@
+noinst_LTLIBRARIES = libp2tc-refine.la
+
+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 mesh-action.c mesh-action.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 mesh-action.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/libs/poly2tri-c/poly2tri-c/refine/bounded-line.c b/libs/poly2tri-c/poly2tri-c/refine/bounded-line.c
new file mode 100644
index 0000000..ad08580
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/bounded-line.c
@@ -0,0 +1,84 @@
+/*
+ * 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 "bounded-line.h"
+
+P2trBoundedLine*
+p2tr_bounded_line_new (const P2trVector2 *start,
+ const P2trVector2 *end)
+{
+ P2trBoundedLine* line = g_slice_new (P2trBoundedLine);
+ p2tr_bounded_line_init (line, start, end);
+ return line;
+}
+
+void
+p2tr_bounded_line_init (P2trBoundedLine *line,
+ const P2trVector2 *start,
+ const P2trVector2 *end)
+{
+ /* Traditional line Equation:
+ * y - mx - n = 0 <==> y = mx + n
+ * Slope Equation:
+ * m = dy / dx
+ * Slope + Traditional:
+ * dx * y - dy * x - dx * n = 0
+ * And the remaining part can be found as
+ * dx * y0 - dy * x0 = dx * n
+ * So the final equation is:
+ * dx * y - dy * x - (dx * y0 - dy * x0) = 0
+ */
+ gdouble dx = end->x - start->x;
+ gdouble dy = end->y - start->y;
+
+ gdouble dxXn = start->y * dx - start->x * dy;
+
+ p2tr_line_init(&line->infinite, -dy, dx, -dxXn);
+
+ p2tr_vector2_copy(&line->start, start);
+ p2tr_vector2_copy(&line->end, end);
+}
+
+gboolean
+p2tr_bounded_line_intersect (const P2trBoundedLine *l1,
+ const P2trBoundedLine *l2)
+{
+ return p2tr_line_different_sides (&l1->infinite, &l2->start, &l2->end)
+ && p2tr_line_different_sides (&l2->infinite, &l1->start, &l1->end);
+}
+
+void
+p2tr_bounded_line_free (P2trBoundedLine *line)
+{
+ g_slice_free (P2trBoundedLine, line);
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/bounded-line.h b/libs/poly2tri-c/poly2tri-c/refine/bounded-line.h
new file mode 100644
index 0000000..577259d
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/bounded-line.h
@@ -0,0 +1,58 @@
+/*
+ * 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_BOUNDED_LINE_H__
+#define __P2TC_REFINE_BOUNDED_LINE_H__
+
+#include <glib.h>
+#include "vector2.h"
+#include "line.h"
+
+typedef struct
+{
+ P2trLine infinite;
+ P2trVector2 start, end;
+} P2trBoundedLine;
+
+P2trBoundedLine* p2tr_bounded_line_new (const P2trVector2 *start,
+ const P2trVector2 *end);
+
+void p2tr_bounded_line_init (P2trBoundedLine *line,
+ const P2trVector2 *start,
+ const P2trVector2 *end);
+
+gboolean p2tr_bounded_line_intersect (const P2trBoundedLine *l1,
+ const P2trBoundedLine *l2);
+
+void p2tr_bounded_line_free (P2trBoundedLine *line);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/cdt-flipfix.c b/libs/poly2tri-c/poly2tri-c/refine/cdt-flipfix.c
new file mode 100644
index 0000000..3efeb09
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/cdt-flipfix.c
@@ -0,0 +1,159 @@
+/*
+ * 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);
+
+/* 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,
+ P2trVEdgeSet *candidates)
+{
+ P2trEdge *edge;
+ P2trVEdge *vedge;
+
+ while (p2tr_vedge_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_vedge_set_add (candidates, p2tr_point_get_edge_to (A, C1, TRUE));
+ p2tr_vedge_set_add (candidates, p2tr_point_get_edge_to (A, C2, TRUE));
+ p2tr_vedge_set_add (candidates, p2tr_point_get_edge_to (B, C1, TRUE));
+ p2tr_vedge_set_add (candidates, p2tr_point_get_edge_to (B, C2, TRUE));
+ 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;
+
+ /* 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;
+
+ 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);
+
+ 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;
+}
+
+
+
diff --git a/libs/poly2tri-c/poly2tri-c/refine/cdt-flipfix.h b/libs/poly2tri-c/poly2tri-c/refine/cdt-flipfix.h
new file mode 100644
index 0000000..dad11b2
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/cdt-flipfix.h
@@ -0,0 +1,49 @@
+/*
+ * 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"
+
+/**
+ * Flip-Fix all the virtual edges inside the given set
+ */
+void p2tr_cdt_flip_fix (P2trCDT *self,
+ P2trVEdgeSet *candidates);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/cdt.c b/libs/poly2tri-c/poly2tri-c/refine/cdt.c
new file mode 100644
index 0000000..7dc1d11
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/cdt.c
@@ -0,0 +1,491 @@
+/*
+ * 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 <stdarg.h>
+#include <glib.h>
+
+#include "point.h"
+#include "edge.h"
+#include "triangle.h"
+
+#include "cdt.h"
+#include "visibility.h"
+#include "cdt-flipfix.h"
+
+static gboolean p2tr_cdt_visible_from_tri (P2trCDT *self,
+ P2trTriangle *tri,
+ P2trVector2 *p);
+
+static gboolean p2tr_cdt_has_empty_circum_circle (P2trCDT *self,
+ P2trTriangle *tri);
+
+static P2trHashSet* p2tr_cdt_triangulate_fan (P2trCDT *self,
+ P2trPoint *center,
+ GList *edge_pts);
+
+void
+p2tr_cdt_validate_unused (P2trCDT* self)
+{
+ P2trEdge *ed;
+ P2trTriangle *tri;
+ P2trHashSetIter iter;
+
+ p2tr_hash_set_iter_init (&iter, self->mesh->edges);
+ while (p2tr_hash_set_iter_next (&iter, (gpointer*)&ed))
+ {
+ g_assert (ed->mirror != NULL);
+ g_assert (! p2tr_edge_is_removed (ed));
+ }
+
+ p2tr_hash_set_iter_init (&iter, self->mesh->triangles);
+ while (p2tr_hash_set_iter_next (&iter, (gpointer*)&tri))
+ g_assert (! p2tr_triangle_is_removed (tri));
+}
+
+P2trCDT*
+p2tr_cdt_new (P2tCDT *cdt)
+{
+ P2tTrianglePtrArray cdt_tris = p2t_cdt_get_triangles (cdt);
+ GHashTable *point_map = g_hash_table_new (g_direct_hash, g_direct_equal);
+ P2trCDT *rmesh = g_slice_new (P2trCDT);
+ GHashTableIter iter;
+ P2trPoint *pt_iter = NULL;
+
+ P2trVEdgeSet *new_edges = p2tr_vedge_set_new ();
+
+ gint i, j;
+
+ rmesh->mesh = p2tr_mesh_new ();
+ rmesh->outline = p2tr_pslg_new ();
+
+ /* First iteration over the CDT - create all the points */
+ for (i = 0; i < cdt_tris->len; i++)
+ {
+ P2tTriangle *cdt_tri = triangle_index (cdt_tris, i);
+ for (j = 0; j < 3; j++)
+ {
+ P2tPoint *cdt_pt = p2t_triangle_get_point(cdt_tri, j);
+ P2trPoint *new_pt = (P2trPoint*) g_hash_table_lookup (point_map, cdt_pt);
+
+ if (new_pt == NULL)
+ {
+ new_pt = p2tr_mesh_new_point2 (rmesh->mesh, cdt_pt->x, cdt_pt->y);
+ g_hash_table_insert (point_map, cdt_pt, new_pt);
+ }
+ }
+ }
+
+ /* Second iteration over the CDT - create all the edges and find the
+ * outline */
+ for (i = 0; i < cdt_tris->len; i++)
+ {
+ P2tTriangle *cdt_tri = triangle_index (cdt_tris, i);
+
+ for (j = 0; j < 3; j++)
+ {
+ P2tPoint *start = p2t_triangle_get_point (cdt_tri, j);
+ P2tPoint *end = p2t_triangle_get_point (cdt_tri, (j + 1) % 3);
+ int edge_index = p2t_triangle_edge_index (cdt_tri, start, end);
+
+ P2trPoint *start_new = (P2trPoint*) g_hash_table_lookup (point_map, start);
+ P2trPoint *end_new = (P2trPoint*) g_hash_table_lookup (point_map, end);
+
+ if (! p2tr_point_has_edge_to (start_new, end_new))
+ {
+ gboolean constrained = cdt_tri->constrained_edge[edge_index]
+ || cdt_tri->neighbors_[edge_index] == NULL;
+ P2trEdge *edge = p2tr_mesh_new_edge (rmesh->mesh, start_new, end_new, constrained);
+
+ /* If the edge is constrained, we should add it to the
+ * outline */
+ if (constrained)
+ p2tr_pslg_add_new_line(rmesh->outline, &start_new->c,
+ &end_new->c);
+
+ /* We only wanted to create the edge now. We will use it
+ * later */
+ p2tr_vedge_set_add (new_edges, edge);
+ }
+ }
+ }
+
+ /* Third iteration over the CDT - create all the triangles */
+ for (i = 0; i < cdt_tris->len; i++)
+ {
+ P2tTriangle *cdt_tri = triangle_index (cdt_tris, i);
+
+ P2trPoint *pt1 = (P2trPoint*) g_hash_table_lookup (point_map, p2t_triangle_get_point (cdt_tri, 0));
+ P2trPoint *pt2 = (P2trPoint*) g_hash_table_lookup (point_map, p2t_triangle_get_point (cdt_tri, 1));
+ P2trPoint *pt3 = (P2trPoint*) g_hash_table_lookup (point_map, p2t_triangle_get_point (cdt_tri, 2));
+
+ P2trTriangle *new_tri = p2tr_mesh_new_triangle (rmesh->mesh,
+ p2tr_point_get_edge_to(pt1, pt2, FALSE),
+ p2tr_point_get_edge_to(pt2, pt3, FALSE),
+ p2tr_point_get_edge_to(pt3, pt1, FALSE));
+
+ /* We won't do any usage of the triangle, so just unref it */
+ p2tr_triangle_unref (new_tri);
+ }
+
+ /* And do an extra flip fix */
+ p2tr_cdt_flip_fix (rmesh, new_edges);
+
+ p2tr_vedge_set_free (new_edges);
+
+ /* Now finally unref the points we added into the map */
+ g_hash_table_iter_init (&iter, point_map);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer*)&pt_iter))
+ p2tr_point_unref (pt_iter);
+ g_hash_table_destroy (point_map);
+
+ return rmesh;
+}
+
+void
+p2tr_cdt_free (P2trCDT *self)
+{
+ p2tr_cdt_free_full (self, TRUE);
+}
+
+void
+p2tr_cdt_free_full (P2trCDT* self, gboolean clear_mesh)
+{
+ p2tr_pslg_free (self->outline);
+ if (clear_mesh)
+ p2tr_mesh_clear (self->mesh);
+ p2tr_mesh_unref (self->mesh);
+
+ g_slice_free (P2trCDT, self);
+}
+
+void
+p2tr_cdt_validate_edges (P2trCDT *self)
+{
+ P2trHashSetIter iter;
+ P2trEdge *e;
+
+ p2tr_hash_set_iter_init (&iter, self->mesh->edges);
+ while (p2tr_hash_set_iter_next (&iter, (gpointer*)&e))
+ {
+ if (! e->constrained && e->tri == NULL)
+ p2tr_exception_geometric ("Found a non constrained edge without a triangle");
+
+ if (e->tri != NULL)
+ {
+ gboolean found = FALSE;
+ gint i = 0;
+
+ for (i = 0; i < 3; i++)
+ if (e->tri->edges[i] == e)
+ {
+ found = TRUE;
+ break;
+ }
+
+ if (! found)
+ p2tr_exception_geometric ("An edge has a triangle to which it does not belong!");
+ }
+ }
+}
+
+gboolean
+p2tr_cdt_visible_from_edge (P2trCDT *self,
+ P2trEdge *e,
+ P2trVector2 *p)
+{
+ P2trBoundedLine line;
+
+ p2tr_bounded_line_init (&line, &P2TR_EDGE_START(e)->c, &e->end->c);
+
+ return p2tr_visibility_is_visible_from_edges (self->outline, p, &line, 1);
+}
+
+static gboolean
+p2tr_cdt_visible_from_tri (P2trCDT *self,
+ P2trTriangle *tri,
+ P2trVector2 *p)
+{
+ P2trBoundedLine lines[3];
+ gint i;
+
+ for (i = 0; i < 3; i++)
+ p2tr_bounded_line_init (&lines[i],
+ &P2TR_EDGE_START(tri->edges[i])->c,
+ &tri->edges[i]->end->c);
+
+ return p2tr_visibility_is_visible_from_edges (self->outline, p, lines, 3);
+}
+
+static gboolean
+p2tr_cdt_has_empty_circum_circle (P2trCDT *self,
+ P2trTriangle *tri)
+{
+ P2trCircle circum;
+ P2trPoint *p;
+ P2trHashSetIter iter;
+
+ p2tr_triangle_get_circum_circle (tri, &circum);
+
+ p2tr_hash_set_iter_init (&iter, self->mesh->points);
+ while (p2tr_hash_set_iter_next (&iter, (gpointer*)&p))
+ {
+ /** TODO: FIXME - is a point on a constrained edge really not a
+ * problem?! */
+ if (p2tr_point_has_constrained_edge (p)
+ /* The points of a triangle can't violate its own empty
+ * circumcircle property */
+ || p == tri->edges[0]->end
+ || p == tri->edges[1]->end
+ || p == tri->edges[2]->end)
+ continue;
+
+ if (! p2tr_circle_test_point_outside(&circum, &p->c)
+ && p2tr_cdt_visible_from_tri (self, tri, &p->c))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void
+p2tr_cdt_validate_cdt (P2trCDT *self)
+{
+ P2trHashSetIter iter;
+ P2trTriangle *tri;
+
+ p2tr_hash_set_iter_init (&iter, self->mesh->triangles);
+ while (p2tr_hash_set_iter_next (&iter, (gpointer*)&tri))
+ if (! p2tr_cdt_has_empty_circum_circle(self, tri))
+ p2tr_exception_geometric ("Not a CDT!");
+}
+
+P2trPoint*
+p2tr_cdt_insert_point (P2trCDT *self,
+ const P2trVector2 *pc,
+ P2trTriangle *point_location_guess)
+{
+ P2trTriangle *tri;
+ P2trPoint *pt;
+ gboolean inserted = FALSE;
+ gint i;
+
+ P2TR_CDT_VALIDATE_UNUSED (self);
+
+ if (point_location_guess == NULL)
+ tri = p2tr_mesh_find_point (self->mesh, pc);
+ else
+ tri = p2tr_mesh_find_point_local (self->mesh, pc, point_location_guess);
+
+ if (tri == NULL)
+ p2tr_exception_geometric ("Tried to add point outside of domain!");
+
+ pt = p2tr_mesh_new_point (self->mesh, pc);
+
+ /* If the point falls on a line, we should split the line */
+ for (i = 0; i < 3; i++)
+ {
+ P2trEdge *edge = tri->edges[i];
+ if (p2tr_math_orient2d (& P2TR_EDGE_START(edge)->c,
+ &edge->end->c, pc) == P2TR_ORIENTATION_LINEAR)
+ {
+ GList *parts = p2tr_cdt_split_edge (self, edge, pt), *eIter;
+ for (eIter = parts; eIter != NULL; eIter = eIter->next)
+ p2tr_edge_unref ((P2trEdge*)eIter->data);
+ inserted = TRUE;
+ break;
+ }
+ }
+
+ if (! inserted)
+ /* If we reached this line, then the point is inside the triangle */
+ p2tr_cdt_insert_point_into_triangle (self, pt, tri);
+
+ /* We no longer need the triangle */
+ p2tr_triangle_unref (tri);
+
+ P2TR_CDT_VALIDATE_UNUSED (self);
+ return pt;
+}
+
+/** Insert a point into a triangle. This function assumes the point is
+ * inside the triangle - not on one of its edges and not outside of it.
+ */
+void
+p2tr_cdt_insert_point_into_triangle (P2trCDT *self,
+ P2trPoint *P,
+ P2trTriangle *tri)
+{
+ P2trVEdgeSet *flip_candidates = p2tr_vedge_set_new ();
+
+ P2trPoint *A = tri->edges[0]->end;
+ P2trPoint *B = tri->edges[1]->end;
+ P2trPoint *C = tri->edges[2]->end;
+
+ P2trEdge *CA = tri->edges[0];
+ P2trEdge *AB = tri->edges[1];
+ P2trEdge *BC = tri->edges[2];
+
+ P2trEdge *AP, *BP, *CP;
+
+ p2tr_triangle_remove (tri);
+
+ AP = p2tr_mesh_new_edge (self->mesh, A, P, FALSE);
+ BP = p2tr_mesh_new_edge (self->mesh, B, P, FALSE);
+ CP = p2tr_mesh_new_edge (self->mesh, C, P, FALSE);
+
+ p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh, AB, BP, AP->mirror));
+ 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_vedge_set_add (flip_candidates, CP);
+ p2tr_vedge_set_add (flip_candidates, AP);
+ p2tr_vedge_set_add (flip_candidates, BP);
+
+ p2tr_vedge_set_add (flip_candidates, p2tr_edge_ref (CA));
+ p2tr_vedge_set_add (flip_candidates, p2tr_edge_ref (AB));
+ p2tr_vedge_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_vedge_set_free (flip_candidates);
+}
+
+/**
+ * Triangulate a polygon by creating edges to a center point.
+ * 1. If there is a NULL point in the polygon, two triangles are not
+ * created (these are the two that would have used it)
+ * 2. THE RETURNED EDGES MUST BE UNREFFED!
+ */
+static P2trVEdgeSet*
+p2tr_cdt_triangulate_fan (P2trCDT *self,
+ P2trPoint *center,
+ GList *edge_pts)
+{
+ P2trVEdgeSet* fan_edges = p2tr_vedge_set_new ();
+ GList *iter;
+
+ /* We can not triangulate unless at least two points are given */
+ if (edge_pts == NULL || edge_pts->next == NULL)
+ {
+ p2tr_exception_programmatic ("Not enough points to triangulate as"
+ " a star!");
+ }
+
+ for (iter = edge_pts; iter != NULL; iter = iter->next)
+ {
+ P2trPoint *A = (P2trPoint*) iter->data;
+ P2trPoint *B = (P2trPoint*) g_list_cyclic_next (edge_pts, iter)->data;
+ P2trEdge *AB, *BC, *CA;
+
+ if (A == NULL || B == NULL)
+ continue;
+
+ AB = p2tr_point_get_edge_to (A, B, TRUE);
+ BC = p2tr_mesh_new_or_existing_edge (self->mesh, B, center, FALSE);
+ CA = p2tr_mesh_new_or_existing_edge (self->mesh, center, A, FALSE);
+
+ p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh, AB, BC, CA));
+
+ p2tr_vedge_set_add (fan_edges, CA);
+ p2tr_vedge_set_add (fan_edges, BC);
+ p2tr_vedge_set_add (fan_edges, AB);
+ }
+
+ return fan_edges;
+}
+
+GList*
+p2tr_cdt_split_edge (P2trCDT *self,
+ P2trEdge *e,
+ P2trPoint *C)
+{
+ /* W
+ * /|\
+ * / | \
+ * / | \ E.Mirror.Tri: YXW
+ * X*---*---*Y E: X->Y
+ * \ |C / E.Tri: XYV
+ * \ | /
+ * \|/
+ * V
+ */
+ P2trPoint *X = P2TR_EDGE_START (e), *Y = e->end;
+ P2trPoint *V = (e->tri != NULL) ? p2tr_triangle_get_opposite_point(e->tri, e, FALSE) : NULL;
+ P2trPoint *W = (e->mirror->tri != NULL) ? p2tr_triangle_get_opposite_point (e->mirror->tri, e->mirror, FALSE) : NULL;
+ gboolean constrained = e->constrained;
+ P2trEdge *XC, *CY;
+ GList *fan = NULL, *new_edges = NULL;
+ P2trHashSet *fan_edges;
+
+ P2TR_CDT_VALIDATE_UNUSED (self);
+
+ p2tr_edge_remove (e);
+
+ XC = p2tr_mesh_new_edge (self->mesh, X, C, constrained);
+ CY = p2tr_mesh_new_edge (self->mesh, C, Y, constrained);
+
+ fan = p2tr_utils_new_reversed_pointer_list (4, W, X, V, Y);
+ fan_edges = p2tr_cdt_triangulate_fan (self, C, fan);
+ g_list_free (fan);
+
+ /* Now make this a CDT again
+ * The new triangles will be unreffed by the flip_fix function, which
+ * is good since we receive them with an extra reference!
+ */
+ p2tr_cdt_flip_fix (self, fan_edges);
+ p2tr_hash_set_free (fan_edges);
+
+ if (constrained)
+ {
+ /* If this was a subsegment, then both parts of the subsegment
+ * should exist */
+ if (p2tr_edge_is_removed (XC) || p2tr_edge_is_removed (CY))
+ p2tr_exception_geometric ("Subsegments gone!");
+ else
+ {
+ new_edges = g_list_prepend (new_edges, CY);
+ new_edges = g_list_prepend (new_edges, XC);
+ }
+ }
+ else
+ {
+ p2tr_edge_unref (XC);
+ p2tr_edge_unref (CY);
+ }
+
+ P2TR_CDT_VALIDATE_UNUSED (self);
+
+ return new_edges;
+}
+
diff --git a/libs/poly2tri-c/poly2tri-c/refine/cdt.h b/libs/poly2tri-c/poly2tri-c/refine/cdt.h
new file mode 100644
index 0000000..23455a6
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/cdt.h
@@ -0,0 +1,127 @@
+/*
+ * 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_H__
+#define __P2TC_REFINE_CDT_H__
+
+#include <poly2tri-c/p2t/poly2tri.h>
+#include "mesh.h"
+#include "pslg.h"
+
+typedef struct
+{
+ P2trMesh *mesh;
+ P2trPSLG *outline;
+} P2trCDT;
+
+/**
+ * Create a new P2trCDT from an existing P2tCDT. The resulting P2trCDT
+ * does not depend on the original P2tCDT which can be freed
+ * @param cdt A P2tCDT Constrained Delaunay Triangulation
+ * @return A P2trCDT Constrained Delaunay Triangulation
+ */
+P2trCDT* p2tr_cdt_new (P2tCDT *cdt);
+
+void p2tr_cdt_free (P2trCDT *cdt);
+
+void p2tr_cdt_free_full (P2trCDT *cdt, gboolean clear_mesh);
+
+/**
+ * Test whether there is a path from the point @ref p to the edge @e
+ * so that the path does not cross any segment of the CDT
+ */
+gboolean p2tr_cdt_visible_from_edge (P2trCDT *self,
+ P2trEdge *e,
+ P2trVector2 *p);
+
+/**
+ * Make sure that all edges either have two triangles (one on each side)
+ * or that they are constrained. The reason for that is that the
+ * triangulation domain of the CDT is defined by a closed PSLG.
+ */
+void p2tr_cdt_validate_edges (P2trCDT *self);
+
+void p2tr_cdt_validate_unused (P2trCDT* self);
+
+/**
+ * Make sure the constrained empty circum-circle property holds,
+ * meaning that each triangles circum-scribing circle is either empty
+ * or only contains points which are not "visible" from the edges of
+ * the triangle.
+ */
+void p2tr_cdt_validate_cdt (P2trCDT *self);
+
+#if P2TR_CDT_VALIDATE
+#define P2TR_CDT_VALIDATE_EDGES(CDT) p2tr_cdt_validate_edges(CDT)
+#define P2TR_CDT_VALIDATE_UNUSED(CDT) p2tr_cdt_validate_unused(CDT)
+#define P2TR_CDT_VALIDATE_CDT(CDT) p2tr_cdt_validate_cdt(CDT)
+#else
+#define P2TR_CDT_VALIDATE_EDGES(CDT) G_STMT_START { } G_STMT_END
+#define P2TR_CDT_VALIDATE_UNUSED(CDT) G_STMT_START { } G_STMT_END
+#define P2TR_CDT_VALIDATE_CDT(CDT) G_STMT_START { } G_STMT_END
+#endif
+
+/**
+ * Insert a point into the triangulation while preserving the
+ * constrained delaunay property
+ * @param self The CDT into which the point should be inserted
+ * @param pc The point to insert
+ * @param point_location_guess A triangle which may be near the
+ * area containing the point (or maybe even contains the point).
+ * The better the guess is, the faster the insertion will be. If
+ * such a triangle is unknown, NULL may be passed.
+ */
+P2trPoint* p2tr_cdt_insert_point (P2trCDT *self,
+ const P2trVector2 *pc,
+ P2trTriangle *point_location_guess);
+
+/**
+ * Similar to @ref p2tr_cdt_insert_point, but assumes that the point to
+ * insert is located inside the area of the given triangle
+ */
+void p2tr_cdt_insert_point_into_triangle (P2trCDT *self,
+ P2trPoint *pt,
+ P2trTriangle *tri);
+
+/**
+ * Insert a point so that is splits an existing edge, while preserving
+ * the constrained delaunay property. This function assumes that the
+ * point is on the edge itself and between its end-points.
+ * If the edge being split is constrained, then the function returns a
+ * list containing both parts resulted from the splitting. In that case,
+ * THE RETURNED EDGES MUST BE UNREFERENCED!
+ */
+GList* p2tr_cdt_split_edge (P2trCDT *self,
+ P2trEdge *e,
+ P2trPoint *C);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/circle.c b/libs/poly2tri-c/poly2tri-c/refine/circle.c
new file mode 100644
index 0000000..affb1f6
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/circle.c
@@ -0,0 +1,47 @@
+/*
+ * 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 "circle.h"
+
+gboolean
+p2tr_circle_test_point_outside (P2trCircle *circle,
+ P2trVector2 *pt)
+{
+ gdouble dx = circle->center.x - pt->x;
+ gdouble dy = circle->center.y - pt->y;
+
+ gdouble d_squared = dx * dx + dy * dy;
+ gdouble radius_squared = circle->radius * circle->radius;
+
+ return d_squared > radius_squared;
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/circle.h b/libs/poly2tri-c/poly2tri-c/refine/circle.h
new file mode 100644
index 0000000..06bcdc3
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/circle.h
@@ -0,0 +1,46 @@
+/*
+ * 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_CIRCLE_H__
+#define __P2TC_REFINE_CIRCLE_H__
+
+#include <glib.h>
+#include "vector2.h"
+
+typedef struct {
+ P2trVector2 center;
+ gdouble radius;
+} P2trCircle;
+
+gboolean p2tr_circle_test_point_outside (P2trCircle *circle, P2trVector2 *pt);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/cluster.c b/libs/poly2tri-c/poly2tri-c/refine/cluster.c
new file mode 100644
index 0000000..3e6ce25
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/cluster.c
@@ -0,0 +1,139 @@
+/*
+ * 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 <math.h>
+
+#include <glib.h>
+#include "utils.h"
+#include "point.h"
+#include "edge.h"
+
+#include "cluster.h"
+
+static gboolean p2tr_cluster_cw_tri_between_is_in_domain (P2trEdge *e1,
+ P2trEdge *e2);
+
+gdouble
+p2tr_cluster_shortest_edge_length (P2trCluster *self)
+{
+ gdouble min_length_sq = G_MAXDOUBLE, temp;
+ GList *iter;
+
+ for (iter = self->edges.head; iter != NULL; iter = iter->next)
+ {
+ temp = p2tr_edge_get_length_squared ((P2trEdge*)iter->data);
+ min_length_sq = MIN(min_length_sq, temp);
+ }
+ return sqrt (min_length_sq);
+}
+
+/**
+ * Return the edge cluster of the specified edge from the specified end
+ * point. THE EDGES IN THE CLUSTER MUST BE UNREFFED!
+ * @param[in] P The point which is shared between all edges of the cluster
+ * @param[in] E The edge whose cluster should be returned
+ * @return The cluster of @ref E from the point @ref P
+ */
+P2trCluster*
+p2tr_cluster_get_for (P2trPoint *P,
+ P2trEdge *E)
+{
+ P2trCluster *cluster = g_slice_new (P2trCluster);
+ gdouble temp_angle;
+ P2trEdge *current, *next;
+
+ cluster->min_angle = G_MAXDOUBLE;
+ g_queue_init (&cluster->edges);
+
+ if (P == E->end)
+ E = E->mirror;
+ else if (P != P2TR_EDGE_START (E))
+ p2tr_exception_programmatic ("Unexpected point for the edge!");
+
+ g_queue_push_head (&cluster->edges, p2tr_edge_ref (E));
+
+ current = E;
+ next = p2tr_point_edge_cw (P, current);
+
+ while (next != g_queue_peek_head (&cluster->edges)
+ && (temp_angle = p2tr_edge_angle_between (current->mirror, next)) <= P2TR_CLUSTER_LIMIT_ANGLE
+ && p2tr_cluster_cw_tri_between_is_in_domain (current, next))
+ {
+ g_queue_push_tail (&cluster->edges, p2tr_edge_ref (next));
+ current = next;
+ next = p2tr_point_edge_cw (P, current);
+ cluster->min_angle = MIN (cluster->min_angle, temp_angle);
+ }
+
+ current = E;
+ next = p2tr_point_edge_ccw(P, current);
+ while (next != g_queue_peek_tail (&cluster->edges)
+ && (temp_angle = p2tr_edge_angle_between (current->mirror, next)) <= P2TR_CLUSTER_LIMIT_ANGLE
+ && p2tr_cluster_cw_tri_between_is_in_domain (next, current))
+ {
+ g_queue_push_head (&cluster->edges, p2tr_edge_ref (next));
+ current = next;
+ next = p2tr_point_edge_ccw (P, current);
+ cluster->min_angle = MIN(cluster->min_angle, temp_angle);
+ }
+
+ return cluster;
+}
+
+/* ^ e1
+ * /
+ * /_ e1.Tri (e2.Mirror.Tri)
+ * / |
+ * *---------> e2
+ *
+ * Check if the angle marked is a part of the triangulation
+ * domain
+ */
+static gboolean
+p2tr_cluster_cw_tri_between_is_in_domain (P2trEdge *e1, P2trEdge *e2)
+{
+ if (P2TR_EDGE_START(e1) != P2TR_EDGE_START(e2) || e1->tri != e2->mirror->tri)
+ p2tr_exception_programmatic ("Non clockwise adjacent edges!");
+ return e1->tri != NULL;
+}
+
+void
+p2tr_cluster_free (P2trCluster *self)
+{
+ GList *iter;
+
+ for (iter = self->edges.head; iter != NULL; iter = iter->next)
+ p2tr_edge_unref ((P2trEdge*)iter->data);
+
+ g_queue_clear (&self->edges);
+ g_slice_free (P2trCluster, self);
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/cluster.h b/libs/poly2tri-c/poly2tri-c/refine/cluster.h
new file mode 100644
index 0000000..6eaed8a
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/cluster.h
@@ -0,0 +1,55 @@
+/*
+ * 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_CLUSTER_H__
+#define __P2TC_REFINE_CLUSTER_H__
+
+#include <glib.h>
+#include "point.h"
+#include "edge.h"
+
+#define P2TR_CLUSTER_LIMIT_ANGLE (G_PI / 6)
+
+typedef struct
+{
+ GQueue edges;
+ gdouble min_angle;
+} P2trCluster;
+
+P2trCluster* p2tr_cluster_get_for (P2trPoint *P,
+ P2trEdge *E);
+
+gdouble p2tr_cluster_shortest_edge_length (P2trCluster *self);
+
+void p2tr_cluster_free (P2trCluster *self);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/delaunay-terminator.c b/libs/poly2tri-c/poly2tri-c/refine/delaunay-terminator.c
new file mode 100644
index 0000000..48ff030
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/delaunay-terminator.c
@@ -0,0 +1,529 @@
+/*
+ * 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 <stdio.h>
+#include <math.h>
+#include <glib.h>
+
+#include "utils.h"
+#include "rmath.h"
+
+#include "point.h"
+#include "edge.h"
+#include "triangle.h"
+
+#include "mesh.h"
+#include "cdt.h"
+#include "cluster.h"
+
+#include "vedge.h"
+#include "vtriangle.h"
+
+#include "delaunay-terminator.h"
+
+/* The code in this file is based on the "Delaunay Terminator" algorithm
+ * - an algorithm for refining constrained delaunay triangulations. The
+ * algorithm itself appears in a paper by Jonathan Richard Shewchuk as
+ * described below:
+ *
+ * Delaunay Refinement Algorithms for Triangular Mesh Generation
+ * Computational Geometry: Theory and Applications 22(1â3):21â74, May 2002
+ * Jonathan Richard Shewchuk
+ * http://www.cs.berkeley.edu/~jrs/papers/2dj.pdf
+ */
+
+gboolean
+p2tr_cdt_test_encroachment_ignore_visibility (const P2trVector2 *w,
+ P2trEdge *e)
+{
+ return p2tr_math_diametral_circle_contains (&P2TR_EDGE_START(e)->c,
+ &e->end->c, w);
+}
+
+gboolean
+p2tr_cdt_is_encroached_by (P2trCDT *self,
+ P2trEdge *e,
+ P2trVector2 *p)
+{
+ if (! e->constrained)
+ return FALSE;
+
+ return p2tr_cdt_test_encroachment_ignore_visibility (p, e)
+ && p2tr_cdt_visible_from_edge (self, e, p);
+}
+
+
+P2trVEdgeSet*
+p2tr_cdt_get_segments_encroached_by (P2trCDT *self,
+ P2trPoint *v)
+{
+ P2trVEdgeSet *encroached = p2tr_vedge_set_new ();
+ GList *iter;
+
+ for (iter = v->outgoing_edges; iter != NULL; iter = iter->next)
+ {
+ P2trEdge *outEdge = (P2trEdge*) iter->data;
+ P2trTriangle *t = outEdge->tri;
+ P2trEdge *e;
+
+ if (t == NULL)
+ continue;
+
+ e = p2tr_triangle_get_opposite_edge (t, v);
+
+ /* we want the fast check and for new points we don't
+ * use that check... So let's go on the full check
+ * since it's still faster */
+ if (e->constrained && p2tr_cdt_is_encroached (e))
+ p2tr_vedge_set_add2 (encroached, p2tr_vedge_new2 (e));
+ }
+
+ return encroached;
+}
+
+gboolean
+p2tr_cdt_is_encroached (P2trEdge *E)
+{
+ P2trTriangle *T1 = E->tri;
+ P2trTriangle *T2 = E->mirror->tri;
+
+ if (! E->constrained)
+ return FALSE;
+
+ return (T1 != NULL && p2tr_cdt_test_encroachment_ignore_visibility (&p2tr_triangle_get_opposite_point (T1, E, FALSE)->c, E))
+ || (T2 != NULL && p2tr_cdt_test_encroachment_ignore_visibility (&p2tr_triangle_get_opposite_point (T2, E, FALSE)->c, E));
+}
+
+/* ****************************************************************** */
+/* Now for the algorithm itself */
+/* ****************************************************************** */
+
+static gboolean
+SplitPermitted (P2trDelaunayTerminator *self, P2trEdge *s, gdouble d);
+
+static void
+SplitEncroachedSubsegments (P2trDelaunayTerminator *self, gdouble theta, P2trTriangleTooBig delta);
+
+static void
+NewVertex (P2trDelaunayTerminator *self, P2trPoint *v, gdouble theta, P2trTriangleTooBig delta);
+
+static gdouble
+ShortestEdgeLength (P2trTriangle *tri);
+
+static gboolean
+TolerantIsShorter (P2trEdge *toTest, P2trEdge *reference);
+
+static inline gdouble
+LOG2 (gdouble v);
+
+static gboolean
+TolerantIsPowerOfTwoLength (gdouble length);
+
+static void
+ChooseSplitVertex(P2trEdge *e, P2trVector2 *dst);
+
+
+
+static inline gint
+vtriangle_quality_compare (P2trVTriangle *t1, P2trVTriangle *t2)
+{
+ gdouble a1, a2;
+ P2trTriangle *r1, *r2;
+
+ r1 = p2tr_vtriangle_is_real (t1);
+ r2 = p2tr_vtriangle_is_real (t2);
+
+ /* TODO: untill we make sure that removed triangles will get out
+ * of Qt, we will make the comparision treat removed triangles as
+ * triangles with "less" quality (meaning they are "smaller")
+ */
+ if (!r1 || !r2)
+ return (!r1) ? -1 : (!r2 ? 1 : 0);
+
+ a1 = p2tr_triangle_smallest_non_constrained_angle (r1);
+ a2 = p2tr_triangle_smallest_non_constrained_angle (r2);
+
+ return (a1 < a2) ? -1 : ((a1 == a2) ? 0 : 1);
+}
+
+P2trDelaunayTerminator*
+p2tr_dt_new (gdouble theta, P2trTriangleTooBig delta, P2trCDT *cdt)
+{
+ P2trDelaunayTerminator *self = g_slice_new (P2trDelaunayTerminator);
+ self->Qt = g_sequence_new (NULL);
+ g_queue_init (&self->Qs);
+ self->delta = delta;
+ self->theta = theta;
+ self->cdt = cdt;
+ return self;
+}
+
+void
+p2tr_dt_free (P2trDelaunayTerminator *self)
+{
+ g_queue_clear (&self->Qs);
+ g_sequence_free (self->Qt);
+ g_slice_free (P2trDelaunayTerminator, self);
+}
+
+static void
+p2tr_dt_enqueue_tri (P2trDelaunayTerminator *self,
+ P2trTriangle *tri)
+{
+ g_sequence_insert_sorted (self->Qt, p2tr_vtriangle_new (tri), (GCompareDataFunc)vtriangle_quality_compare, NULL);
+}
+
+static inline gboolean
+p2tr_dt_tri_queue_is_empty (P2trDelaunayTerminator *self)
+{
+ return g_sequence_iter_is_end (g_sequence_get_begin_iter (self->Qt));
+}
+
+static P2trVTriangle*
+p2tr_dt_dequeue_tri (P2trDelaunayTerminator *self)
+{
+ GSequenceIter *first = g_sequence_get_begin_iter (self->Qt);
+
+ /* If we have an empty sequence, return NULL */
+ if (p2tr_dt_tri_queue_is_empty (self))
+ return NULL;
+ else
+ {
+ P2trVTriangle *ret = (P2trVTriangle*) g_sequence_get (first);
+ g_sequence_remove (first);
+ return ret;
+ }
+}
+
+static void
+p2tr_dt_enqueue_segment (P2trDelaunayTerminator *self,
+ P2trEdge *E)
+{
+ if (! E->constrained)
+ p2tr_exception_programmatic ("Tried to append a non-segment!");
+
+ g_queue_push_tail (&self->Qs, p2tr_edge_ref (E));
+}
+
+static P2trEdge*
+p2tr_dt_dequeue_segment (P2trDelaunayTerminator *self)
+{
+ if (g_queue_is_empty (&self->Qs))
+ return NULL;
+ else
+ return (P2trEdge*) g_queue_pop_head (&self->Qs);
+}
+
+static gboolean
+p2tr_dt_segment_queue_is_empty (P2trDelaunayTerminator *self)
+{
+ return g_queue_is_empty (&self->Qs);
+}
+
+void
+p2tr_dt_refine (P2trDelaunayTerminator *self,
+ gint max_steps,
+ P2trRefineProgressNotify on_progress)
+{
+ P2trHashSetIter hs_iter;
+ P2trEdge *s;
+ P2trTriangle *t;
+ P2trVTriangle *vt;
+ gint steps = 0;
+
+ P2TR_CDT_VALIDATE_CDT (self->cdt);
+
+ if (steps++ >= max_steps)
+ return;
+
+ p2tr_hash_set_iter_init (&hs_iter, self->cdt->mesh->edges);
+ while (p2tr_hash_set_iter_next (&hs_iter, (gpointer*)&s))
+ if (s->constrained && p2tr_cdt_is_encroached (s))
+ p2tr_dt_enqueue_segment (self, s);
+
+ SplitEncroachedSubsegments (self, 0, p2tr_refiner_false_too_big);
+ P2TR_CDT_VALIDATE_CDT (self->cdt);
+
+ p2tr_hash_set_iter_init (&hs_iter, self->cdt->mesh->triangles);
+ while (p2tr_hash_set_iter_next (&hs_iter, (gpointer*)&t))
+ if (p2tr_triangle_smallest_non_constrained_angle (t) < self->theta)
+ p2tr_dt_enqueue_tri (self, t);
+
+ if (on_progress != NULL) on_progress ((P2trRefiner*) self, steps, max_steps);
+
+ while (! p2tr_dt_tri_queue_is_empty (self))
+ {
+ vt = p2tr_dt_dequeue_tri (self);
+ t = p2tr_vtriangle_is_real (vt);
+
+ if (t && steps++ < max_steps)
+ {
+ P2trCircle tCircum;
+ P2trVector2 *c;
+ P2trTriangle *triContaining_c;
+ P2trVEdgeSet *E;
+ P2trPoint *cPoint;
+
+ P2TR_CDT_VALIDATE_CDT (self->cdt);
+ p2tr_triangle_get_circum_circle (t, &tCircum);
+ c = &tCircum.center;
+
+ triContaining_c = p2tr_mesh_find_point_local (self->cdt->mesh, c, t);
+
+ /* If no edge is encroached, then this must be
+ * inside the triangulation domain!!! */
+ if (triContaining_c == NULL)
+ p2tr_exception_geometric ("Should not happen! (%f, %f) (Center of (%f,%f)->(%f,%f)->(%f,%f)) is outside the domain!", c->x, c->y,
+ vt->points[0]->c.x, vt->points[0]->c.y,
+ vt->points[1]->c.x, vt->points[1]->c.y,
+ vt->points[2]->c.x, vt->points[2]->c.y);
+
+ /* Now, check if this point would encroach any edge
+ * of the triangulation */
+ p2tr_mesh_action_group_begin (self->cdt->mesh);
+
+ cPoint = p2tr_cdt_insert_point (self->cdt, c, triContaining_c);
+ E = p2tr_cdt_get_segments_encroached_by (self->cdt, cPoint);
+
+ if (p2tr_vedge_set_size (E) == 0)
+ {
+ p2tr_mesh_action_group_commit (self->cdt->mesh);
+ NewVertex (self, cPoint, self->theta, self->delta);
+ }
+ else
+ {
+ P2trVEdge *vSegment;
+ gdouble d;
+
+ p2tr_mesh_action_group_undo (self->cdt->mesh);
+ /* The (reverted) changes to the mesh may have eliminated the
+ * original triangle t. We must restore it manually from
+ * the virtual triangle
+ */
+ t = p2tr_vtriangle_is_real (vt);
+ g_assert (t != NULL);
+
+ d = ShortestEdgeLength (t);
+
+ while (p2tr_vedge_set_pop (E, &vSegment))
+ {
+ s = p2tr_vedge_get (vSegment);
+ if (self->delta (t) || SplitPermitted(self, s, d))
+ p2tr_dt_enqueue_segment (self, s);
+ p2tr_edge_unref (s);
+ p2tr_vedge_unref (vSegment);
+ }
+
+ if (! p2tr_dt_segment_queue_is_empty (self))
+ {
+ p2tr_dt_enqueue_tri (self, t);
+ SplitEncroachedSubsegments(self, self->theta, self->delta);
+ }
+ }
+
+ p2tr_vedge_set_free (E);
+ p2tr_point_unref (cPoint);
+ p2tr_triangle_unref (triContaining_c);
+ }
+
+ p2tr_vtriangle_unref (vt);
+
+ if (on_progress != NULL) on_progress ((P2trRefiner*) self, steps, max_steps);
+ }
+}
+
+static gboolean
+SplitPermitted (P2trDelaunayTerminator *self, P2trEdge *s, gdouble d)
+{
+ P2trCluster *startCluster = p2tr_cluster_get_for (P2TR_EDGE_START(s), s);
+ P2trCluster *endCluster = p2tr_cluster_get_for (s->end, s);
+ P2trCluster *S_NOREF;
+ GList *iter;
+
+ gboolean permitted = FALSE;
+
+ if (! TolerantIsPowerOfTwoLength (p2tr_edge_get_length (s))
+ /* True when different, meaning both null or both exist */
+ || ((startCluster != NULL) ^ (endCluster == NULL)))
+ {
+ permitted = TRUE;
+ }
+
+ if (! permitted)
+ {
+ S_NOREF = (startCluster != NULL) ? startCluster : endCluster;
+
+ for (iter = g_queue_peek_head_link (&S_NOREF->edges); iter != NULL; iter = iter->next)
+ if (TolerantIsShorter((P2trEdge*) iter->data, s)) /* e shorter than s */
+ {
+ permitted = TRUE;
+ break;
+ }
+ }
+
+ if (! permitted)
+ {
+ gdouble rmin = p2tr_edge_get_length(s) * sin(S_NOREF->min_angle / 2);
+ if (rmin >= d)
+ permitted = TRUE;
+ }
+
+ if (startCluster) p2tr_cluster_free (startCluster);
+ if (endCluster) p2tr_cluster_free (endCluster);
+
+ return permitted;
+}
+
+static void
+SplitEncroachedSubsegments (P2trDelaunayTerminator *self, gdouble theta, P2trTriangleTooBig delta)
+{
+ while (! p2tr_dt_segment_queue_is_empty (self))
+ {
+ P2trEdge *s = p2tr_dt_dequeue_segment (self);
+ if (p2tr_hash_set_contains (self->cdt->mesh->edges, s))
+ {
+ P2trVector2 v;
+ P2trPoint *Pv;
+ GList *parts, *iter;
+
+ ChooseSplitVertex (s, &v);
+ Pv = p2tr_mesh_new_point (self->cdt->mesh, &v);
+
+ /* Update here if using diametral lenses */
+
+ parts = p2tr_cdt_split_edge (self->cdt, s, Pv);
+
+ NewVertex (self, Pv, theta, delta);
+
+ for (iter = parts; iter != NULL; iter = iter->next)
+ {
+ P2trEdge *e = (P2trEdge*)iter->data;
+ if (p2tr_cdt_is_encroached (e))
+ p2tr_dt_enqueue_segment (self, e);
+ p2tr_edge_unref (e);
+ }
+ }
+ p2tr_edge_unref (s);
+ }
+}
+
+static void
+NewVertex (P2trDelaunayTerminator *self, P2trPoint *v, gdouble theta, P2trTriangleTooBig delta)
+{
+ GList *iter;
+ for (iter = v->outgoing_edges; iter != NULL; iter = iter->next)
+ {
+ P2trEdge *outEdge = (P2trEdge*) iter->data;
+ P2trTriangle *t = outEdge->tri;
+ P2trEdge *e;
+
+ if (t == NULL)
+ continue;
+
+ e = p2tr_triangle_get_opposite_edge (t, v);
+
+ /* we want the fast check and for new points we don't
+ * use that check... So let's go on the full check
+ * since it's still faster */
+ if (e->constrained && p2tr_cdt_is_encroached (e))
+ p2tr_dt_enqueue_segment (self, e);
+ else if (delta (t) || p2tr_triangle_smallest_non_constrained_angle (t) < theta)
+ p2tr_dt_enqueue_tri (self, t);
+
+ p2tr_edge_unref (e);
+ }
+}
+
+static gdouble
+ShortestEdgeLength (P2trTriangle *tri)
+{
+ gdouble a1 = p2tr_edge_get_length_squared (tri->edges[0]);
+ gdouble a2 = p2tr_edge_get_length_squared (tri->edges[1]);
+ gdouble a3 = p2tr_edge_get_length_squared (tri->edges[2]);
+
+ return sqrt (MIN (a1, MIN (a2, a3)));
+}
+
+static gboolean
+TolerantIsShorter (P2trEdge *toTest, P2trEdge *reference)
+{
+ return p2tr_edge_get_length(toTest) < p2tr_edge_get_length(reference) * 1.01;
+}
+
+static inline gdouble
+LOG2 (gdouble v)
+{
+ return log10 (v) / G_LOG_2_BASE_10;
+}
+
+static gboolean
+TolerantIsPowerOfTwoLength (gdouble length)
+{
+ gdouble exp = LOG2 (length);
+ gdouble intpart, frac = modf (exp, &intpart);
+ gdouble distance;
+
+ /* If the length is a negative power of 2, the returned fraction will be
+ * negative */
+ frac = ABS(frac);
+
+ /* Find how close is exp to the closest integer */
+ distance = MIN(frac, 1-frac);
+
+ return distance < 0.05;
+}
+
+static void
+ChooseSplitVertex(P2trEdge *e, P2trVector2 *dst)
+{
+ gdouble sourceLength = p2tr_edge_get_length(e);
+ gdouble newLengthFloor = pow(2, floor(LOG2(sourceLength)));
+ gdouble newLengthCeil = newLengthFloor * 2;
+ gdouble newLength =
+ (sourceLength - newLengthFloor < newLengthCeil - sourceLength)
+ ? newLengthFloor : newLengthCeil;
+ gdouble ratio, resultLength;
+
+ /* IMPORTANT! DIVIDE BY 2! */
+ newLength /= 2;
+
+ ratio = newLength / sourceLength;
+
+ dst->x = (1 - ratio) * P2TR_EDGE_START(e)->c.x + (ratio) * e->end->c.x;
+ dst->y = (1 - ratio) * P2TR_EDGE_START(e)->c.y + (ratio) * e->end->c.y;
+
+ /* now let's avoid consistency problems */
+ resultLength = sqrt(P2TR_VECTOR2_DISTANCE_SQ(&P2TR_EDGE_START(e)->c, dst));
+
+ if (! TolerantIsPowerOfTwoLength(resultLength))
+ p2tr_exception_numeric ("Bad rounding!");
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/delaunay-terminator.h b/libs/poly2tri-c/poly2tri-c/refine/delaunay-terminator.h
new file mode 100644
index 0000000..fe0ef5d
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/delaunay-terminator.h
@@ -0,0 +1,71 @@
+/*
+ * 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_DELAUNAY_TERMINATOR_H__
+#define __P2TC_REFINE_DELAUNAY_TERMINATOR_H__
+
+#include <glib.h>
+#include "cdt.h"
+#include "refiner.h"
+#include "vedge.h"
+
+typedef struct
+{
+ P2trCDT *cdt;
+ GQueue Qs;
+ GSequence *Qt;
+ gdouble theta;
+ P2trTriangleTooBig delta;
+} P2trDelaunayTerminator;
+
+gboolean p2tr_cdt_test_encroachment_ignore_visibility (const P2trVector2 *w,
+ P2trEdge *e);
+
+gboolean p2tr_cdt_is_encroached_by (P2trCDT *self,
+ P2trEdge *e,
+ P2trVector2 *p);
+
+P2trVEdgeSet* p2tr_cdt_get_segments_encroached_by (P2trCDT *self,
+ P2trPoint *v);
+
+gboolean p2tr_cdt_is_encroached (P2trEdge *E);
+
+P2trDelaunayTerminator*
+p2tr_dt_new (gdouble theta, P2trTriangleTooBig delta, P2trCDT *cdt);
+
+void p2tr_dt_free (P2trDelaunayTerminator *self);
+
+void p2tr_dt_refine (P2trDelaunayTerminator *self,
+ gint max_steps,
+ P2trRefineProgressNotify on_progress);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/edge.c b/libs/poly2tri-c/poly2tri-c/refine/edge.c
new file mode 100644
index 0000000..a95a6ee
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/edge.c
@@ -0,0 +1,247 @@
+/*
+ * 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 <math.h>
+#include <glib.h>
+
+#include "point.h"
+#include "edge.h"
+#include "triangle.h"
+#include "mesh.h"
+
+static void
+p2tr_edge_init (P2trEdge *self,
+ P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained,
+ P2trEdge *mirror)
+{
+ self->angle = atan2 (end->c.y - start->c.y,
+ end->c.x - start->c.x);
+ self->constrained = constrained;
+ self->delaunay = FALSE;
+ self->end = end;
+ self->mirror = mirror;
+ self->refcount = 0;
+ 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);
+
+ return p2tr_edge_ref (self);
+}
+
+P2trEdge*
+p2tr_edge_ref (P2trEdge *self)
+{
+ ++self->refcount;
+ return self;
+}
+
+void
+p2tr_edge_unref (P2trEdge *self)
+{
+ g_assert (self->refcount > 0);
+ if (--self->refcount == 0 && self->mirror->refcount == 0)
+ p2tr_edge_free (self);
+}
+
+gboolean
+p2tr_edge_is_removed (P2trEdge *self)
+{
+ return self->end == NULL; /* This is only true if the edge was removed */
+}
+
+void
+p2tr_edge_remove (P2trEdge *self)
+{
+ P2trMesh *mesh;
+ P2trPoint *start, *end;
+
+ if (p2tr_edge_is_removed (self))
+ return;
+
+ mesh = p2tr_edge_get_mesh (self);
+
+ start = P2TR_EDGE_START(self);
+ end = self->end;
+
+ if (self->tri != NULL)
+ p2tr_triangle_remove (self->tri);
+ if (self->mirror->tri != NULL)
+ p2tr_triangle_remove (self->mirror->tri);
+
+ if (mesh != NULL)
+ {
+ p2tr_mesh_on_edge_removed (mesh, self);
+ p2tr_mesh_unref (mesh); /* The get function reffed it */
+ }
+
+ /* Warning - the code here is not that trivial!
+ * Assuming we would now want to remove `self' and `self->mirror' from
+ * `start' and `end'. If both have exactly one reference, then after
+ * removing the second, the edge struct will be freed before we can
+ * mark it as removed by setting the end points to be NULL! (Marking
+ * it as removed in that case, will be an access to unallocated
+ * memory).
+ * To solve this, we will hold a "ghost" reference to `self' to
+ * prevent freeing from happening until we are done modifying the
+ * struct.
+ */
+ p2tr_edge_ref (self);
+
+ _p2tr_point_remove_edge(start, self);
+ _p2tr_point_remove_edge(end, self->mirror);
+
+ self->end = NULL;
+ self->mirror->end = NULL;
+
+ /* Now release the "ghost" reference */
+ p2tr_edge_unref (self);
+
+ p2tr_point_unref (start);
+ p2tr_point_unref (end);
+}
+
+void
+p2tr_edge_free (P2trEdge *self)
+{
+ g_assert (p2tr_edge_is_removed (self));
+ g_slice_free (P2trEdge, self->mirror);
+ g_slice_free (P2trEdge, self);
+}
+
+void
+p2tr_edge_get_diametral_circle (P2trEdge *self,
+ P2trCircle *circle)
+{
+ P2trVector2 radius;
+
+ p2tr_vector2_center (&self->end->c, &P2TR_EDGE_START(self)->c, &circle->center);
+ p2tr_vector2_sub (&self->end->c, &circle->center, &radius);
+
+ circle->radius = p2tr_vector2_norm (&radius);
+}
+
+P2trMesh*
+p2tr_edge_get_mesh (P2trEdge *self)
+{
+ if (self->end != NULL)
+ return p2tr_point_get_mesh (self->end);
+ else
+ return NULL;
+}
+
+gdouble
+p2tr_edge_get_length (P2trEdge* self)
+{
+ return sqrt (p2tr_math_length_sq2 (&self->end->c, &P2TR_EDGE_START(self)->c));
+}
+
+gdouble
+p2tr_edge_get_length_squared (P2trEdge* self)
+{
+ return p2tr_math_length_sq2 (&self->end->c, &P2TR_EDGE_START(self)->c);
+}
+
+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].
+ */
+ gdouble result;
+
+ 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!");
+
+ result = G_PI - e1->angle + e2->angle;
+ if (result > 2 * G_PI)
+ result -= 2 * G_PI;
+
+ return result;
+}
+
+gdouble
+p2tr_edge_angle_between_positive (P2trEdge *e1,
+ P2trEdge *e2)
+{
+ gdouble result = p2tr_edge_angle_between (e1, e2);
+ if (result < 0)
+ return result + 2 * G_PI;
+ else
+ return result;
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/edge.h b/libs/poly2tri-c/poly2tri-c/refine/edge.h
new file mode 100644
index 0000000..4e44c44
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/edge.h
@@ -0,0 +1,104 @@
+/*
+ * 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_EDGE_H__
+#define __P2TC_REFINE_EDGE_H__
+
+#include <glib.h>
+#include "circle.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.
+ * 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;
+};
+
+#define P2TR_EDGE_START(E) ((E)->mirror->end)
+
+P2trEdge* p2tr_edge_new (P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained);
+
+P2trEdge* p2tr_edge_ref (P2trEdge *self);
+
+void p2tr_edge_unref (P2trEdge *self);
+
+void p2tr_edge_free (P2trEdge *self);
+
+void p2tr_edge_remove (P2trEdge *self);
+
+P2trMesh* p2tr_edge_get_mesh (P2trEdge *self);
+
+gboolean p2tr_edge_is_removed (P2trEdge *self);
+
+gdouble p2tr_edge_get_length (P2trEdge* self);
+
+gdouble p2tr_edge_get_length_squared (P2trEdge* self);
+
+gdouble p2tr_edge_angle_between (P2trEdge *e1,
+ P2trEdge *e2);
+
+gdouble p2tr_edge_angle_between_positive (P2trEdge *e1,
+ P2trEdge *e2);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/line.c b/libs/poly2tri-c/poly2tri-c/refine/line.c
new file mode 100644
index 0000000..d2e0ccf
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/line.c
@@ -0,0 +1,102 @@
+/*
+ * 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 "line.h"
+
+void
+p2tr_line_init (P2trLine *line,
+ gdouble a,
+ gdouble b,
+ gdouble c)
+{
+ line->a = a;
+ line->b = b;
+ line->c = c;
+}
+
+gboolean
+p2tr_line_different_sides (const P2trLine *line,
+ const P2trVector2 *pt1,
+ const P2trVector2 *pt2)
+{
+ gdouble side1 = line->a * pt1->x + line->b * pt1->y + line->c;
+ gdouble side2 = line->a * pt2->x + line->b * pt2->y + line->c;
+
+ /* Signs are different if the product is negative */
+ return side1 * side2 < 0;
+}
+
+P2trLineRelation
+p2tr_line_intersection (const P2trLine *l1,
+ const P2trLine *l2,
+ P2trVector2 *out_intersection)
+{
+ /* In order to find the intersection, we intend to solve
+ * the following set of equations:
+ *
+ * ( A1 B1 ) ( x ) = ( -C1 )
+ * ( A2 B2 ) ( y ) = ( -C2 )
+ *
+ * We can simplify the solution using Cramers Rule which
+ * gives the following results:
+ *
+ * x = (-C1 * B2) - (-C2 * B1) / (A1 * B2 - A2 * B1)
+ * y = (A1 * -C2) - (A2 * -C1) / (A1 * B2 - A2 * B1)
+ */
+ double d = l1->a * l2->b - l2->a * l1->b;
+
+ /* If the denominator in the result of applying Cramers rule
+ * is zero, then the lines have exactly the same slope, meaning
+ * they are either exactly the same or they are parallel and
+ * never intersect */
+ if (d == 0)
+ {
+ /* We want to check if the offsets of boths the lines are the
+ * same, i.e. whether: C1 / A1 = C2 / A2
+ * This test can be done without zero division errors if we do
+ * it in like this: C1 * A2 = C2 * A1
+ */
+ if (l1->c * l2->a == l1->a * l2->c)
+ return P2TR_LINE_RELATION_SAME;
+ else
+ return P2TR_LINE_RELATION_PARALLEL;
+ }
+
+ if (out_intersection != NULL)
+ {
+ out_intersection->x = (-l1->c * l2->b + l2->c * l1->b) / d;
+ out_intersection->y = (l1->a * -l2->c + l2->a * l1->c) / d;
+ }
+
+ return P2TR_LINE_RELATION_INTERSECTING;
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/line.h b/libs/poly2tri-c/poly2tri-c/refine/line.h
new file mode 100644
index 0000000..a72813b
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/line.h
@@ -0,0 +1,66 @@
+/*
+ * 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_LINE_H__
+#define __P2TC_REFINE_LINE_H__
+
+#include <glib.h>
+#include "vector2.h"
+
+/* A line is the equation of the following form:
+ * a * X + b * Y + c = 0
+ */
+typedef struct {
+ gdouble a, b, c;
+} P2trLine;
+
+typedef enum
+{
+ P2TR_LINE_RELATION_INTERSECTING = 0,
+ P2TR_LINE_RELATION_PARALLEL = 1,
+ P2TR_LINE_RELATION_SAME = 2
+} P2trLineRelation;
+
+void p2tr_line_init (P2trLine *line,
+ gdouble a,
+ gdouble b,
+ gdouble c);
+
+gboolean p2tr_line_different_sides (const P2trLine *line,
+ const P2trVector2 *pt1,
+ const P2trVector2 *pt2);
+
+P2trLineRelation p2tr_line_intersection (const P2trLine *l1,
+ const P2trLine *l2,
+ P2trVector2 *out_intersection);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/mesh-action.c b/libs/poly2tri-c/poly2tri-c/refine/mesh-action.c
new file mode 100644
index 0000000..c2ffd9c
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/mesh-action.c
@@ -0,0 +1,228 @@
+/*
+ * 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 "mesh.h"
+#include "vedge.h"
+#include "vtriangle.h"
+#include "mesh-action.h"
+
+static P2trMeshAction*
+p2tr_mesh_action_point (P2trPoint *point,
+ gboolean added)
+{
+ P2trMeshAction *self = g_slice_new (P2trMeshAction);
+ self->type = P2TR_MESH_ACTION_POINT;
+ self->added = added;
+ self->refcount = 1;
+ self->action.action_point.point = p2tr_point_ref (point);
+ return self;
+}
+
+static void
+p2tr_mesh_action_point_free (P2trMeshAction *self)
+{
+ g_assert (self->type == P2TR_MESH_ACTION_POINT);
+ p2tr_point_unref (self->action.action_point.point);
+ g_slice_free (P2trMeshAction, self);
+}
+
+static void
+p2tr_mesh_action_point_undo (P2trMeshAction *self,
+ P2trMesh *mesh)
+{
+ g_assert (self->type == P2TR_MESH_ACTION_POINT);
+ if (self->added)
+ p2tr_point_remove (self->action.action_point.point);
+ else
+ p2tr_mesh_add_point (mesh, self->action.action_point.point);
+}
+
+P2trMeshAction*
+p2tr_mesh_action_new_point (P2trPoint *point)
+{
+ return p2tr_mesh_action_point (point, TRUE);
+}
+
+P2trMeshAction*
+p2tr_mesh_action_del_point (P2trPoint *point)
+{
+ return p2tr_mesh_action_point (point, FALSE);
+}
+
+static P2trMeshAction*
+p2tr_mesh_action_edge (P2trEdge *edge,
+ gboolean added)
+{
+ P2trMeshAction *self = g_slice_new (P2trMeshAction);
+ self->type = P2TR_MESH_ACTION_EDGE;
+ self->added = added;
+ self->refcount = 1;
+ self->action.action_edge.vedge = p2tr_vedge_new2 (edge);
+ self->action.action_edge.constrained = edge->constrained;
+ return self;
+}
+
+static void
+p2tr_mesh_action_edge_free (P2trMeshAction *self)
+{
+ g_assert (self->type == P2TR_MESH_ACTION_EDGE);
+ p2tr_vedge_unref (self->action.action_edge.vedge);
+ g_slice_free (P2trMeshAction, self);
+}
+
+static void
+p2tr_mesh_action_edge_undo (P2trMeshAction *self,
+ P2trMesh *mesh)
+{
+ g_assert (self->type == P2TR_MESH_ACTION_EDGE);
+
+ if (self->added)
+ p2tr_vedge_remove (self->action.action_edge.vedge);
+ else
+ p2tr_vedge_create (self->action.action_edge.vedge);
+}
+
+P2trMeshAction*
+p2tr_mesh_action_new_edge (P2trEdge *edge)
+{
+ return p2tr_mesh_action_edge (edge, TRUE);
+}
+
+P2trMeshAction*
+p2tr_mesh_action_del_edge (P2trEdge *edge)
+{
+ return p2tr_mesh_action_edge (edge, FALSE);
+}
+
+static P2trMeshAction*
+p2tr_mesh_action_triangle (P2trTriangle *tri,
+ gboolean added)
+{
+ P2trMeshAction *self = g_slice_new (P2trMeshAction);
+ self->type = P2TR_MESH_ACTION_TRIANGLE;
+ self->added = added;
+ self->refcount = 1;
+ self->action.action_tri.vtri = p2tr_vtriangle_new (tri);
+ return self;
+}
+
+static void
+p2tr_mesh_action_triangle_free (P2trMeshAction *self)
+{
+ g_assert (self->type == P2TR_MESH_ACTION_TRIANGLE);
+ p2tr_vtriangle_unref (self->action.action_tri.vtri);
+ g_slice_free (P2trMeshAction, self);
+}
+
+static void
+p2tr_mesh_action_triangle_undo (P2trMeshAction *self,
+ P2trMesh *mesh)
+{
+ g_assert (self->type == P2TR_MESH_ACTION_TRIANGLE);
+
+ if (self->added)
+ p2tr_vtriangle_remove (self->action.action_tri.vtri);
+ else
+ p2tr_vtriangle_create (self->action.action_tri.vtri);
+}
+
+P2trMeshAction*
+p2tr_mesh_action_new_triangle (P2trTriangle *tri)
+{
+ return p2tr_mesh_action_triangle (tri, TRUE);
+}
+
+P2trMeshAction*
+p2tr_mesh_action_del_triangle (P2trTriangle *tri)
+{
+ return p2tr_mesh_action_triangle (tri, FALSE);
+}
+
+P2trMeshAction*
+p2tr_mesh_action_ref (P2trMeshAction *self)
+{
+ ++self->refcount;
+ return self;
+}
+
+void
+p2tr_mesh_action_free (P2trMeshAction *self)
+{
+ switch (self->type)
+ {
+ case P2TR_MESH_ACTION_POINT:
+ p2tr_mesh_action_point_free (self);
+ break;
+ case P2TR_MESH_ACTION_EDGE:
+ p2tr_mesh_action_edge_free (self);
+ break;
+ case P2TR_MESH_ACTION_TRIANGLE:
+ p2tr_mesh_action_triangle_free (self);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+void
+p2tr_mesh_action_unref (P2trMeshAction *self)
+{
+ g_assert (self->refcount > 0);
+ if (--self->refcount == 0)
+ p2tr_mesh_action_free (self);
+}
+
+void
+p2tr_mesh_action_undo (P2trMeshAction *self,
+ P2trMesh *mesh)
+{
+ switch (self->type)
+ {
+ case P2TR_MESH_ACTION_POINT:
+ p2tr_mesh_action_point_undo (self, mesh);
+ break;
+ case P2TR_MESH_ACTION_EDGE:
+ p2tr_mesh_action_edge_undo (self, mesh);
+ break;
+ case P2TR_MESH_ACTION_TRIANGLE:
+ p2tr_mesh_action_triangle_undo (self, mesh);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
diff --git a/libs/poly2tri-c/poly2tri-c/refine/mesh-action.h b/libs/poly2tri-c/poly2tri-c/refine/mesh-action.h
new file mode 100644
index 0000000..cd3e840
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/mesh-action.h
@@ -0,0 +1,170 @@
+/*
+ * 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_MESH_ACTION_H__
+#define __P2TC_REFINE_MESH_ACTION_H__
+
+#include <glib.h>
+
+/**
+ * \defgroup P2trMeshAction P2trMeshAction - Mesh Action Recording
+ * Action recording state objects for mesh objects. These may be
+ * inspected by code outside of the library, but objects of this type
+ * should not be created or manipulated by external code!
+ * @{
+ */
+
+/**
+ * The type of the geometric primitive affected by a mesh action
+ */
+typedef enum
+{
+ P2TR_MESH_ACTION_POINT,
+ P2TR_MESH_ACTION_EDGE,
+ P2TR_MESH_ACTION_TRIANGLE
+} P2trMeshActionType;
+
+/**
+ * A struct representing any single action on a mesh. A single atomic
+ * action may be the insertion/removal of a point/edge/triangle.
+ *
+ * Note that such an action only treats the direct geometric operation
+ * related to the specific geometric primitve, without any of its
+ * dependencies.
+ *
+ * For example, if removing a point requires the removal of several
+ * edges and triangles, then the removal of each one of those should be
+ * recorded in its own action object.
+ */
+typedef struct P2trMeshAction_
+{
+ /** The type of geometric primitive affected by the action */
+ P2trMeshActionType type;
+ /** A flag specifying whether the primitive was added or removed */
+ gboolean added;
+ /** A reference count to the action object */
+ gint refcount;
+ /** Specific additional information which is needed for each type
+ * of action */
+ union {
+ /** Information required to undo a point action */
+ struct {
+ /** The point that was added/deleted */
+ P2trPoint *point;
+ } action_point;
+
+ /** Information required to undo an edge action */
+ struct {
+ /** A virtual edge representing the added/deleted edge */
+ P2trVEdge *vedge;
+ /** A flag specifying whether the edge is constrained */
+ gboolean constrained;
+ } action_edge;
+
+ /** Information required to undo a triangle action */
+ struct {
+ /** A virtual triangle representing the added/deleted triangle */
+ P2trVTriangle *vtri;
+ } action_tri;
+ } action;
+} P2trMeshAction;
+
+/**
+ * Create a new mesh action describing the addition of a new point
+ * @param point The point that is added to the mesh
+ * @return An object representing the point addition action
+ */
+P2trMeshAction* p2tr_mesh_action_new_point (P2trPoint *point);
+
+/**
+ * Create a new mesh action describing the deletion of an existing point
+ * @param point The point that is deleted from the mesh
+ * @return An object representing the point deletion action
+ */
+P2trMeshAction* p2tr_mesh_action_del_point (P2trPoint *point);
+
+/**
+ * Create a new mesh action describing the addition of a new edge
+ * @param edge The edge that is added to the mesh
+ * @return An object representing the edge addition action
+ */
+P2trMeshAction* p2tr_mesh_action_new_edge (P2trEdge *edge);
+
+/**
+ * Create a new mesh action describing the deletion of an existing edge
+ * @param edge The edge that is deleted from the mesh
+ * @return An object representing the edge deletion action
+ */
+P2trMeshAction* p2tr_mesh_action_del_edge (P2trEdge *edge);
+
+/**
+ * Create a new mesh action describing the addition of a triangle
+ * @param tri The triangle that is added to the mesh
+ * @return An object representing the triangle addition action
+ */
+P2trMeshAction* p2tr_mesh_action_new_triangle (P2trTriangle *tri);
+
+/**
+ * Create a new mesh action describing the deletion of an existing
+ * triangle
+ * @param tri The triangle that is deleted from the mesh
+ * @return An object representing the triangle deletion action
+ */
+P2trMeshAction* p2tr_mesh_action_del_triangle (P2trTriangle *tri);
+
+/**
+ * Increase the reference count to this mesh action by 1
+ * @param self The mesh action whose reference count should be increased
+ */
+P2trMeshAction* p2tr_mesh_action_ref (P2trMeshAction *self);
+
+/**
+ * Decrease the reference count to this mesh action by 1
+ * @param self The mesh action whose reference count should be decreased
+ */
+void p2tr_mesh_action_unref (P2trMeshAction *self);
+
+/**
+ * Free the memory used by a mesh action data structure
+ * @param self The mesh action whose memory should be freed
+ */
+void p2tr_mesh_action_free (P2trMeshAction *self);
+
+/**
+ * Undo the action described by the given mesh action object
+ * @param self The mesh action to undo
+ * @param mesh The mesh on which this action was applied
+ */
+void p2tr_mesh_action_undo (P2trMeshAction *self,
+ P2trMesh *mesh);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/mesh.c b/libs/poly2tri-c/poly2tri-c/refine/mesh.c
new file mode 100644
index 0000000..4478178
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/mesh.c
@@ -0,0 +1,406 @@
+/*
+ * 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 "utils.h"
+
+#include "mesh.h"
+#include "point.h"
+#include "edge.h"
+#include "triangle.h"
+#include "mesh-action.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->record_undo = FALSE;
+ g_queue_init (&mesh->undo);
+
+ return mesh;
+}
+
+P2trPoint*
+p2tr_mesh_add_point (P2trMesh *self,
+ P2trPoint *point)
+{
+ g_assert (point->mesh == NULL);
+ point->mesh = self;
+ p2tr_mesh_ref (self);
+ p2tr_hash_set_insert (self->points, point);
+
+ if (self->record_undo)
+ g_queue_push_tail (&self->undo, p2tr_mesh_action_new_point (point));
+
+ return p2tr_point_ref (point);
+}
+
+P2trPoint*
+p2tr_mesh_new_point (P2trMesh *self,
+ const P2trVector2 *c)
+{
+ return p2tr_mesh_new_point2 (self, c->x, c->y);
+}
+
+P2trPoint*
+p2tr_mesh_new_point2 (P2trMesh *self,
+ gdouble x,
+ gdouble y)
+{
+ return p2tr_mesh_add_point (self, p2tr_point_new2 (x, y));
+}
+
+P2trEdge*
+p2tr_mesh_add_edge (P2trMesh *self,
+ P2trEdge *edge)
+{
+ p2tr_hash_set_insert (self->edges, p2tr_edge_ref (edge->mirror));
+ p2tr_hash_set_insert (self->edges, p2tr_edge_ref (edge));
+
+ if (self->record_undo)
+ g_queue_push_tail (&self->undo, p2tr_mesh_action_new_edge (edge));
+
+ return edge;
+}
+
+P2trEdge*
+p2tr_mesh_new_edge (P2trMesh *self,
+ P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained)
+{
+ return p2tr_mesh_add_edge (self, p2tr_edge_new (start, end, constrained));
+}
+
+P2trEdge*
+p2tr_mesh_new_or_existing_edge (P2trMesh *self,
+ P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained)
+{
+ P2trEdge *result = p2tr_point_has_edge_to (start, end);
+ if (result)
+ p2tr_edge_ref (result);
+ else
+ result = p2tr_mesh_new_edge (self, start, end, constrained);
+ return result;
+}
+
+P2trTriangle*
+p2tr_mesh_add_triangle (P2trMesh *self,
+ P2trTriangle *tri)
+{
+ p2tr_hash_set_insert (self->triangles, tri);
+
+ if (self->record_undo)
+ g_queue_push_tail (&self->undo, p2tr_mesh_action_new_triangle (tri));
+
+ return p2tr_triangle_ref (tri);
+}
+
+P2trTriangle*
+p2tr_mesh_new_triangle (P2trMesh *self,
+ P2trEdge *AB,
+ P2trEdge *BC,
+ P2trEdge *CA)
+{
+ return p2tr_mesh_add_triangle (self, p2tr_triangle_new (AB, BC, CA));
+}
+
+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);
+
+ p2tr_hash_set_remove (self->points, point);
+
+ if (self->record_undo)
+ g_queue_push_tail (&self->undo, p2tr_mesh_action_del_point (point));
+
+ p2tr_point_unref (point);
+}
+
+void
+p2tr_mesh_on_edge_removed (P2trMesh *self,
+ P2trEdge *edge)
+{
+ p2tr_hash_set_remove (self->edges, edge->mirror);
+ p2tr_edge_unref (edge->mirror);
+ p2tr_hash_set_remove (self->edges, edge);
+
+ if (self->record_undo)
+ g_queue_push_tail (&self->undo, p2tr_mesh_action_del_edge (edge));
+
+ p2tr_edge_unref (edge);
+}
+
+void
+p2tr_mesh_on_triangle_removed (P2trMesh *self,
+ P2trTriangle *triangle)
+{
+ p2tr_hash_set_remove (self->triangles, triangle);
+
+ if (self->record_undo)
+ g_queue_push_tail (&self->undo, p2tr_mesh_action_del_triangle (triangle));
+
+ p2tr_triangle_unref (triangle);
+}
+
+void
+p2tr_mesh_action_group_begin (P2trMesh *self)
+{
+ g_assert (! self->record_undo);
+ self->record_undo = TRUE;
+}
+
+void
+p2tr_mesh_action_group_commit (P2trMesh *self)
+{
+ GList *iter;
+
+ g_assert (self->record_undo);
+
+ for (iter = self->undo.head; iter != NULL; iter = iter->next)
+ p2tr_mesh_action_unref ((P2trMeshAction*)iter->data);
+ g_queue_clear (&self->undo);
+
+ self->record_undo = FALSE;
+}
+
+void
+p2tr_mesh_action_group_undo (P2trMesh *self)
+{
+ GList *iter;
+
+ g_assert (self->record_undo);
+
+ for (iter = self->undo.tail; iter != NULL; iter = iter->prev)
+ {
+ p2tr_mesh_action_undo ((P2trMeshAction*)iter->data, self);
+ p2tr_mesh_action_unref ((P2trMeshAction*)iter->data);
+ }
+ g_queue_clear (&self->undo);
+
+ self->record_undo = FALSE;
+}
+
+void
+p2tr_mesh_clear (P2trMesh *self)
+{
+ P2trHashSetIter iter;
+ gpointer temp;
+
+ /* While iterating over the sets of points/edges/triangles to remove
+ * all the mesh elements, the sets will be modified by the removal
+ * operation itself. Therefore we can't use a regular iterator -
+ * instead we must look always at the first place */
+ p2tr_hash_set_iter_init (&iter, self->triangles);
+ while (p2tr_hash_set_iter_next (&iter, &temp))
+ {
+ p2tr_triangle_remove ((P2trTriangle*)temp);
+ p2tr_hash_set_iter_init (&iter, self->triangles);
+ }
+
+ p2tr_hash_set_iter_init (&iter, self->edges);
+ while (p2tr_hash_set_iter_next (&iter, &temp))
+ {
+ g_assert (((P2trEdge*)temp)->tri == NULL);
+ p2tr_edge_remove ((P2trEdge*)temp);
+ p2tr_hash_set_iter_init (&iter, self->edges);
+ }
+
+ p2tr_hash_set_iter_init (&iter, self->points);
+ while (p2tr_hash_set_iter_next (&iter, &temp))
+ {
+ g_assert (((P2trPoint*)temp)->outgoing_edges == NULL);
+ p2tr_point_remove ((P2trPoint*)temp);
+ p2tr_hash_set_iter_init (&iter, self->points);
+ }
+}
+
+void
+p2tr_mesh_free (P2trMesh *self)
+{
+ if (self->record_undo)
+ p2tr_mesh_action_group_commit (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)
+{
+ g_assert (self->refcount > 0);
+ if (--self->refcount == 0)
+ p2tr_mesh_free (self);
+}
+
+P2trMesh*
+p2tr_mesh_ref (P2trMesh *self)
+{
+ ++self->refcount;
+ return self;
+}
+
+P2trTriangle*
+p2tr_mesh_find_point (P2trMesh *self,
+ const P2trVector2 *pt)
+{
+ gdouble u, v;
+ return p2tr_mesh_find_point2 (self, pt, &u, &v);
+}
+
+P2trTriangle*
+p2tr_mesh_find_point2 (P2trMesh *self,
+ const P2trVector2 *pt,
+ gdouble *u,
+ gdouble *v)
+{
+ P2trHashSetIter iter;
+ P2trTriangle *result;
+
+ p2tr_hash_set_iter_init (&iter, self->triangles);
+ while (p2tr_hash_set_iter_next (&iter, (gpointer*)&result))
+ if (p2tr_triangle_contains_point2 (result, pt, u, v) != P2TR_INTRIANGLE_OUT)
+ return p2tr_triangle_ref (result);
+
+ return NULL;
+}
+
+P2trTriangle*
+p2tr_mesh_find_point_local (P2trMesh *self,
+ const P2trVector2 *pt,
+ P2trTriangle *initial_guess)
+{
+ gdouble u, v;
+ return p2tr_mesh_find_point_local2 (self, pt, initial_guess, &u, &v);
+}
+
+P2trTriangle*
+p2tr_mesh_find_point_local2 (P2trMesh *self,
+ const P2trVector2 *pt,
+ P2trTriangle *initial_guess,
+ gdouble *u,
+ gdouble *v)
+{
+ P2trHashSet *checked_tris;
+ GQueue to_check;
+ P2trTriangle *result = NULL;
+
+ if (initial_guess == NULL)
+ return p2tr_mesh_find_point2(self, pt, u, v);
+
+ checked_tris = p2tr_hash_set_new_default ();
+ g_queue_init (&to_check);
+ g_queue_push_head (&to_check, initial_guess);
+
+ while (! g_queue_is_empty (&to_check))
+ {
+ P2trTriangle *tri = (P2trTriangle*) g_queue_pop_head (&to_check);
+
+ p2tr_hash_set_insert (checked_tris, tri);
+ if (p2tr_triangle_contains_point2 (tri, pt, u, v) != P2TR_INTRIANGLE_OUT)
+ {
+ result = tri;
+ break;
+ }
+ else
+ {
+ gint i;
+ for (i = 0; i < 3; i++)
+ {
+ P2trTriangle *new_to_check = tri->edges[i]->mirror->tri;
+ if (new_to_check != NULL
+ && ! p2tr_hash_set_contains (checked_tris, new_to_check))
+ {
+ p2tr_hash_set_insert (checked_tris, new_to_check);
+ g_queue_push_tail (&to_check, new_to_check);
+ }
+ }
+ }
+ }
+
+ p2tr_hash_set_free (checked_tris);
+ g_queue_clear (&to_check);
+
+ if (result != NULL)
+ p2tr_triangle_ref (result);
+
+ return result;
+}
+
+void
+p2tr_mesh_get_bounds (P2trMesh *self,
+ gdouble *min_x,
+ gdouble *min_y,
+ gdouble *max_x,
+ gdouble *max_y)
+{
+ gdouble lmin_x = + G_MAXDOUBLE, lmin_y = + G_MAXDOUBLE;
+ gdouble lmax_x = - G_MAXDOUBLE, lmax_y = - G_MAXDOUBLE;
+
+ P2trHashSetIter iter;
+ P2trPoint *pt;
+
+ p2tr_hash_set_iter_init (&iter, self->points);
+ while (p2tr_hash_set_iter_next (&iter, (gpointer*) &pt))
+ {
+ gdouble x = pt->c.x;
+ gdouble y = pt->c.y;
+
+ lmin_x = MIN (lmin_x, x);
+ lmin_y = MIN (lmin_y, y);
+ lmax_x = MAX (lmax_x, x);
+ lmax_y = MAX (lmax_y, y);
+ }
+ *min_x = lmin_x;
+ *min_y = lmin_y;
+ *max_x = lmax_x;
+ *max_y = lmax_y;
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/mesh.h b/libs/poly2tri-c/poly2tri-c/refine/mesh.h
new file mode 100644
index 0000000..c814df4
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/mesh.h
@@ -0,0 +1,361 @@
+/*
+ * 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_MESH_H__
+#define __P2TC_REFINE_MESH_H__
+
+#include <glib.h>
+#include "vector2.h"
+#include "utils.h"
+#include "triangulation.h"
+
+/**
+ * \defgroup P2trMesh P2trMesh - Triangular Meshes
+ * The library is designed to handle triangular meshes which are made
+ * of one continuous region, potentially with holes
+ * @{
+ */
+
+/**
+ * A struct for representing a triangular mesh
+ */
+struct P2trMesh_
+{
+ /**
+ * A hash set containing pointers to all the triangles
+ * (\ref P2trTriangle) in the mesh
+ */
+ P2trHashSet *triangles;
+
+ /**
+ * A hash set containing pointers to all the edges (\ref P2trEdge) in
+ * the mesh
+ */
+ P2trHashSet *edges;
+
+ /**
+ * A hash set containing pointers to all the points (\ref P2trPoint)
+ * in the mesh
+ */
+ P2trHashSet *points;
+
+ /**
+ * A boolean flag specifying whether recording of actions on the
+ * mesh (for allowing to undo them) is taking place right now
+ */
+ gboolean record_undo;
+
+ /**
+ * A queue stroing all the actions done on the mesh since the begining
+ * of the recording
+ */
+ GQueue undo;
+
+ /**
+ * Counts the amount of references to the mesh. When this counter
+ * reaches zero, the mesh will be freed
+ */
+ guint refcount;
+};
+
+/**
+ * Create a new empty mesh
+ * @return The newly created mesh
+ */
+P2trMesh* p2tr_mesh_new (void);
+
+/**
+ * Add an existing point to the given mesh
+ * @param self The mesh to add the point to
+ * @param point The point to add
+ * @return The given point
+ */
+P2trPoint* p2tr_mesh_add_point (P2trMesh *self,
+ P2trPoint *point);
+
+/**
+ * Create a new point and add it to the given mesh
+ * @param mesh The mesh to add the point to
+ * @param c The coordinates of the point to create
+ * @return The newly created point
+ */
+P2trPoint* p2tr_mesh_new_point (P2trMesh *mesh,
+ const P2trVector2 *c);
+
+/**
+ * Create a new point and add it to the given mesh
+ * @param mesh The mesh to add the point to
+ * @param x The X coordinate of the point to create
+ * @param y The Y coordinate of the point to create
+ * @return The newly created point
+ */
+P2trPoint* p2tr_mesh_new_point2 (P2trMesh *mesh,
+ gdouble x,
+ gdouble y);
+
+/**
+ * Add an existing edge to the given mesh
+ * @param self The mesh to add the edge to
+ * @param edge The edge to add
+ * @return The given edge
+ */
+P2trEdge* p2tr_mesh_add_edge (P2trMesh *self,
+ P2trEdge *point);
+
+/**
+ * Create a new edge and add it to the given mesh
+ * @param mesh The mesh to add the edge to
+ * @param start The starting point of the edge
+ * @param end The ending point of the edge
+ * @param constrained Specify whether this edge is constrained or not
+ * @return Thew newly created edge
+ */
+P2trEdge* p2tr_mesh_new_edge (P2trMesh *mesh,
+ P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained);
+
+/**
+ * This function checks if an edge between two points exists, and if
+ * not it creates it. In both cases the returned edge will be returned
+ * with an extra reference, so it must be unreffed later.
+ * @param self The mesh of the returned edge
+ * @param start The starting point of the returned edge
+ * @param end The ending point of the returned edge
+ * @param constrained Specify whether this edge should be constrained
+ * or not (in case a new edge is created)
+ * @return An edge between the two points
+ */
+P2trEdge* p2tr_mesh_new_or_existing_edge (P2trMesh *self,
+ P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained);
+
+/**
+ * Add an existing triangle to the given mesh
+ * @param self The mesh to add the triangle to
+ * @param edge The triangle to add
+ * @return The given triangle
+ */
+P2trTriangle* p2tr_mesh_add_triangle (P2trMesh *self,
+ P2trTriangle *tri);
+
+/**
+ * Create a new triangle and add it to the given mesh
+ * @param mesh The mesh to add the triangle to
+ * @param AB An edge from the first point of the triangle to the second
+ * @param BC An edge from the second point of the triangle to the third
+ * @param CA An edge from the third point of the triangle to the first
+ */
+P2trTriangle* p2tr_mesh_new_triangle (P2trMesh *mesh,
+ P2trEdge *AB,
+ P2trEdge *BC,
+ P2trEdge *CA);
+
+/** \internal
+ * This function should be called just before a point is removed from
+ * the mesh. It is used internally to update the mesh and it should not
+ * be called by any code outside of this library.
+ * @param mesh The mesh from which the point is going to be removed
+ * @param point The point which is going to be removed
+*/
+void p2tr_mesh_on_point_removed (P2trMesh *mesh,
+ P2trPoint *point);
+
+/** \internal
+ * This function should be called just before an edge is removed from
+ * the mesh. It is used internally to update the mesh and it should not
+ * be called by any code outside of this library.
+ * @param mesh The mesh from which the edge is going to be removed
+ * @param edge The edge which is going to be removed
+*/
+void p2tr_mesh_on_edge_removed (P2trMesh *mesh,
+ P2trEdge *edge);
+
+/** \internal
+ * This function should be called just before a triangle is removed from
+ * the mesh. It is used internally to update the mesh and it should not
+ * be called by any code outside of this library.
+ * @param mesh The mesh from which the triangle is going to be removed
+ * @param triangle The triangle which is going to be removed
+*/
+void p2tr_mesh_on_triangle_removed (P2trMesh *mesh,
+ P2trTriangle *triangle);
+
+/**
+ * Begin recording all action performed on a mesh. Recording the
+ * actions performed on a mesh allows choosing later whether to commit
+ * those actions or whether they should be undone.
+ * \warning This function must not be called when recording is already
+ * taking place!
+ * @param self The mesh whose actions should be recorded
+ */
+void p2tr_mesh_action_group_begin (P2trMesh *self);
+
+/**
+ * Terminate the current session of recording mesh actions by
+ * committing all the actions to the mesh
+ * \warning This function must not be called unless recording of
+ * actions is already taking place!
+ * @param self The mesh whose actions were recorded
+ */
+void p2tr_mesh_action_group_commit (P2trMesh *self);
+
+/**
+ * Terminate the current session of recording mesh actions by
+ * undoing all the actions done to the mesh.
+ * \warning This function must not be called unless recording of
+ * actions is already taking place!
+ * \warning A call to this function may invalidate all references to
+ * any non virtual geometric primitives! If you plan on using
+ * this function, consider using virtual data structures!
+ * @param self The mesh whose actions were recorded
+ */
+void p2tr_mesh_action_group_undo (P2trMesh *self);
+
+/**
+ * Remove all triangles, edges and points from a mesh
+ * @param mesh The mesh to clear
+ */
+void p2tr_mesh_clear (P2trMesh *mesh);
+
+/**
+ * Clear and then free the memory used by a mesh data structure
+ * @param mesh The mesh whose memory should be freed
+ */
+void p2tr_mesh_free (P2trMesh *mesh);
+
+/**
+ * Decrease the reference count to this mesh by 1
+ * @param mesh The mesh whose reference count should be decreased
+ */
+void p2tr_mesh_unref (P2trMesh *mesh);
+
+/**
+ * Increase the reference count to this mesh by 1
+ * @param mesh The mesh whose reference count should be increased
+ * @return The given mesh (\ref mesh)
+ */
+P2trMesh* p2tr_mesh_ref (P2trMesh *mesh);
+
+/**
+ * Find a triangle of the mesh, containing the point at the given
+ * location
+ * @param self The mesh whose triangles should be checked
+ * @param pt The location of the point to test
+ * @return The triangle containing the given point, or NULL if the
+ * point is outside the triangulation domain
+ */
+P2trTriangle* p2tr_mesh_find_point (P2trMesh *self,
+ const P2trVector2 *pt);
+
+/**
+ * Exactly like \ref p2tr_mesh_find_point, except for the fact that
+ * this variant also returns the UV coordinates of the point inside the
+ * triangle
+ * @param[in] self The mesh whose triangles should be checked
+ * @param[in] pt The location of the point to test
+ * @param[out] u The U coordinate of the point inside the triangle
+ * @param[out] v The V coordinate of the point inside the triangle
+ * @return The triangle containing the given point, or NULL if the
+ * point is outside the triangulation domain
+ */
+P2trTriangle* p2tr_mesh_find_point2 (P2trMesh *self,
+ const P2trVector2 *pt,
+ gdouble *u,
+ gdouble *v);
+
+/**
+ * Another variant of \ref p2tr_mesh_find_point taking an initial
+ * triangle that the search should begin from its area. The search is
+ * performed first on triangles close to the given triangle, and it
+ * gradually tests farther and farther triangles until it finds the one
+ * containing the given point.
+ *
+ * This way of search should be fast when the approximate area of the
+ * point to find is known, but it will be slower if initial triangle
+ * is not near.
+ *
+ * Note that in this function, triangles are considered near depending
+ * on the length of the chain of neighbor triangles needed to go from
+ * one to the other.
+ *
+ * \warning This function may use memory which is at least linear in
+ * the amount of triangles to test. Therefor, do not use it
+ * on large mesh objects unless the initial guess is supposed
+ * to be good!
+ * @param self The mesh whose triangles should be checked
+ * @param pt The location of the point to test
+ * @param initial_guess An initial guess for which triangle contains
+ * the point, or is at least near the triangle containing it
+ * @return The triangle containing the given point, or NULL if the
+ * point is outside the triangulation domain
+ */
+P2trTriangle* p2tr_mesh_find_point_local (P2trMesh *self,
+ const P2trVector2 *pt,
+ P2trTriangle *initial_guess);
+
+/**
+ * Exactly like \ref p2tr_mesh_find_point_local, except for the fact
+ * that this variant also returns the UV coordinates of the point
+ * inside the triangle
+ * @param[in] self The mesh whose triangles should be checked
+ * @param[in] pt The location of the point to test
+ * @param[in] initial_guess An initial guess for which triangle
+ * contains the point, or is at least near the triangle
+ * containing it
+ * @param[out] u The U coordinate of the point inside the triangle
+ * @param[out] v The V coordinate of the point inside the triangle
+ * @return The triangle containing the given point, or NULL if the
+ * point is outside the triangulation domain
+ */
+P2trTriangle* p2tr_mesh_find_point_local2 (P2trMesh *self,
+ const P2trVector2 *pt,
+ P2trTriangle *initial_guess,
+ gdouble *u,
+ gdouble *v);
+
+/**
+ * Find the bounding rectangle containing this mesh.
+ * @param[in] self The mesh whose bounding rectangle should be computed
+ * @param[out] min_x The minimal X coordinate of the mesh
+ * @param[out] min_y The minimal Y coordinate of the mesh
+ * @param[out] max_x The maximal X coordinate of the mesh
+ * @param[out] max_y The maximal Y coordinate of the mesh
+ */
+void p2tr_mesh_get_bounds (P2trMesh *self,
+ gdouble *min_x,
+ gdouble *min_y,
+ gdouble *max_x,
+ gdouble *max_y);
+/** @} */
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/point.c b/libs/poly2tri-c/poly2tri-c/refine/point.c
new file mode 100644
index 0000000..722cab6
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/point.c
@@ -0,0 +1,227 @@
+/*
+ * 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 "mesh.h"
+
+P2trPoint*
+p2tr_point_new (const P2trVector2 *c)
+{
+ return p2tr_point_new2 (c->x, c->y);
+}
+
+P2trPoint*
+p2tr_point_new2 (gdouble x, gdouble y)
+{
+ P2trPoint *self = g_slice_new (P2trPoint);
+
+ self->c.x = x;
+ self->c.y = y;
+ self->mesh = NULL;
+ self->outgoing_edges = NULL;
+ self->refcount = 1;
+
+ return self;
+}
+
+void
+p2tr_point_remove (P2trPoint *self)
+{
+ /* 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);
+}
+
+void
+p2tr_point_free (P2trPoint *self)
+{
+ p2tr_point_remove (self);
+ g_slice_free (P2trPoint, self);
+}
+
+P2trEdge*
+p2tr_point_has_edge_to (P2trPoint *start,
+ P2trPoint *end)
+{
+ GList *iter;
+
+ for (iter = start->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,
+ gboolean do_ref)
+{
+ P2trEdge* result = p2tr_point_has_edge_to (start, end);
+ if (result == NULL)
+ p2tr_exception_programmatic ("Tried to get an edge that doesn't exist!");
+ else
+ return do_ref ? p2tr_edge_ref (result) : 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;
+ P2trEdge *result;
+
+ 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!");
+
+ result = (P2trEdge*) g_list_cyclic_next (self->outgoing_edges, node)->data;
+ return p2tr_edge_ref (result);
+}
+
+P2trEdge*
+p2tr_point_edge_cw (P2trPoint* self,
+ P2trEdge *e)
+{
+ GList *node;
+ P2trEdge *result;
+
+ 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!");
+
+ result = (P2trEdge*) g_list_cyclic_prev (self->outgoing_edges, node)->data;
+ return p2tr_edge_ref (result);
+}
+
+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;
+}
+
+/**
+ * Increase the reference count of the given input point
+ * @param self - The point to ref
+ * @return The point given
+ */
+P2trPoint*
+p2tr_point_ref (P2trPoint *self)
+{
+ ++self->refcount;
+ return self;
+}
+
+void
+p2tr_point_unref (P2trPoint *self)
+{
+ g_assert (self->refcount > 0);
+ if (--self->refcount == 0)
+ p2tr_point_free (self);
+}
+
+P2trMesh*
+p2tr_point_get_mesh (P2trPoint *self)
+{
+ if (self->mesh)
+ return p2tr_mesh_ref (self->mesh);
+ else
+ return NULL;
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/point.h b/libs/poly2tri-c/poly2tri-c/refine/point.h
new file mode 100644
index 0000000..8b968fb
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/point.h
@@ -0,0 +1,99 @@
+/*
+ * 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_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;
+
+ /** The triangular mesh containing this point */
+ P2trMesh *mesh;
+};
+
+P2trPoint* p2tr_point_new (const P2trVector2 *c);
+
+P2trPoint* p2tr_point_new2 (gdouble x, gdouble y);
+
+P2trPoint* 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_has_edge_to (P2trPoint *start,
+ P2trPoint *end);
+
+P2trEdge* p2tr_point_get_edge_to (P2trPoint *start,
+ P2trPoint *end,
+ gboolean do_ref);
+
+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);
+
+P2trMesh* p2tr_point_get_mesh (P2trPoint *self);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/pslg.c b/libs/poly2tri-c/poly2tri-c/refine/pslg.c
new file mode 100644
index 0000000..59f4d0d
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/pslg.c
@@ -0,0 +1,105 @@
+/*
+ * 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 "pslg.h"
+
+static void
+free_bounded_line_if_not_null (gpointer line)
+{
+ p2tr_bounded_line_free ((P2trBoundedLine*)line);
+}
+
+/* A PSLG which is essentially a set of lines, will be represented by a
+ * hash table. When it will have an entry where both key and value are
+ * a line, it means that this is a new line and therefore should be
+ * freed. When it has an entry where the key is a line and the value is
+ * NULL, it means this is a line that should not be freed.
+ * This behaiour will be acheived by a NULL key free function and a
+ * real free function for values */
+P2trPSLG*
+p2tr_pslg_new (void)
+{
+ return g_hash_table_new_full (NULL, NULL, NULL, free_bounded_line_if_not_null);
+}
+
+void
+p2tr_pslg_add_new_line (P2trPSLG *pslg,
+ const P2trVector2 *start,
+ const P2trVector2 *end)
+{
+ P2trBoundedLine *line = p2tr_bounded_line_new (start, end);
+ /* We would like to free this line, so also add it as a value */
+ g_hash_table_insert (pslg, line, line);
+}
+
+/* Add a line that needs not to be freed */
+void
+p2tr_pslg_add_existing_line (P2trPSLG *pslg,
+ const P2trBoundedLine *line)
+{
+ g_hash_table_insert (pslg, (P2trBoundedLine*) line, NULL);
+}
+
+guint
+p2tr_pslg_size (P2trPSLG *pslg)
+{
+ return g_hash_table_size (pslg);
+}
+
+void
+p2tr_pslg_iter_init (P2trPSLGIter *iter,
+ P2trPSLG *pslg)
+{
+ g_hash_table_iter_init (iter, pslg);
+}
+
+gboolean
+p2tr_pslg_iter_next (P2trPSLGIter *iter,
+ const P2trBoundedLine **line)
+{
+ /* The values are always stored in the key */
+ return g_hash_table_iter_next (iter, (gpointer*)line, NULL);
+}
+
+gboolean
+p2tr_pslg_contains_line (P2trPSLG *pslg,
+ const P2trBoundedLine *line)
+{
+ return g_hash_table_lookup_extended (pslg, line, NULL, NULL);
+}
+
+void
+p2tr_pslg_free (P2trPSLG *pslg)
+{
+ g_hash_table_destroy (pslg);
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/pslg.h b/libs/poly2tri-c/poly2tri-c/refine/pslg.h
new file mode 100644
index 0000000..ef06bf3
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/pslg.h
@@ -0,0 +1,115 @@
+/*
+ * 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_PSLG_H__
+#define __P2TC_REFINE_PSLG_H__
+
+#include "utils.h"
+#include "vector2.h"
+#include "line.h"
+#include "bounded-line.h"
+
+typedef P2trHashSet P2trPSLG;
+typedef P2trHashSetIter P2trPSLGIter;
+
+/**
+ * Create a new PSLG. After finishing to use this PSLG, it should be
+ * freed by calling @ref p2tr_pslg_free
+ * @return A new empty PSLG
+ */
+P2trPSLG* p2tr_pslg_new (void);
+
+/**
+ * Add a new line to the PSLG, where the line is defined by two given
+ * points.
+ * @param[in] pslg The PSLG
+ * @param[in] start The first edge-point of the new line to add
+ * @param[in] end The second edge-point of the new line to add
+ */
+void p2tr_pslg_add_new_line (P2trPSLG *pslg,
+ const P2trVector2 *start,
+ const P2trVector2 *end);
+
+/**
+ * Add an existing P2trBoundedLine to the PSLG, so that the line will
+ * not be freed when the PSLG is freed. This line must not be freed
+ * before the PSLG is freed!
+ * @param[in] pslg The PSLG
+ * @param[in] line The existing line to add
+ */
+void p2tr_pslg_add_existing_line (P2trPSLG *pslg,
+ const P2trBoundedLine *line);
+
+/**
+ * Count how many lines are there in the PSLG
+ * @param[in] pslg The PSLG
+ * @return The amount of lines in the PSLG
+ */
+guint p2tr_pslg_size (P2trPSLG *pslg);
+
+/**
+ * Initialize an iterator to iterate over all the lines of the PSLG. The
+ * iterator will remain valid as long as the PSLG is not modified.
+ * @param[out] iter The iterator for this PSLG
+ * @param[in] pslg The PSLG
+ */
+void p2tr_pslg_iter_init (P2trPSLGIter *iter,
+ P2trPSLG *pslg);
+
+/**
+ * Advance the iterator to the next line of the PSLG
+ * @param[in] iter The PSLG iterator
+ * @param[out] line The next line of the PSLG
+ * @return TRUE if there was another line, FALSE if the iteration over
+ * all the lines was finished
+ */
+gboolean p2tr_pslg_iter_next (P2trPSLGIter *iter,
+ const P2trBoundedLine **line);
+
+/**
+ * Test whether the PSLG contains this line. The line comparision is
+ * done *by refrence* and not by value, so this function only test if
+ * the line at the given memory location is inside the PSLG.
+ * @param[in] pslg The PSLG
+ * @param[in] line The line to search for
+ * @return TRUE if the line was found in the PSLG, FALSE otherwise
+ */
+gboolean p2tr_pslg_contains_line (P2trPSLG *pslg,
+ const P2trBoundedLine *line);
+
+/**
+ * Free a PSLG and all of the resources allocated for it
+ * @param[in] pslg The PSLG to free
+ */
+void p2tr_pslg_free (P2trPSLG *pslg);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/refine.h b/libs/poly2tri-c/poly2tri-c/refine/refine.h
new file mode 100644
index 0000000..7828887
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/refine.h
@@ -0,0 +1,59 @@
+/*
+ * 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_H__
+#define __P2TC_REFINE_H__
+
+#include "utils.h"
+#include "rmath.h"
+
+#include "vector2.h"
+#include "circle.h"
+#include "line.h"
+#include "bounded-line.h"
+#include "pslg.h"
+
+#include "triangulation.h"
+
+#include "point.h"
+#include "edge.h"
+#include "triangle.h"
+#include "mesh.h"
+
+#include "vedge.h"
+#include "vtriangle.h"
+
+#include "cluster.h"
+#include "cdt.h"
+#include "refiner.h"
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/refiner.c b/libs/poly2tri-c/poly2tri-c/refine/refiner.c
new file mode 100644
index 0000000..92e2c32
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/refiner.c
@@ -0,0 +1,70 @@
+/*
+ * 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 "cdt.h"
+#include "delaunay-terminator.h"
+#include "refiner.h"
+
+#define P2TR_REFINER_REAL_TYPE P2trDelaunayTerminator
+
+#define P2T_REFINER_TO_IMP(X) ((P2TR_REFINER_REAL_TYPE*)(X))
+#define P2T_IMP_TO_REFINER(X) ((P2trRefiner*)(X))
+
+gboolean
+p2tr_refiner_false_too_big (P2trTriangle *tri)
+{
+ return FALSE;
+}
+
+P2trRefiner*
+p2tr_refiner_new (gdouble min_angle,
+ P2trTriangleTooBig size_control,
+ P2trCDT *cdt)
+{
+ return P2T_IMP_TO_REFINER (p2tr_dt_new (min_angle, size_control, cdt));
+}
+
+void
+p2tr_refiner_free (P2trRefiner *self)
+{
+ p2tr_dt_free (P2T_REFINER_TO_IMP (self));
+}
+
+void
+p2tr_refiner_refine (P2trRefiner *self,
+ gint max_steps,
+ P2trRefineProgressNotify on_progress)
+{
+ p2tr_dt_refine (P2T_REFINER_TO_IMP (self), max_steps, on_progress);
+}
+
diff --git a/libs/poly2tri-c/poly2tri-c/refine/refiner.h b/libs/poly2tri-c/poly2tri-c/refine/refiner.h
new file mode 100644
index 0000000..ffeba91
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/refiner.h
@@ -0,0 +1,61 @@
+/*
+ * 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_REFINER_H__
+#define __P2TC_REFINE_REFINER_H__
+
+#include <glib.h>
+#include "cdt.h"
+
+typedef struct P2trRefiner_ P2trRefiner;
+
+
+typedef gboolean (*P2trTriangleTooBig) (P2trTriangle *tri);
+
+gboolean p2tr_refiner_false_too_big (P2trTriangle *tri);
+
+
+typedef void (*P2trRefineProgressNotify) (P2trRefiner *refiner,
+ int step_number,
+ int max_steps);
+
+P2trRefiner* p2tr_refiner_new (gdouble min_angle,
+ P2trTriangleTooBig size_control,
+ P2trCDT *cdt);
+
+void p2tr_refiner_free (P2trRefiner *self);
+
+void p2tr_refiner_refine (P2trRefiner *self,
+ gint max_steps,
+ P2trRefineProgressNotify on_progress);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/rmath.c b/libs/poly2tri-c/poly2tri-c/refine/rmath.c
new file mode 100644
index 0000000..f644eaf
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/rmath.c
@@ -0,0 +1,301 @@
+/*
+ * 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 <math.h>
+#include <glib.h>
+#include "rmath.h"
+
+gdouble
+p2tr_math_length_sq (gdouble x1, gdouble y1,
+ gdouble x2, gdouble y2)
+{
+ return P2TR_VECTOR2_DISTANCE_SQ2 (x1, y1, x2, y2);
+}
+
+gdouble
+p2tr_math_length_sq2 (const P2trVector2 *pt1,
+ const P2trVector2 *pt2)
+{
+ return p2tr_math_length_sq (pt1->x, pt1->y, pt2->x, pt2->y);
+}
+
+static inline gdouble
+p2tr_matrix_det2 (gdouble a00, gdouble a01,
+ gdouble a10, gdouble a11)
+{
+ return a00 * a11 - a10 * a01;
+}
+
+static inline gdouble
+p2tr_matrix_det3 (gdouble a00, gdouble a01, gdouble a02,
+ gdouble a10, gdouble a11, gdouble a12,
+ gdouble a20, gdouble a21, gdouble a22)
+{
+ return
+ + a00 * (a11 * a22 - a21 * a12)
+ - a01 * (a10 * a22 - a20 * a12)
+ + a02 * (a10 * a21 - a20 * a11);
+}
+
+static inline gdouble
+p2tr_matrix_det4 (gdouble a00, gdouble a01, gdouble a02, gdouble a03,
+ gdouble a10, gdouble a11, gdouble a12, gdouble a13,
+ gdouble a20, gdouble a21, gdouble a22, gdouble a23,
+ gdouble a30, gdouble a31, gdouble a32, gdouble a33)
+{
+ return
+ + a00 * p2tr_matrix_det3 (a11, a12, a13,
+ a21, a22, a23,
+ a31, a32, a33)
+ - a01 * p2tr_matrix_det3 (a10, a12, a13,
+ a20, a22, a23,
+ a30, a32, a33)
+ + a02 * p2tr_matrix_det3 (a10, a11, a13,
+ a20, a21, a23,
+ a30, a31, a33)
+ - a03 * p2tr_matrix_det3 (a10, a11, a12,
+ a20, a21, a22,
+ a30, a31, a32);
+}
+
+void
+p2tr_math_triangle_circumcircle (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C,
+ P2trCircle *circle)
+{
+ /* | Ax Bx Cx |
+ * D = + | Ay By Cy | * 2
+ * | +1 +1 +1 |
+ *
+ * | Asq Bsq Csq |
+ * X = + | Ay By Cy | / D
+ * | 1 1 1 |
+ *
+ * | Asq Bsq Csq |
+ * Y = - | Ax Bx Cx | / D
+ * | 1 1 1 |
+ */
+ gdouble Asq = P2TR_VECTOR2_LEN_SQ (A);
+ gdouble Bsq = P2TR_VECTOR2_LEN_SQ (B);
+ gdouble Csq = P2TR_VECTOR2_LEN_SQ (C);
+
+ gdouble invD = 1 / (2 * p2tr_matrix_det3 (
+ A->x, B->x, C->x,
+ A->y, B->y, C->y,
+ 1, 1, 1));
+
+ circle->center.x = + p2tr_matrix_det3 (
+ Asq, Bsq, Csq,
+ A->y, B->y, C->y,
+ 1, 1, 1) * invD;
+
+ circle->center.y = - p2tr_matrix_det3 (
+ Asq, Bsq, Csq,
+ A->x, B->x, C->x,
+ 1, 1, 1) * invD;
+
+ circle->radius = sqrt (P2TR_VECTOR2_DISTANCE_SQ (A, &circle->center));
+}
+
+/* The point in triangle test which is implemented below is based on the
+ * algorithm which appears on:
+ *
+ * http://www.blackpawn.com/texts/pointinpoly/default.html
+ */
+void
+p2tr_math_triangle_barcycentric (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C,
+ const P2trVector2 *P,
+ gdouble *u,
+ gdouble *v)
+{
+ gdouble dot00, dot01, dot02, dot11, dot12, invDenom;
+
+ /* Compute the vectors offsetted so that A is the origin */
+ P2trVector2 v0, v1, v2;
+ p2tr_vector2_sub(C, A, &v0);
+ p2tr_vector2_sub(B, A, &v1);
+ p2tr_vector2_sub(P, A, &v2);
+
+ /* Compute dot products */
+ dot00 = P2TR_VECTOR2_DOT(&v0, &v0);
+ dot01 = P2TR_VECTOR2_DOT(&v0, &v1);
+ dot02 = P2TR_VECTOR2_DOT(&v0, &v2);
+ dot11 = P2TR_VECTOR2_DOT(&v1, &v1);
+ dot12 = P2TR_VECTOR2_DOT(&v1, &v2);
+
+ /* Compute barycentric coordinates */
+ invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
+ *u = (dot11 * dot02 - dot01 * dot12) * invDenom;
+ *v = (dot00 * dot12 - dot01 * dot02) * invDenom;
+}
+
+#define INTRIANGLE_EPSILON 0e-9
+
+P2trInTriangle
+p2tr_math_intriangle (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C,
+ const P2trVector2 *P)
+{
+ gdouble u, v;
+ return p2tr_math_intriangle2 (A, B, C, P, &u, &v);
+}
+
+P2trInTriangle
+p2tr_math_intriangle2 (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C,
+ const P2trVector2 *P,
+ gdouble *u,
+ gdouble *v)
+{
+ p2tr_math_triangle_barcycentric (A, B, C, P, u, v);
+
+ /* Check if point is in triangle - i.e. whether (u + v) < 1 and both
+ * u and v are positive */
+ if ((*u >= INTRIANGLE_EPSILON) && (*v >= INTRIANGLE_EPSILON) && (*u + *v < 1 - INTRIANGLE_EPSILON))
+ return P2TR_INTRIANGLE_IN;
+ else if ((*u >= -INTRIANGLE_EPSILON) && (*v >= -INTRIANGLE_EPSILON) && (*u + *v <= 1 + INTRIANGLE_EPSILON))
+ return P2TR_INTRIANGLE_ON;
+ else
+ return P2TR_INTRIANGLE_OUT;
+}
+
+/* The point in triangle circumcircle test, and the 3-point orientation
+ * test, are both based on the work of Jonathan Richard Shewchuk. The
+ * technique used here is described in his paper "Adaptive Precision
+ * Floating-Point Arithmetic and Fast Robust Geometric Predicates"
+ */
+
+#define ORIENT2D_EPSILON 1e-9
+
+P2trOrientation p2tr_math_orient2d (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C)
+{
+ /* We are trying to compute this determinant:
+ * |Ax Ay 1|
+ * |Bx By 1|
+ * |Cx Cy 1|
+ */
+ gdouble result = p2tr_matrix_det3 (
+ A->x, A->y, 1,
+ B->x, B->y, 1,
+ C->x, C->y, 1
+ );
+
+ if (result > ORIENT2D_EPSILON)
+ return P2TR_ORIENTATION_CCW;
+ else if (result < -ORIENT2D_EPSILON)
+ return P2TR_ORIENTATION_CW;
+ else
+ return P2TR_ORIENTATION_LINEAR;
+}
+
+#define INCIRCLE_EPSILON 1e-9
+
+/* Points must be given in CCW order!!!!! */
+P2trInCircle
+p2tr_math_incircle (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C,
+ const P2trVector2 *D)
+{
+ /* We are trying to compute this determinant:
+ * |Ax Ay Ax^2+Ay^2 1|
+ * |Bx By Bx^2+By^2 1|
+ * |Cx Cy Cx^2+Cy^2 1|
+ * |Dx Dy Dx^2+Dy^2 1|
+ */
+ gdouble result = p2tr_matrix_det4 (
+ A->x, A->y, P2TR_VECTOR2_LEN_SQ(A), 1,
+ B->x, B->y, P2TR_VECTOR2_LEN_SQ(B), 1,
+ C->x, C->y, P2TR_VECTOR2_LEN_SQ(C), 1,
+ D->x, D->y, P2TR_VECTOR2_LEN_SQ(D), 1
+ );
+
+ if (result > INCIRCLE_EPSILON)
+ return P2TR_INCIRCLE_IN;
+ else if (result < INCIRCLE_EPSILON)
+ return P2TR_INCIRCLE_OUT;
+ else
+ return P2TR_INCIRCLE_ON;
+}
+
+/* The point inside diametral-circle test and the point inside diametral
+ * lens test, are both based on the work of Jonathan Richard Shewchuk.
+ * The techniques used here are partially described in his paper
+ * "Delaunay Refinement Algorithms for Triangular Mesh Generation".
+ *
+ * W is inside the diametral circle (lens) of the line XY if and only if
+ * the angle XWY is larger than 90 (120) degrees. We know how to compute
+ * the cosine of that angle very easily like so:
+ *
+ * cos XWY = (WX * WY) / (|WX| * |WY|)
+ *
+ * Since XWY is larger than 90 (120) degrees, cos XWY <= 0 (-0.5) so:
+ *
+ * Diametral Circle | Diametral Lens
+ * -------------------------------+-----------------------------------
+ * 0 >= (WX * WY) / (|WX| * |WY|) | - 0.5 >= (WX * WY) / (|WX| * |WY|)
+ * 0 >= WX * WY | - 0.5 * |WX| * |WY| >= WX * WY
+ */
+
+gboolean
+p2tr_math_diametral_circle_contains (const P2trVector2 *X,
+ const P2trVector2 *Y,
+ const P2trVector2 *W)
+{
+ P2trVector2 WX, WY;
+
+ p2tr_vector2_sub(X, W, &WX);
+ p2tr_vector2_sub(Y, W, &WY);
+
+ return P2TR_VECTOR2_DOT(&WX, &WY) <= 0;
+}
+
+gboolean
+p2tr_math_diametral_lens_contains (const P2trVector2 *X,
+ const P2trVector2 *Y,
+ const P2trVector2 *W)
+{
+ P2trVector2 WX, WY;
+
+ p2tr_vector2_sub(X, W, &WX);
+ p2tr_vector2_sub(Y, W, &WY);
+
+ return P2TR_VECTOR2_DOT(&WX, &WY)
+ <= 0.5 * p2tr_vector2_norm(&WX) * p2tr_vector2_norm(&WY);
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/rmath.h b/libs/poly2tri-c/poly2tri-c/refine/rmath.h
new file mode 100644
index 0000000..68f9e87
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/rmath.h
@@ -0,0 +1,132 @@
+/*
+ * 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_MATH_H__
+#define __P2TC_REFINE_MATH_H__
+
+#include <glib.h>
+#include "vector2.h"
+#include "circle.h"
+
+gdouble p2tr_math_length_sq (gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2);
+
+gdouble p2tr_math_length_sq2 (const P2trVector2 *pt1,
+ const P2trVector2 *pt2);
+
+
+/**
+ * Find the circumscribing circle of a triangle defined by the given
+ * points.
+ * @param[in] A The first vertex of the triangle
+ * @param[in] B The second vertex of the triangle
+ * @param[in] C The third vertex of the triangle
+ * @param[out] circle The circumscribing circle of the triangle
+ */
+void p2tr_math_triangle_circumcircle (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C,
+ P2trCircle *circle);
+
+typedef enum
+{
+ P2TR_INTRIANGLE_OUT = -1,
+ P2TR_INTRIANGLE_ON = 0,
+ P2TR_INTRIANGLE_IN = 1
+} P2trInTriangle;
+
+/**
+ * Return the barycentric coordinates of a point inside a triangle. This
+ * means that the computation returns @ref u and @ref v so that the
+ * following equation is satisfied:
+ * {{{ AP = u * AB + v * AC }}}
+ *
+ * @param[in] A The first point of the triangle
+ * @param[in] B The second point of the triangle
+ * @param[in] C The third point of the triangle
+ * @param[in] P The point whose barycentric coordinates should be
+ * computed
+ * @param[out] u The first barycentric coordinate
+ * @param[out] v The second barycentric coordinate
+ */
+void p2tr_math_triangle_barcycentric (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C,
+ const P2trVector2 *P,
+ gdouble *u,
+ gdouble *v);
+
+P2trInTriangle p2tr_math_intriangle (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C,
+ const P2trVector2 *P);
+
+P2trInTriangle p2tr_math_intriangle2 (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C,
+ const P2trVector2 *P,
+ gdouble *u,
+ gdouble *v);
+
+typedef enum
+{
+ P2TR_ORIENTATION_CW = -1,
+ P2TR_ORIENTATION_LINEAR = 0,
+ P2TR_ORIENTATION_CCW = 1
+} P2trOrientation;
+
+P2trOrientation p2tr_math_orient2d (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C);
+
+typedef enum
+{
+ P2TR_INCIRCLE_IN,
+ P2TR_INCIRCLE_ON,
+ P2TR_INCIRCLE_OUT
+} P2trInCircle;
+
+P2trInCircle p2tr_math_incircle (const P2trVector2 *A,
+ const P2trVector2 *B,
+ const P2trVector2 *C,
+ const P2trVector2 *D);
+
+gboolean p2tr_math_diametral_circle_contains (const P2trVector2 *X,
+ const P2trVector2 *Y,
+ const P2trVector2 *W);
+
+gboolean p2tr_math_diametral_lens_contains (const P2trVector2 *X,
+ const P2trVector2 *Y,
+ const P2trVector2 *W);
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/triangle.c b/libs/poly2tri-c/poly2tri-c/refine/triangle.c
new file mode 100644
index 0000000..ce28dcc
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/triangle.c
@@ -0,0 +1,313 @@
+/*
+ * 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 <math.h>
+#include <glib.h>
+
+#include "utils.h"
+#include "rmath.h"
+
+#include "point.h"
+#include "edge.h"
+#include "triangle.h"
+#include "mesh.h"
+
+void
+p2tr_validate_edges_can_form_tri (P2trEdge *AB,
+ P2trEdge *BC,
+ P2trEdge *CA)
+{
+ if (AB != AB->mirror->mirror ||
+ BC != BC->mirror->mirror ||
+ CA != CA->mirror->mirror)
+ {
+ p2tr_exception_programmatic ("Bad edge mirroring!");
+ }
+
+ if (AB->end != P2TR_EDGE_START(BC)
+ || BC->end != P2TR_EDGE_START(CA)
+ || CA->end != P2TR_EDGE_START(AB))
+ {
+ p2tr_exception_programmatic ("Unexpected edge sequence for a triangle!");
+ }
+
+ if (AB == BC->mirror || BC == CA->mirror || CA == AB->mirror)
+ {
+ p2tr_exception_programmatic ("Repeated edge in a triangle!");
+ }
+}
+
+P2trTriangle*
+p2tr_triangle_new (P2trEdge *AB,
+ P2trEdge *BC,
+ P2trEdge *CA)
+{
+ gint i;
+ P2trTriangle *self = g_slice_new (P2trTriangle);
+
+ self->refcount = 0;
+
+#ifndef P2TC_NO_LOGIC_CHECKS
+ p2tr_validate_edges_can_form_tri (AB, BC, CA);
+#endif
+
+ switch (p2tr_math_orient2d(&CA->end->c, &AB->end->c, &BC->end->c))
+ {
+ case P2TR_ORIENTATION_CCW:
+ self->edges[0] = CA->mirror;
+ self->edges[1] = BC->mirror;
+ self->edges[2] = AB->mirror;
+ break;
+
+ case P2TR_ORIENTATION_CW:
+ self->edges[0] = AB;
+ self->edges[1] = BC;
+ self->edges[2] = CA;
+ break;
+
+ case P2TR_ORIENTATION_LINEAR:
+ p2tr_exception_geometric ("Can't make a triangle of linear points!");
+ }
+
+#ifndef P2TC_NO_LOGIC_CHECKS
+ p2tr_validate_edges_can_form_tri (self->edges[0], self->edges[1], self->edges[2]);
+
+ if (p2tr_math_orient2d (&P2TR_TRIANGLE_GET_POINT(self,0)->c,
+ &P2TR_TRIANGLE_GET_POINT(self,1)->c,
+ &P2TR_TRIANGLE_GET_POINT(self,2)->c) != P2TR_ORIENTATION_CW)
+ {
+ p2tr_exception_programmatic ("Bad ordering!");
+ }
+#endif
+
+ for (i = 0; i < 3; i++)
+ {
+#ifndef P2TC_NO_LOGIC_CHECKS
+ if (self->edges[i]->tri != NULL)
+ p2tr_exception_programmatic ("This edge is already in use by "
+ "another triangle!");
+#endif
+ self->edges[i]->tri = self;
+ p2tr_edge_ref (self->edges[i]);
+ p2tr_triangle_ref (self);
+ }
+
+ return p2tr_triangle_ref (self);
+}
+
+P2trTriangle*
+p2tr_triangle_ref (P2trTriangle *self)
+{
+ ++self->refcount;
+ return self;
+}
+
+void
+p2tr_triangle_unref (P2trTriangle *self)
+{
+ g_assert (self->refcount > 0);
+ if (--self->refcount == 0)
+ p2tr_triangle_free (self);
+}
+
+void
+p2tr_triangle_free (P2trTriangle *self)
+{
+ g_assert (p2tr_triangle_is_removed (self));
+ g_slice_free (P2trTriangle, self);
+}
+
+void
+p2tr_triangle_remove (P2trTriangle *self)
+{
+ gint i;
+ P2trMesh *mesh;
+
+ if (p2tr_triangle_is_removed (self))
+ return;
+
+ mesh = p2tr_triangle_get_mesh (self);
+
+ if (mesh != NULL)
+ {
+ p2tr_mesh_on_triangle_removed (mesh, self);
+ p2tr_mesh_unref (mesh); /* The get function reffed it */
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ self->edges[i]->tri = NULL;
+ p2tr_edge_unref (self->edges[i]);
+ self->edges[i] = NULL;
+ /* Although we lost reference to the triangle 3 rows above, we must
+ * not unref it untill here since we still use the struct until this
+ * line! */
+ p2tr_triangle_unref (self);
+ }
+}
+
+P2trMesh*
+p2tr_triangle_get_mesh (P2trTriangle *self)
+{
+ if (self->edges[0] != NULL)
+ return p2tr_edge_get_mesh (self->edges[0]);
+ else
+ return NULL;
+}
+
+gboolean
+p2tr_triangle_is_removed (P2trTriangle *self)
+{
+ return self->edges[0] == NULL;
+}
+
+P2trPoint*
+p2tr_triangle_get_opposite_point (P2trTriangle *self,
+ P2trEdge *e,
+ gboolean do_ref)
+{
+ P2trPoint *pt;
+ if (self->edges[0] == e || self->edges[0]->mirror == e)
+ pt = self->edges[1]->end;
+ else if (self->edges[1] == e || self->edges[1]->mirror == e)
+ pt = self->edges[2]->end;
+ else if (self->edges[2] == e || self->edges[2]->mirror == e)
+ pt = self->edges[0]->end;
+ else
+ p2tr_exception_programmatic ("The edge is not in the triangle!");
+
+ return do_ref ? p2tr_point_ref (pt) : pt;
+}
+
+P2trEdge*
+p2tr_triangle_get_opposite_edge (P2trTriangle *self,
+ P2trPoint *p)
+{
+ if (self->edges[0]->end == p)
+ return p2tr_edge_ref (self->edges[2]);
+ if (self->edges[1]->end == p)
+ return p2tr_edge_ref (self->edges[0]);
+ if (self->edges[2]->end == p)
+ return p2tr_edge_ref (self->edges[1]);
+
+ p2tr_exception_programmatic ("The point is not in the triangle!");
+}
+
+/**
+ * Angles return by this function are always in the range [0,180]
+ */
+gdouble
+p2tr_triangle_get_angle_at (P2trTriangle *self,
+ P2trPoint *p)
+{
+ if (p == self->edges[0]->end)
+ return p2tr_edge_angle_between (self->edges[0], self->edges[1]);
+ else if (p == self->edges[1]->end)
+ return p2tr_edge_angle_between (self->edges[1], self->edges[2]);
+ else if (p == self->edges[2]->end)
+ return p2tr_edge_angle_between (self->edges[2], self->edges[0]);
+
+ p2tr_exception_programmatic ("Can't find the point!");
+}
+
+gdouble
+p2tr_triangle_smallest_non_constrained_angle (P2trTriangle *self)
+{
+ gdouble result = G_MAXDOUBLE, angle;
+
+ if (! self->edges[0]->constrained || !self->edges[1]->constrained)
+ {
+ angle = p2tr_edge_angle_between(self->edges[0], self->edges[1]);
+ result = MIN(result, angle);
+ }
+
+ if (!self->edges[1]->constrained || !self->edges[2]->constrained)
+ {
+ angle = p2tr_edge_angle_between(self->edges[1], self->edges[2]);
+ result = MIN(result, angle);
+ }
+
+ if (!self->edges[2]->constrained || !self->edges[0]->constrained)
+ {
+ angle = p2tr_edge_angle_between(self->edges[2], self->edges[0]);
+ result = MIN(result, angle);
+ }
+
+ return result;
+}
+
+void
+p2tr_triangle_get_circum_circle (P2trTriangle *self,
+ P2trCircle *circle)
+{
+ p2tr_math_triangle_circumcircle (
+ &P2TR_TRIANGLE_GET_POINT(self,0)->c,
+ &P2TR_TRIANGLE_GET_POINT(self,1)->c,
+ &P2TR_TRIANGLE_GET_POINT(self,2)->c,
+ circle);
+}
+
+P2trInCircle
+p2tr_triangle_circumcircle_contains_point (P2trTriangle *self,
+ const P2trVector2 *pt)
+{
+ /* Points must be given in CCW order! */
+ return p2tr_math_incircle (
+ &P2TR_TRIANGLE_GET_POINT(self,2)->c,
+ &P2TR_TRIANGLE_GET_POINT(self,1)->c,
+ &P2TR_TRIANGLE_GET_POINT(self,0)->c,
+ pt);
+}
+
+P2trInTriangle
+p2tr_triangle_contains_point (P2trTriangle *self,
+ const P2trVector2 *pt)
+{
+ return p2tr_math_intriangle (
+ &P2TR_TRIANGLE_GET_POINT(self,0)->c,
+ &P2TR_TRIANGLE_GET_POINT(self,1)->c,
+ &P2TR_TRIANGLE_GET_POINT(self,2)->c,
+ pt);
+}
+
+P2trInTriangle
+p2tr_triangle_contains_point2 (P2trTriangle *self,
+ const P2trVector2 *pt,
+ gdouble *u,
+ gdouble *v)
+{
+ return p2tr_math_intriangle2 (
+ &P2TR_TRIANGLE_GET_POINT(self,0)->c,
+ &P2TR_TRIANGLE_GET_POINT(self,1)->c,
+ &P2TR_TRIANGLE_GET_POINT(self,2)->c,
+ pt, u, v);
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/triangle.h b/libs/poly2tri-c/poly2tri-c/refine/triangle.h
new file mode 100644
index 0000000..bb18cfa
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/triangle.h
@@ -0,0 +1,94 @@
+/*
+ * 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_TRIANGLE_H__
+#define __P2TC_REFINE_TRIANGLE_H__
+
+#include <glib.h>
+#include "rmath.h"
+#include "triangulation.h"
+
+/**
+ * @struct P2trTriangle_
+ * A struct for a triangle in a triangular mesh
+ */
+struct P2trTriangle_
+{
+ P2trEdge* edges[3];
+
+ guint refcount;
+};
+
+P2trTriangle* p2tr_triangle_new (P2trEdge *AB,
+ P2trEdge *BC,
+ P2trEdge *CA);
+
+P2trTriangle* p2tr_triangle_ref (P2trTriangle *self);
+
+void p2tr_triangle_unref (P2trTriangle *self);
+
+void p2tr_triangle_free (P2trTriangle *self);
+
+void p2tr_triangle_remove (P2trTriangle *self);
+
+P2trMesh* p2tr_triangle_get_mesh (P2trTriangle *self);
+
+gboolean p2tr_triangle_is_removed (P2trTriangle *self);
+
+P2trPoint* p2tr_triangle_get_opposite_point (P2trTriangle *self,
+ P2trEdge *e,
+ gboolean do_ref);
+
+P2trEdge* p2tr_triangle_get_opposite_edge (P2trTriangle *self,
+ P2trPoint *p);
+
+gdouble p2tr_triangle_get_angle_at (P2trTriangle *self,
+ P2trPoint *p);
+
+gdouble p2tr_triangle_smallest_non_constrained_angle (P2trTriangle *self);
+
+void p2tr_triangle_get_circum_circle (P2trTriangle *self,
+ P2trCircle *circle);
+
+P2trInCircle p2tr_triangle_circumcircle_contains_point (P2trTriangle *self,
+ const P2trVector2 *pt);
+
+P2trInTriangle p2tr_triangle_contains_point (P2trTriangle *self,
+ const P2trVector2 *pt);
+
+P2trInTriangle p2tr_triangle_contains_point2 (P2trTriangle *self,
+ const P2trVector2 *pt,
+ gdouble *u,
+ gdouble *v);
+
+#define P2TR_TRIANGLE_GET_POINT(tr,index) ((tr)->edges[((index)+3-1)%3]->end)
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/triangulation.h b/libs/poly2tri-c/poly2tri-c/refine/triangulation.h
new file mode 100644
index 0000000..4a93ac0
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/triangulation.h
@@ -0,0 +1,49 @@
+/*
+ * 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_TRIANGULATION_H__
+#define __P2TC_REFINE_TRIANGULATION_H__
+
+/** \ingroup P2trPoint */
+typedef struct P2trPoint_ P2trPoint;
+/** \ingroup P2trEdge */
+typedef struct P2trEdge_ P2trEdge;
+/** \ingroup P2trTriangle */
+typedef struct P2trTriangle_ P2trTriangle;
+/** \ingroup P2trMesh */
+typedef struct P2trMesh_ P2trMesh;
+
+/** \ingroup P2trVEdge */
+typedef struct P2trVEdge_ P2trVEdge;
+/** \ingroup P2trVTriangle */
+typedef struct P2trVTriangle_ P2trVTriangle;
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/utils.c b/libs/poly2tri-c/poly2tri-c/refine/utils.c
new file mode 100644
index 0000000..d9d7db4
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/utils.c
@@ -0,0 +1,51 @@
+/*
+ * 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 <stdarg.h>
+#include <glib.h>
+
+#include "utils.h"
+
+GList*
+p2tr_utils_new_reversed_pointer_list (int count, ...)
+{
+ int i;
+ va_list args;
+ GList *result = NULL;
+
+ va_start (args, count);
+ for (i = 0; i < count; i++)
+ result = g_list_prepend (result, va_arg (args, gpointer));
+ va_end (args);
+
+ return result;
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/utils.h b/libs/poly2tri-c/poly2tri-c/refine/utils.h
new file mode 100644
index 0000000..576476f
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/utils.h
@@ -0,0 +1,88 @@
+/*
+ * 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_UTILS_H__
+#define __P2TC_REFINE_UTILS_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <glib.h>
+
+ /* The code for the Hash Set is partially based on the example given at
+ * http://developer.gnome.org/glib/2.29/glib-Hash-Tables.html
+ */
+
+ typedef GHashTable P2trHashSet;
+ typedef GHashTableIter P2trHashSetIter;
+
+#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_STMT_START \
+{ \
+ /* The "obvious" code (presented below) won't work: */ \
+ /* g_hash_table_insert ((set), (element), (element)) */ \
+ /* since it will cause double evaluation of (element) which is a */ \
+ /* problem! */ \
+ gpointer P2TR_HASH_SET_ELEM = (element); \
+ g_hash_table_insert ((set), P2TR_HASH_SET_ELEM, P2TR_HASH_SET_ELEM); \
+} \
+G_STMT_END
+#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_size(set) g_hash_table_size(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)
+#define p2tr_hash_set_iter_remove(iter) g_hash_table_iter_remove ((iter))
+
+#define g_list_cyclic_prev(list,elem) (((elem)->prev != NULL) ? (elem)->prev : g_list_last ((elem)))
+#define g_list_cyclic_next(list,elem) (((elem)->next != NULL) ? (elem)->next : g_list_first ((elem)))
+
+#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
+
+GList* p2tr_utils_new_reversed_pointer_list (int count, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/vector2.c b/libs/poly2tri-c/poly2tri-c/refine/vector2.c
new file mode 100644
index 0000000..b6e3359
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/vector2.c
@@ -0,0 +1,84 @@
+/*
+ * 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 <math.h>
+#include <glib.h>
+#include "vector2.h"
+
+gdouble
+p2tr_vector2_dot (const P2trVector2 *a,
+ const P2trVector2 *b)
+{
+ return P2TR_VECTOR2_DOT (a, b);
+}
+
+gboolean
+p2tr_vector2_is_same (const P2trVector2 *a,
+ const P2trVector2 *b)
+{
+ if (a == NULL || b == NULL)
+ return ! ((a == NULL) ^ (b == NULL));
+ else
+ return a->x == b->x && a->y == b->y;
+}
+
+void
+p2tr_vector2_sub (const P2trVector2 *a,
+ const P2trVector2 *b,
+ P2trVector2 *dest)
+{
+ dest->x = a->x - b->x;
+ dest->y = a->y - b->y;
+}
+
+void
+p2tr_vector2_center (const P2trVector2 *a,
+ const P2trVector2 *b,
+ P2trVector2 *dest)
+{
+ dest->x = (a->x + b->x) * 0.5;
+ dest->y = (a->y + b->y) * 0.5;
+}
+
+gdouble
+p2tr_vector2_norm (const P2trVector2 *v)
+{
+ return sqrt (P2TR_VECTOR2_LEN_SQ (v));
+}
+
+void
+p2tr_vector2_copy (P2trVector2 *dest,
+ const P2trVector2 *src)
+{
+ dest->x = src->x;
+ dest->y = src->y;
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/vector2.h b/libs/poly2tri-c/poly2tri-c/refine/vector2.h
new file mode 100644
index 0000000..0573da2
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/vector2.h
@@ -0,0 +1,101 @@
+/*
+ * 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 __P2TR_REFINE_VECTOR2_H__
+#define __P2TR_REFINE_VECTOR2_H__
+
+#include <glib.h>
+
+/**
+ * \struct P2trVector2
+ * A struct for representing a vector with 2 coordinates (a point in 2D)
+ */
+typedef struct {
+ /** The first coordinate of the vector */
+ gdouble x;
+ /** The second coordinate of the vector */
+ gdouble y;
+} P2trVector2;
+
+#define P2TR_VECTOR2_LEN_SQ2(X, Y) \
+ ((X) * (X) + (Y) * (Y))
+
+#define P2TR_VECTOR2_LEN_SQ(V) \
+ (P2TR_VECTOR2_LEN_SQ2((V)->x, (V)->y))
+
+#define P2TR_VECTOR2_DOT(V1,V2) \
+ ((V1)->x * (V2)->x + (V1)->y * (V2)->y)
+
+#define P2TR_VECTOR2_DISTANCE_SQ2(X1,Y1,X2,Y2) \
+ (P2TR_VECTOR2_LEN_SQ2((X1) - (X2), (Y1) - (Y2)))
+
+#define P2TR_VECTOR2_DISTANCE_SQ(V1,V2) \
+ (P2TR_VECTOR2_DISTANCE_SQ2((V1)->x, (V1)->y, (V2)->x, (V2)->y))
+
+/** Compute the dot product of two vectors */
+gdouble p2tr_vector2_dot (const P2trVector2 *a, const P2trVector2 *b);
+
+/** Check if all the coordinates of the two vectors are the same */
+gboolean p2tr_vector2_is_same (const P2trVector2 *a, const P2trVector2 *b);
+
+/**
+ * Compute the difference of two vectors
+ * @param[in] a The vector to subtract from
+ * @param[in] b The vector to be subtracted
+ * @param[out] dest The vector in which the result should be stored
+ */
+void p2tr_vector2_sub (const P2trVector2 *a, const P2trVector2 *b, P2trVector2 *dest);
+
+/**
+ * Compute the center point of the edge defined between two points
+ * @param[in] a The first side of the edge
+ * @param[in] b The second side of the edge
+ * @param[out] dest The vector in which the result should be stored
+ */
+void p2tr_vector2_center (const P2trVector2 *a, const P2trVector2 *b, P2trVector2 *dest);
+
+/**
+ * Compute the norm of a vector (the length of the line from the origin
+ * to the 2D point it represents)
+ * @param[in] v The vector whose norm should be computed
+ * @return The norm of the vector
+ */
+gdouble p2tr_vector2_norm (const P2trVector2 *v);
+
+/**
+ * Copy a vector
+ * @param[out] dest The destination of the copy operation
+ * @param[in] src The vector to copy
+ */
+void p2tr_vector2_copy (P2trVector2 *dest, const P2trVector2 *src);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/vedge.c b/libs/poly2tri-c/poly2tri-c/refine/vedge.c
new file mode 100644
index 0000000..74a6a31
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/vedge.c
@@ -0,0 +1,228 @@
+/*
+ * 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 <math.h>
+#include <glib.h>
+
+#include "point.h"
+#include "edge.h"
+#include "vedge.h"
+#include "mesh.h"
+
+static void
+p2tr_vedge_init (P2trVEdge *self,
+ P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained)
+{
+ self->start = start;
+ self->end = end;
+ self->constrained = constrained;
+ self->refcount = 0;
+}
+
+P2trVEdge*
+p2tr_vedge_new (P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained)
+{
+ P2trVEdge *self = g_slice_new (P2trVEdge);
+
+ p2tr_vedge_init (self, start, end, constrained);
+
+ p2tr_point_ref (start);
+ p2tr_point_ref (end);
+
+ ++self->refcount;
+ return self;
+}
+
+P2trVEdge*
+p2tr_vedge_new2 (P2trEdge *real)
+{
+ return p2tr_vedge_new (P2TR_EDGE_START (real), real->end,
+ real->constrained);
+}
+
+P2trVEdge*
+p2tr_vedge_ref (P2trVEdge *self)
+{
+ ++self->refcount;
+ return self;
+}
+
+void
+p2tr_vedge_unref (P2trVEdge *self)
+{
+ g_assert (self->refcount > 0);
+ if (--self->refcount == 0)
+ p2tr_vedge_free (self);
+}
+
+P2trEdge*
+p2tr_vedge_is_real (P2trVEdge *self)
+{
+ return p2tr_point_has_edge_to (self->start, self->end);
+}
+
+void
+p2tr_vedge_create (P2trVEdge *self)
+{
+ P2trMesh *mesh;
+ P2trEdge *edge;
+
+ g_assert (! p2tr_vedge_is_real (self));
+
+ mesh = p2tr_vedge_get_mesh (self);
+ if (mesh != NULL)
+ {
+ edge = p2tr_mesh_new_edge (mesh, self->start, self->end, self->constrained);
+ p2tr_mesh_unref (mesh);
+ }
+ else
+ edge = p2tr_edge_new (self->start, self->end, self->constrained);
+
+ p2tr_edge_unref (edge);
+}
+
+void
+p2tr_vedge_remove (P2trVEdge *self)
+{
+ P2trEdge *edge = p2tr_vedge_is_real (self);
+
+ g_assert (edge != NULL);
+
+ p2tr_edge_remove (edge);
+}
+
+void
+p2tr_vedge_free (P2trVEdge *self)
+{
+ p2tr_point_unref (self->start);
+ p2tr_point_unref (self->end);
+ g_slice_free (P2trVEdge, self);
+}
+
+P2trMesh*
+p2tr_vedge_get_mesh (P2trVEdge *self)
+{
+ return p2tr_point_get_mesh (self->end);
+}
+
+P2trEdge*
+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;
+}
+
+P2trVEdgeSet*
+p2tr_vedge_set_new ()
+{
+ return p2tr_hash_set_new (
+ (GHashFunc) p2tr_vedge_undirected_hash,
+ (GEqualFunc) p2tr_vedge_undirected_equals,
+ NULL
+ );
+}
+
+void
+p2tr_vedge_set_add (P2trVEdgeSet *self,
+ P2trEdge *to_flip)
+{
+ p2tr_vedge_set_add2 (self, p2tr_vedge_new2 (to_flip));
+ p2tr_edge_unref (to_flip);
+}
+
+void
+p2tr_vedge_set_add2 (P2trVEdgeSet *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_vedge_set_pop (P2trVEdgeSet *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;
+}
+
+guint
+p2tr_vedge_set_size (P2trVEdgeSet *self)
+{
+ return p2tr_hash_set_size (self);
+}
+
+void
+p2tr_vedge_set_free (P2trVEdgeSet *self)
+{
+ g_assert (p2tr_hash_set_size (self) == 0);
+ p2tr_hash_set_free (self);
+}
+
+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/libs/poly2tri-c/poly2tri-c/refine/vedge.h b/libs/poly2tri-c/poly2tri-c/refine/vedge.h
new file mode 100644
index 0000000..30f0e8f
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/vedge.h
@@ -0,0 +1,143 @@
+/*
+ * 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_VEDGE_H__
+#define __P2TC_REFINE_VEDGE_H__
+
+#include <glib.h>
+#include "utils.h"
+#include "triangulation.h"
+
+/**
+ * @struct P2trVEdge_
+ * A struct for representing a potential ("virtual") edge in a
+ * triangular mesh
+ */
+struct P2trVEdge_
+{
+ /** The start point of this virtual edge */
+ P2trPoint *start;
+ /** The end point of this virtual edge */
+ P2trPoint *end;
+ /** A flag to make whether this is a constrained edge */
+ gboolean constrained;
+ /** A count of references to the virtual edge */
+ guint refcount;
+};
+
+P2trVEdge* p2tr_vedge_new (P2trPoint *start,
+ P2trPoint *end,
+ gboolean constrained);
+
+P2trVEdge* p2tr_vedge_new2 (P2trEdge *real);
+
+P2trVEdge* p2tr_vedge_ref (P2trVEdge *self);
+
+void p2tr_vedge_unref (P2trVEdge *self);
+
+void p2tr_vedge_free (P2trVEdge *self);
+
+P2trMesh* p2tr_vedge_get_mesh (P2trVEdge *self);
+
+P2trEdge* p2tr_vedge_is_real (P2trVEdge *self);
+
+void p2tr_vedge_create (P2trVEdge *self);
+
+void p2tr_vedge_remove (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);
+
+/**
+ * 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 P2trVEdgeSet;
+
+/**
+ * Create a new flip-set - a set of virtual edges that should possibly
+ * be flipped to restore the Constrained Delaunay property to a
+ * triangulation
+*/
+P2trVEdgeSet* p2tr_vedge_set_new ();
+
+/**
+ * Add the given edge to the flip set. THE EDGE MUST HAVE BEEN REFFED
+ * BEFORE THE CALL TO THIS FUNCTION!
+ */
+void p2tr_vedge_set_add (P2trVEdgeSet *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_vedge_set_add2 (P2trVEdgeSet *self,
+ P2trVEdge *to_flip);
+
+/**
+ * Try popping a virtual edge from the set. If succeeds, THE RETURNED
+ * VIRTUAL EDGE MUST BE UNREFFED!
+ */
+gboolean p2tr_vedge_set_pop (P2trVEdgeSet *self,
+ P2trVEdge **value);
+
+/**
+ * Returns the amount of virtual edges currently in the set
+ */
+guint p2tr_vedge_set_size (P2trVEdgeSet *self);
+
+/**
+ * Free the flip set. IT IS THE REPONSIBILITY OF THE CALLER TO MAKE
+ * SURE NO VIRTUAL EDGES WERE LEFT IN THE SET!
+ */
+void p2tr_vedge_set_free (P2trVEdgeSet *self);
+
+gboolean p2tr_vedge_undirected_equals (const P2trVEdge *e1,
+ const P2trVEdge *e2);
+
+guint p2tr_vedge_undirected_hash (const P2trVEdge *edge);
+
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/visibility.c b/libs/poly2tri-c/poly2tri-c/refine/visibility.c
new file mode 100644
index 0000000..eab71ed
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/visibility.c
@@ -0,0 +1,438 @@
+/*
+ * 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.
+ */
+
+/* Given a polygon "Poly" (a list of bounded lines), a point "P" and a
+ * a planar straight line graph (pslg) "PSLG", the question is if
+ * there is a straight line from "P" to some point in/on "Poly" so that
+ * the line does not intersect any of the lines of "PSLG".
+ *
+ * In this file is an algorithm for answering the above question, and
+ * it's pseudo-code is hereby presented:
+ *
+ * IsVisible(G, Poly, P):
+ * ----------------------
+ * { G = (V,E) - The PSLG where E is the set of edges in the graph }
+ * { Poly - A polygon (a list of edges) }
+ * { P - The point we are checking whether is "visible" from }
+ * { Poly }
+ *
+ * W <- Some point in T (for example, center of weight)
+ *
+ * # A set of edges from @PSLG known to intersect some potential lines
+ * # from @P to @Poly
+ * KnownBlocks <- {}
+ *
+ * # A set of points on @Poly which should be checked whether a line
+ * # from them to @P is not obstructed by any of the edges of @PSLG
+ * SecondPoint <- {W}
+ *
+ * WHILE SecondPoint is not empty:
+ *
+ * # Pick some point to check
+ * S <- Some point from SecondPoint
+ * SecondPoint <- SecondPoint \ {S}
+ *
+ * PS <- The infinite line going through P and S
+ *
+ * IF PS intersects @Poly:
+ *
+ * IF there is an edge B=(u,v) (from E) that intersects PS so that
+ * the intersection is between @Poly and @P:
+ *
+ * IF B is not in KnownBlocks:
+ * # Try new lines going through the end points of this edge
+ * SecondPoint <- SecondPoint + {u,v}
+ * KnownBlocks <- KnownBlocks + {B}
+ *
+ * ELSE:
+ * # Nothing to do - we already tried/are trying to handle this
+ * # blocking edge by going around it
+ *
+ * ELSE:
+ * RETURN "Visible"
+ *
+ * ELSE:
+ * # PS doesn't help anyway, no matter if it's blocked or not,
+ * # since it does not reach the polygon
+ *
+ * RETURN "Ocluded"
+ */
+
+#include <glib.h>
+#include "bounded-line.h"
+#include "pslg.h"
+
+
+static gboolean
+find_closest_intersection (P2trPSLG *pslg,
+ P2trLine *line,
+ P2trVector2 *close_to,
+ P2trVector2 *dest)
+{
+ gdouble distance_sq = G_MAXDOUBLE;
+ gboolean found = FALSE;
+
+ const P2trBoundedLine *pslg_line = NULL;
+ P2trPSLGIter pslg_iter;
+ P2trVector2 temp;
+
+ p2tr_pslg_iter_init (&pslg_iter, pslg);
+
+ while (p2tr_pslg_iter_next (&pslg_iter, &pslg_line))
+ {
+ if (p2tr_line_intersection (&pslg_line->infinite, line, &temp)
+ == P2TR_LINE_RELATION_INTERSECTING)
+ {
+ gdouble test_distance_sq = P2TR_VECTOR2_DISTANCE_SQ (&temp, close_to);
+
+ found = TRUE;
+
+ if (test_distance_sq < distance_sq)
+ {
+ distance_sq = test_distance_sq;
+ }
+ }
+ }
+
+ if (found && dest != NULL)
+ p2tr_vector2_copy (dest, &temp);
+
+ return found;
+}
+
+static void
+find_point_in_polygon (P2trPSLG *polygon,
+ P2trVector2 *out_point)
+{
+ P2trPSLGIter iter;
+ const P2trBoundedLine *line = NULL;
+
+ g_assert (p2tr_pslg_size (polygon) >= 1);
+
+ p2tr_pslg_iter_init (&iter, polygon);
+ p2tr_pslg_iter_next (&iter, &line);
+
+ out_point->x = (line->start.x + line->end.x) / 2;
+ out_point->y = (line->start.y + line->end.y) / 2;
+}
+
+#ifdef EXPERIMENTAL_VISIBILITY
+static P2trBoundedLine*
+pslg_line_intersection (P2trPSLG *pslg,
+ P2trBoundedLine *line)
+{
+ P2trPSLGIter iter;
+ P2trBoundedLine *pslg_line = NULL;
+
+ p2tr_pslg_iter_init (&iter, pslg);
+ while (p2tr_pslg_iter_next (&iter, &pslg_line))
+ if (p2tr_bounded_line_intersect (line, pslg_line))
+ return pslg_line;
+
+ return NULL;
+}
+
+gboolean
+p2tr_pslg_visibility_check (P2trPSLG *pslg,
+ P2trVector2 *point,
+ P2trPSLG *polygon)
+{
+ P2trPSLG *known_blocks;
+ GArray *second_points;
+ gboolean found_visibility_path = FALSE;
+
+ /* W <- Some point in T (for example, center of weight) */
+ P2trVector2 W;
+ find_point_in_polygon (polygon, &W);
+
+ /* KnownBlocks <- {} */
+ known_blocks = p2tr_pslg_new ();
+
+ /* SecondPoint <- {W} */
+ second_points = g_array_new (FALSE, FALSE, sizeof(P2trVector2));
+ g_array_append_val (second_points, W);
+
+ while ((! found_visibility_path) && second_points->len > 0)
+ {
+ P2trVector2 S;
+ P2trBoundedLine PS;
+ P2trVector2 poly_intersection;
+
+ /* S <- Some point from SecondPoint */
+ p2tr_vector2_copy (&S, &g_array_index(second_points, P2trVector2, 0));
+ /* SecondPoint <- SecondPoint \ {S} */
+ g_array_remove_index_fast (second_points, 0);
+
+ /* PS <- The infinite line going through P and S */
+ p2tr_bounded_line_init (&PS, &S, point);
+
+ /* IF PS intersects @Poly */
+ if (find_closest_intersection (polygon, &PS.infinite, point, &poly_intersection))
+ {
+ P2trBoundedLine PS_exact, *B;
+
+ /* IF there is an edge B=(u,v) (from E) that intersects PS */
+ p2tr_bounded_line_init (&PS_exact, point, &poly_intersection);
+ B = pslg_line_intersection (pslg, &PS_exact);
+
+ if (B != NULL)
+ {
+ /* IF B is not in KnownBlocks: */
+ if (! p2tr_pslg_contains_line (known_blocks, B))
+ {
+ /* SecondPoint <- SecondPoint + {u,v} */
+ g_array_append_val (second_points, B->start);
+ g_array_append_val (second_points, B->end);
+ /* KnownBlocks <- KnownBlocks + {B} */
+ p2tr_pslg_add_existing_line (known_blocks, B);
+ }
+ }
+ else
+ {
+ found_visibility_path = TRUE;
+ }
+ }
+ }
+
+ g_array_free (second_points, TRUE);
+ p2tr_pslg_free (known_blocks);
+
+ return found_visibility_path;
+}
+#else
+
+/* Refer to the "Ray casting algorithm":
+ * http://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm
+ */
+static gboolean
+PointIsInsidePolygon (P2trVector2 *vec,
+ P2trPSLG *polygon)
+{
+ P2trHashSetIter iter;
+ const P2trBoundedLine *polyline = NULL;
+ int count = 0;
+
+ /* So, if we work on the X axis, what we want to check is how many
+ * segments of the polygon cross the line (-inf,y)->(x,y) */
+ p2tr_pslg_iter_init (&iter, polygon);
+ while (p2tr_pslg_iter_next (&iter, &polyline))
+ {
+ if ((polyline->start.y - vec->y) * (polyline->end.y - vec->y) >= 0)
+ continue; /* The line doesn't cross the horizontal line Y = vec->y */
+ if (MIN (polyline->start.x, polyline->end.x) <= vec->x)
+ count++;
+ }
+ return (count % 2) == 1;
+}
+
+/* If the bounded line intersects the polygon in more than two places,
+ * then the answer is simply NO - the line is not completly outside the
+ * polygon.
+ * Else, if the bounded line intersects the polygon twice, we analyze
+ * its end points and middle point:
+ * - If both end-points are inside/on:
+ * - Test the midpoint - it it's inside then the line goes inside the
+ * polygon, otherwise it goes outside (remember, we said it
+ * intersects the polygon exactly twice!)
+ * - Otherwise, there must be a subsegment of the poly-line which is
+ * partially inside!
+ * Else, if it intersects exactly once:
+ * - If both end-points are inside/on then it's partially inside.
+ * - If exactly one end-points is inside/on then decide by the middle
+ * point (if it's partially inside then so is the line)
+ * - If both end-points are outside - CAN'T HAPPEN WITH EXACTLY ONE INTERSECTION!
+ * Else, if it does not intersect:
+ * - Test any point inside the bounded line (end-points, middle points,
+ * etc.). If it's inside then the bounded line is inside. Otherwise
+ * it is outside
+ */
+static gboolean
+LineIsOutsidePolygon (P2trBoundedLine *line,
+ P2trPSLG *polygon)
+{
+ P2trHashSetIter iter;
+ const P2trBoundedLine *polyline = NULL;
+ P2trVector2 middle;
+ gint intersection_count = 0, inside_count = 0;
+
+ p2tr_pslg_iter_init (&iter, polygon);
+ while (p2tr_pslg_iter_next (&iter, &polyline))
+ {
+ if (p2tr_bounded_line_intersect (polyline, line))
+ if (++intersection_count > 2)
+ return FALSE;
+ }
+
+ inside_count += (PointIsInsidePolygon (&line->start, polygon) ? 1 : 0);
+ inside_count += (PointIsInsidePolygon (&line->end, polygon) ? 1 : 0);
+
+ /* To decrease the chance of numeric errors when working on the edge points of
+ * the line, the point we will test is the middle of the input line */
+ middle.x = (line->start.x + line->end.x) / 2;
+ middle.y = (line->start.y + line->end.y) / 2;
+
+ if (intersection_count == 2)
+ {
+ if (inside_count == 2) return PointIsInsidePolygon (&middle, polygon);
+ else return TRUE;
+ }
+ else if (intersection_count == 1)
+ {
+ if (inside_count == 2) return TRUE;
+ else return PointIsInsidePolygon (&middle, polygon);
+ }
+ else return inside_count > 0;
+}
+
+static gboolean
+TryVisibilityAroundBlock(P2trPSLG *PSLG,
+ P2trVector2 *P,
+ P2trPSLG *ToSee,
+ P2trPSLG *KnownBlocks,
+ GQueue *BlocksForTest,
+ /* Try on the edges of this block */
+ const P2trBoundedLine *BlockBeingTested,
+ const P2trVector2 *SideOfBlock)
+{
+ const P2trVector2 *S = SideOfBlock;
+ P2trVector2 ClosestIntersection;
+ P2trBoundedLine PS;
+
+ p2tr_bounded_line_init (&PS, P, S);
+
+ if (find_closest_intersection (ToSee, &PS.infinite, P, &ClosestIntersection))
+ {
+ P2trPSLGIter iter;
+ P2trBoundedLine PK;
+ const P2trBoundedLine *Segment = NULL;
+ p2tr_bounded_line_init (&PK, P, &ClosestIntersection);
+
+ /* Now we must make sure that the bounded line PK is inside
+ * the polygon, because otherwise it is not considered as a
+ * valid visibility path */
+
+ p2tr_pslg_iter_init (&iter, PSLG);
+ while (p2tr_pslg_iter_next (&iter, &Segment))
+ {
+ if (Segment == BlockBeingTested)
+ continue;
+
+ /* If we have two segments with a shared point,
+ * the point should not be blocked by any of them
+ */
+ if (p2tr_vector2_is_same (SideOfBlock, &(Segment->start))
+ || p2tr_vector2_is_same (SideOfBlock, &(Segment->end)))
+ continue;
+
+ if (p2tr_bounded_line_intersect (Segment, &PK))
+ {
+ if (g_queue_find (BlocksForTest, Segment))
+ {
+ g_queue_push_tail (BlocksForTest, (P2trBoundedLine*)Segment);
+ }
+ /* obstruction found! */
+ return FALSE;
+ }
+ }
+
+ if (LineIsOutsidePolygon (&PK, PSLG))
+ return FALSE;
+
+ /* No obstruction! */
+ return TRUE;
+ }
+ /* No intersection for this attempt, continue */
+ return FALSE;
+}
+
+/**
+ * Check if a point is "visible" from any one or more of the edges in a
+ * given group.
+ * Formally: Check if there is a line from @ref P to any of the edges in
+ * @ref Edges so that the line does not cross any of the lines of the
+ * PSLG @ref PSLG
+ */
+gboolean
+IsVisibleFromEdges (P2trPSLG *PSLG,
+ P2trVector2 *P,
+ P2trPSLG *Edges)
+{
+ gboolean found_visibility_path = FALSE;
+ P2trPSLG *KnownBlocks = p2tr_pslg_new ();
+ GQueue *BlocksForTest = g_queue_new ();
+
+ P2trVector2 W;
+ find_point_in_polygon (Edges, &W);
+
+ if (TryVisibilityAroundBlock(PSLG, P, Edges, KnownBlocks, BlocksForTest, NULL, &W))
+ found_visibility_path = TRUE;
+
+ while (! g_queue_is_empty (BlocksForTest) && ! found_visibility_path)
+ {
+ const P2trBoundedLine *Block = (P2trBoundedLine*)g_queue_pop_head (BlocksForTest);
+
+ if (p2tr_pslg_contains_line (KnownBlocks, Block))
+ continue;
+ else if (TryVisibilityAroundBlock(PSLG, P, Edges, KnownBlocks, BlocksForTest, Block, &Block->start)
+ || TryVisibilityAroundBlock(PSLG, P, Edges, KnownBlocks, BlocksForTest, Block, &Block->end))
+ {
+ found_visibility_path = TRUE;
+ }
+ else
+ p2tr_pslg_add_existing_line (KnownBlocks, Block);
+ }
+
+ p2tr_pslg_free (KnownBlocks);
+ g_queue_free (BlocksForTest);
+
+ return found_visibility_path;
+}
+#endif
+
+gboolean
+p2tr_visibility_is_visible_from_edges (P2trPSLG *pslg,
+ P2trVector2 *p,
+ const P2trBoundedLine *lines,
+ guint line_count)
+{
+ P2trPSLG *edges = p2tr_pslg_new ();
+ gint i;
+ gboolean result;
+
+ for (i = 0; i < line_count; i++)
+ p2tr_pslg_add_existing_line (edges, &lines[i]);
+
+ result = IsVisibleFromEdges (pslg, p, edges);
+
+ p2tr_pslg_free (edges);
+ return result;
+}
diff --git a/libs/poly2tri-c/poly2tri-c/refine/visibility.h b/libs/poly2tri-c/poly2tri-c/refine/visibility.h
new file mode 100644
index 0000000..3109b9b
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/visibility.h
@@ -0,0 +1,46 @@
+/*
+ * 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_VISIBILITY_H__
+#define __P2TC_REFINE_VISIBILITY_H__
+
+#include <glib.h>
+
+#include "bounded-line.h"
+#include "vector2.h"
+#include "pslg.h"
+
+gboolean p2tr_visibility_is_visible_from_edges (P2trPSLG *pslg,
+ P2trVector2 *p,
+ const P2trBoundedLine *lines,
+ guint line_count);
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/refine/vtriangle.c b/libs/poly2tri-c/poly2tri-c/refine/vtriangle.c
new file mode 100644
index 0000000..e213372
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/vtriangle.c
@@ -0,0 +1,145 @@
+/*
+ * 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 "mesh.h"
+
+#include "vtriangle.h"
+
+P2trVTriangle*
+p2tr_vtriangle_new (P2trTriangle *tri)
+{
+ P2trVTriangle *self = g_slice_new (P2trVTriangle);
+
+ self->points[0] = p2tr_point_ref (tri->edges[0]->end);
+ self->points[1] = p2tr_point_ref (tri->edges[1]->end);
+ self->points[2] = p2tr_point_ref (tri->edges[2]->end);
+
+ self->refcount = 1;
+
+ return self;
+}
+
+P2trVTriangle*
+p2tr_vtriangle_ref (P2trVTriangle *self)
+{
+ ++self->refcount;
+ return self;
+}
+
+void
+p2tr_vtriangle_unref (P2trVTriangle *self)
+{
+ g_assert (self->refcount > 0);
+ if (--self->refcount == 0)
+ p2tr_vtriangle_free (self);
+}
+
+void
+p2tr_vtriangle_free (P2trVTriangle *self)
+{
+ p2tr_point_unref (self->points[0]);
+ p2tr_point_unref (self->points[1]);
+ p2tr_point_unref (self->points[2]);
+ g_slice_free (P2trVTriangle, self);
+}
+
+P2trMesh*
+p2tr_vtriangle_get_mesh (P2trVTriangle *self)
+{
+ return p2tr_point_get_mesh (self->points[0]);
+}
+
+P2trTriangle*
+p2tr_vtriangle_is_real (P2trVTriangle *self)
+{
+ P2trEdge *e0, *e1, *e2;
+
+ /* The triangle exists if and only if all the edges
+ * still exist and they all are a part of the same
+ * triangle. */
+ if ((e0 = p2tr_point_has_edge_to (self->points[0], self->points[1])) &&
+ (e1 = p2tr_point_has_edge_to (self->points[1], self->points[2])) &&
+ (e2 = p2tr_point_has_edge_to (self->points[2], self->points[0])) &&
+ e0->tri == e1->tri && e1->tri == e2->tri)
+ return e0->tri;
+ else
+ return NULL;
+}
+
+void
+p2tr_vtriangle_create (P2trVTriangle *self)
+{
+ P2trMesh *mesh;
+ P2trEdge *e1, *e2, *e3;
+ P2trTriangle *tri;
+
+ g_assert (! p2tr_vtriangle_is_real (self));
+
+ mesh = p2tr_vtriangle_get_mesh (self);
+ e1 = p2tr_point_get_edge_to (self->points[0], self->points[1], FALSE);
+ e2 = p2tr_point_get_edge_to (self->points[1], self->points[2], FALSE);
+ e3 = p2tr_point_get_edge_to (self->points[2], self->points[0], FALSE);
+
+ if (mesh != NULL)
+ {
+ tri = p2tr_mesh_new_triangle (mesh, e1, e2, e3);
+ p2tr_mesh_unref (mesh);
+ }
+ else
+ tri = p2tr_triangle_new (e1, e2, e3);
+
+ p2tr_triangle_unref (tri);
+}
+
+void
+p2tr_vtriangle_remove (P2trVTriangle *self)
+{
+ P2trTriangle *tri = p2tr_vtriangle_is_real (self);
+
+ g_assert (tri != NULL);
+
+ p2tr_triangle_remove (tri);
+}
+
+P2trTriangle*
+p2tr_vtriangle_get (P2trVTriangle *self)
+{
+ P2trTriangle *real = p2tr_vtriangle_is_real (self);
+ g_assert (real != NULL);
+ return p2tr_triangle_ref (real);
+}
+
diff --git a/libs/poly2tri-c/poly2tri-c/refine/vtriangle.h b/libs/poly2tri-c/poly2tri-c/refine/vtriangle.h
new file mode 100644
index 0000000..5e63251
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/refine/vtriangle.h
@@ -0,0 +1,70 @@
+/*
+ * 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_VTRIANGLE_H__
+#define __P2TC_REFINE_VTRIANGLE_H__
+
+#include <glib.h>
+#include "rmath.h"
+#include "triangulation.h"
+
+/**
+ * @struct P2trVTriangle_
+ * A struct for representing a potential ("virtual") triangle
+ * in a triangular mesh
+ */
+struct P2trVTriangle_
+{
+ P2trPoint* points[3];
+
+ guint refcount;
+};
+
+P2trVTriangle* p2tr_vtriangle_new (P2trTriangle *tri);
+
+P2trVTriangle* p2tr_vtriangle_ref (P2trVTriangle *self);
+
+void p2tr_vtriangle_unref (P2trVTriangle *self);
+
+void p2tr_vtriangle_free (P2trVTriangle *self);
+
+P2trMesh* p2tr_vtriangle_get_mesh (P2trVTriangle *self);
+
+P2trTriangle* p2tr_vtriangle_is_real (P2trVTriangle *self);
+
+void p2tr_vtriangle_create (P2trVTriangle *self);
+
+void p2tr_vtriangle_remove (P2trVTriangle *self);
+
+P2trTriangle* p2tr_vtriangle_get (P2trVTriangle *self);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/render/Makefile.am b/libs/poly2tri-c/poly2tri-c/render/Makefile.am
new file mode 100644
index 0000000..8c02ec3
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/render/Makefile.am
@@ -0,0 +1,6 @@
+noinst_LTLIBRARIES = libp2tc-render.la
+
+libp2tc_render_la_SOURCES = mesh-render.c mesh-render.h svg-plot.c svg-plot.h
+
+P2TC_RENDER_publicdir = $(P2TC_publicdir)/render
+P2TC_RENDER_public_HEADERS = mesh-render.h svg-plot.h
diff --git a/libs/poly2tri-c/poly2tri-c/render/mesh-render.c b/libs/poly2tri-c/poly2tri-c/render/mesh-render.c
new file mode 100644
index 0000000..13f78db
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/render/mesh-render.c
@@ -0,0 +1,273 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <poly2tri-c/refine/refine.h>
+#include "mesh-render.h"
+
+/* This function implements box logic to see if a point is contained in a
+ * triangles bounding box. This is very useful for cases where there are many
+ * triangles to test against a single point, and most of them aren't even near
+ * it.
+ *
+ * Instead of finding the Xmin, Xmax, Ymin, Ymax and checking if the the point
+ * is outside, just check if the point is on the SAME SIDE compared to all the
+ * points of the triangle.
+ * See http://lightningismyname.blogspot.com/2011/08/quickboxa-quick-point-in-triangle-test.html
+ */
+gboolean
+p2tr_triangle_quick_box_test (P2trTriangle *self,
+ gdouble Px,
+ gdouble Py)
+{
+ P2trPoint *A = P2TR_TRIANGLE_GET_POINT (self, 0);
+ P2trPoint *B = P2TR_TRIANGLE_GET_POINT (self, 1);
+ P2trPoint *C = P2TR_TRIANGLE_GET_POINT (self, 2);
+
+ register gboolean xPBorder = B->c.x <= Px;
+ register gboolean yPBorder = B->c.y <= Py;
+
+ return (((A->c.x <= Px) == xPBorder) && (xPBorder == (C->c.x <= Px)))
+ || (((A->c.y <= Py) == yPBorder) && (yPBorder == (C->c.y <= Py)));
+}
+
+void
+p2tr_mesh_render_cache_uvt (P2trMesh *T,
+ P2trUVT *dest,
+ P2trImageConfig *config)
+{
+ p2tr_mesh_render_cache_uvt_exact (T, dest, config->x_samples * config->y_samples, config);
+}
+
+void
+p2tr_mesh_render_cache_uvt_exact (P2trMesh *T,
+ P2trUVT *dest,
+ gint dest_len,
+ P2trImageConfig *config)
+{
+ gint x, y, n = dest_len;
+ P2trUVT *uvt = dest;
+ P2trTriangle *tr_prev = NULL;
+ P2trVector2 pt;
+
+ pt.x = config->min_x;
+ pt.y = config->min_y;
+
+ uvt->tri = p2tr_mesh_find_point_local2 (T, &pt, NULL, &uvt->u, &uvt->v);
+ if (uvt->tri) p2tr_triangle_unref (uvt->tri);
+ tr_prev = uvt->tri;
+
+ for (y = 0, pt.y = config->min_y; y < config->y_samples; ++y, pt.y += config->step_y)
+ for (x = 0, pt.x = config->min_x; x < config->x_samples; ++x, pt.x += config->step_x)
+ {
+ if (n-- == 0) return;
+ uvt->tri = p2tr_mesh_find_point_local2 (T, &pt, tr_prev, &uvt->u, &uvt->v);
+ if (uvt->tri) p2tr_triangle_unref (uvt->tri);
+ tr_prev = uvt->tri;
+ ++uvt;
+ }
+}
+
+#define P2TR_USE_BARYCENTRIC(u, v, A, B, C) \
+ ((A) + (v) * ((B) - (A)) + (u) * ((C) - (A)))
+
+/**
+ * This is a general macro for using a UVT cache in order to render a
+ * color interpolation triangular mesh. The reason this is a macro and
+ * not a function is to allow using different numeric types for
+ * representing colors
+ * @param uvt_cache The buffer containing the UVT cache of the area to
+ * render. Should be of type @ref P2trUVT*
+ * @param uvt_cache_w The width of the area for which the UVT cache was
+ * created. Should be a positive integer.
+ * @param uvt_cache_h The height of the area for which the UVT cache was
+ * created. Should be a positive integer.
+ * @param dest The buffer in which the rendering result should be saved.
+ * Should be of type @ref cformat*
+ * @param n The amount of pixels to render into dest. Should be a
+ * positive integer.
+ * @param cformat The type of the data inside @ref dest. This can be any
+ * numeric type (double, float, int, ...)
+ * @param cpp The amount of color channels per pixel, not including the
+ * alpha channel. Should be a positive integer.
+ * @param pt2col The function which maps mesh points into colors. This
+ * function should be deterministic!
+ * @param pt2col_user_data An additional parameter to @ref pt2col
+ * @param alpha_last Specifies whether the alpha component should come
+ * after or before the other color channels. Should be a boolean.
+ */
+#define P2TR_MESH_RENDER_FROM_CACHE(uvt_cache, \
+ uvt_cache_w, \
+ uvt_cache_h, \
+ dest, \
+ n, \
+ cformat, \
+ cpp, \
+ pt2col, \
+ pt2col_user_data, \
+ alpha_last) \
+G_STMT_START \
+{ \
+ P2trUVT *uvt_p = (uvt_cache); \
+ guint remain = n; \
+ \
+ P2trTriangle *tr_prev = NULL; \
+ guint x, y, i; \
+ P2trPointToColorFuncC pt2col_c = (P2trPointToColorFuncC) (pt2col); \
+ \
+ cformat *colA = g_newa (cformat, (cpp)); \
+ cformat *colB = g_newa (cformat, (cpp)); \
+ cformat *colC = g_newa (cformat, (cpp)); \
+ \
+ cformat *pixel = dest; \
+ \
+ for (y = 0; y < (uvt_cache_w) && remain > 0; ++y) \
+ for (x = 0; x < (uvt_cache_h) && remain > 0; ++x, --remain, ++uvt_p) \
+ { \
+ P2trTriangle *tr_now = uvt_p->tri; \
+ \
+ /* If we are outside of the triangulation, set alpha to */ \
+ /* zero and continue */ \
+ if (tr_now == NULL) \
+ { \
+ /* Remember that cpp does not include the alpha! */ \
+ pixel[(alpha_last) ? (cpp) : 0] = 0; \
+ pixel += cpp + 1; \
+ } \
+ else \
+ { \
+ gdouble u = uvt_p->u; \
+ gdouble v = uvt_p->v; \
+ /* If the triangle hasn't changed since the previous */ \
+ /* pixel, then don't sample the color at the vertices */ \
+ /* again, since that is an expensive process! */ \
+ if (tr_now != tr_prev) \
+ { \
+ /* Get the points of the triangle in some fixed */ \
+ /* order, just to make sure that the computation */ \
+ /* goes the same everywhere */ \
+ P2trPoint *A = P2TR_TRIANGLE_GET_POINT (tr_now, 0); \
+ P2trPoint *B = P2TR_TRIANGLE_GET_POINT (tr_now, 1); \
+ P2trPoint *C = P2TR_TRIANGLE_GET_POINT (tr_now, 2); \
+ /* At each point 'X' sample the color into 'colX' */ \
+ pt2col_c (A, (gpointer) colA, pt2col_user_data); \
+ pt2col_c (B, (gpointer) colB, pt2col_user_data); \
+ pt2col_c (C, (gpointer) colC, pt2col_user_data); \
+ /* Set the current triangle */ \
+ tr_now = tr_prev; \
+ } \
+ \
+ /* We are inside the mesh, so set as opaque */ \
+ if (! alpha_last) *pixel++ = (cformat) 1; \
+ /* Interpolate the color using barycentric coodinates */ \
+ for (i = 0; i < cpp; ++i) \
+ *pixel++ = (cformat) P2TR_USE_BARYCENTRIC (u, v, \
+ colA[i], colB[i], colC[i]); \
+ /* We are inside the mesh, so set as opaque */ \
+ if (alpha_last) *pixel++ = (cformat) 1; \
+ } \
+ } \
+} \
+G_STMT_END
+
+#define P2TR_MESH_RENDER(mesh, \
+ dest, \
+ config, \
+ pt2col, \
+ pt2col_user_data, \
+ cache_render_func) \
+G_STMT_START \
+{ \
+ gint n = (config)->x_samples * (config)->y_samples; \
+ P2trUVT *uvt_cache = g_new (P2trUVT, n); \
+ \
+ p2tr_mesh_render_cache_uvt_exact ((mesh), uvt_cache, n, (config)); \
+ cache_render_func (uvt_cache, (dest), n, (config), (pt2col), \
+ (pt2col_user_data)); \
+ \
+ g_free (uvt_cache); \
+} \
+G_STMT_END
+
+void
+p2tr_mesh_render_from_cache_f (P2trUVT *uvt_cache,
+ gfloat *dest,
+ gint n,
+ P2trImageConfig *config,
+ P2trPointToColorFuncF pt2col,
+ gpointer pt2col_user_data)
+{
+ P2TR_MESH_RENDER_FROM_CACHE (uvt_cache,
+ config->x_samples, config->y_samples,
+ dest, n, gfloat, config->cpp,
+ pt2col, pt2col_user_data,
+ config->alpha_last);
+}
+
+void
+p2tr_mesh_render_f (P2trMesh *mesh,
+ gfloat *dest,
+ P2trImageConfig *config,
+ P2trPointToColorFuncF pt2col,
+ gpointer pt2col_user_data)
+{
+ P2TR_MESH_RENDER (mesh, dest, config, pt2col, pt2col_user_data,
+ p2tr_mesh_render_from_cache_f);
+}
+
+void
+p2tr_mesh_render_from_cache_b (P2trUVT *uvt_cache,
+ guint8 *dest,
+ gint n,
+ P2trImageConfig *config,
+ P2trPointToColorFuncB pt2col,
+ gpointer pt2col_user_data)
+{
+ P2TR_MESH_RENDER_FROM_CACHE (uvt_cache,
+ config->x_samples, config->y_samples,
+ dest, n, guint8, config->cpp,
+ pt2col, pt2col_user_data,
+ config->alpha_last);
+}
+
+void
+p2tr_mesh_render_b (P2trMesh *mesh,
+ guint8 *dest,
+ P2trImageConfig *config,
+ P2trPointToColorFuncB pt2col,
+ gpointer pt2col_user_data)
+{
+ P2TR_MESH_RENDER (mesh, dest, config, pt2col, pt2col_user_data,
+ p2tr_mesh_render_from_cache_b);
+}
diff --git a/libs/poly2tri-c/poly2tri-c/render/mesh-render.h b/libs/poly2tri-c/poly2tri-c/render/mesh-render.h
new file mode 100644
index 0000000..9a1d63c
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/render/mesh-render.h
@@ -0,0 +1,175 @@
+/*
+ * 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 __P2TR_RENDER_MESH_RENDER_H__
+#define __P2TR_RENDER_MESH_RENDER_H__
+
+#include <glib.h>
+#include <poly2tri-c/refine/refine.h>
+
+/**
+ * A struct containing the necessary information to render a "color
+ * image" of a triangular mesh, by interpolating "colors" between its
+ * points.
+ * This can in fact be used to interpolate any N-Dimensional value set
+ * along the triangles of a mesh.
+ */
+typedef struct {
+ /** Minimal X and Y coordinates to start sampling at */
+ gdouble min_x, min_y;
+ /** Size of a step (distance between samples) in each axis */
+ gdouble step_x, step_y;
+ /** The amount of samples desired in each axis */
+ guint x_samples, y_samples;
+ /**
+ * The amount of channels per "pixel", both in the destination buffer
+ * and in the colors returned from the matching point-to-color
+ * function. Note that this does not include the alpha channel!
+ */
+ guint cpp;
+ /**
+ * Specifies whether the alpha channel (0 outside the mesh, 1 inside)
+ * should come after or before the the channel colors
+ */
+ gboolean alpha_last;
+} P2trImageConfig;
+
+/**
+ * A function that maps mesh points into colors
+ * @param point The mesh point
+ * @param dest The destination buffer for the color components, where
+ * each component is one unsigned byte (guint8)
+ * @param user_data Custom data passed as a pointer to the function
+ */
+typedef void (*P2trPointToColorFuncB) (P2trPoint *point,
+ guint8 *dest,
+ gpointer user_data);
+
+/**
+ * Similar to @ref P2trPointToColorFuncB, but with floating point data
+ * types for each color component
+ */
+typedef void (*P2trPointToColorFuncF) (P2trPoint *point,
+ gfloat *dest,
+ gpointer user_data);
+
+/**
+ * A generalization of all the point-to-color functions. This is used
+ * only for type casting inside the library and should not be used
+ * externally.
+ */
+typedef void (*P2trPointToColorFuncC) (P2trPoint *point,
+ void *dest,
+ gpointer user_data);
+
+/**
+ * A struct for caching the barycentric coordinates of a point inside
+ * a triangle. A buffer of these structs is referred to as a UVT cache.
+ */
+typedef struct {
+ gdouble u;
+ gdouble v;
+ P2trTriangle *tri;
+} P2trUVT;
+
+/**
+ * Compute the UVT cache for the given mesh for the area and resolution
+ * specified by the image configuration struct. The cache for the point
+ * (min_x + i * step_x, min_y + j * step_y) would be at the index
+ * j * x_samples + i (assuming of course the point is inside the area
+ * described by image configuration struct).
+ */
+void p2tr_mesh_render_cache_uvt (P2trMesh *mesh,
+ P2trUVT *dest,
+ P2trImageConfig *config);
+
+/**
+ * Similar to @ref p2tr_mesh_render_cache_uvt, but cache only the
+ * first @ref dest_len pixels.
+ */
+void p2tr_mesh_render_cache_uvt_exact (P2trMesh *mesh,
+ P2trUVT *dest,
+ gint dest_len,
+ P2trImageConfig *config);
+
+/**
+ * Render a mesh using a UVT cache that was computed for the given
+ * area, together with a point-to-color function.
+ * @param uvt_cache A cache for the given area, computed with
+ * @ref p2tr_mesh_render_cache_uvt_exact
+ * @param dest The destination buffer for the image
+ * @param dest_len How many pixels to render from the area. The cache
+ * should contain data for at least this many pixels!
+ * @param config The render configuration struct
+ * @param pt2col A function that receives points in the mesh and returns
+ * colors. The returned colors should have config->cpp components
+ * @param pt2col_user_data Custom data to pass to @ref pt2col
+ */
+void p2tr_mesh_render_from_cache_f (P2trUVT *uvt_cache,
+ gfloat *dest,
+ gint dest_len,
+ P2trImageConfig *config,
+ P2trPointToColorFuncF pt2col,
+ gpointer pt2col_user_data);
+
+/**
+ * Render a mesh with the given area and sampling configuration. Same
+ * as first caching @ref p2tr_mesh_render_cache_uvt and then calling
+ * @ref p2tr_mesh_render_cache_uvt_exact with the cache, and finally
+ * freeing the cache
+ */
+void p2tr_mesh_render_f (P2trMesh *mesh,
+ gfloat *dest,
+ P2trImageConfig *config,
+ P2trPointToColorFuncF pt2col,
+ gpointer pt2col_user_data);
+
+/**
+ * See @ref p2tr_mesh_render_from_cache_f
+ */
+void p2tr_mesh_render_from_cache_b (P2trUVT *uvt_cache,
+ guint8 *dest,
+ gint dest_len,
+ P2trImageConfig *config,
+ P2trPointToColorFuncB pt2col,
+ gpointer pt2col_user_data);
+
+/**
+ * See @ref p2tr_mesh_render_f
+ */
+void p2tr_mesh_render_b (P2trMesh *mesh,
+ guint8 *dest,
+ P2trImageConfig *config,
+ P2trPointToColorFuncB pt2col,
+ gpointer pt2col_user_data);
+
+#endif
diff --git a/libs/poly2tri-c/poly2tri-c/render/svg-plot.c b/libs/poly2tri-c/poly2tri-c/render/svg-plot.c
new file mode 100644
index 0000000..66f636c
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/render/svg-plot.c
@@ -0,0 +1,204 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <glib.h>
+
+#include <poly2tri-c/refine/triangulation.h>
+
+#include "svg-plot.h"
+
+#define P2TR_SVG_NEWLINE "\n"
+
+void
+p2tr_render_svg_init (FILE *out,
+ const P2trVector2 *bottom_left,
+ const P2trVector2 *top_right)
+{
+ gdouble real_width = top_right->x - bottom_left->x;
+ gdouble real_height = top_right->y - bottom_left->y;
+
+ /* Begin with the header of the document */
+ fprintf (out, "<?xml version=\"1.0\" standalone=\"no\"?>%s",
+ P2TR_SVG_NEWLINE);
+ fprintf (out, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"%s",
+ P2TR_SVG_NEWLINE);
+ fprintf (out, "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">%s",
+ P2TR_SVG_NEWLINE);
+
+ fprintf (out, "<svg xmlns=\"http://www.w3.org/2000/svg\""
+ " version=\"1.1\"%s", P2TR_SVG_NEWLINE);
+
+ fprintf (out, " viewBox=\"%f %f %f %f\"%s",
+ + bottom_left->x, - (bottom_left->y + real_height),
+ + real_width, + real_height,
+ P2TR_SVG_NEWLINE);
+
+ fprintf (out, " preserveAspectRatio=\"xMidYMid meet\"%s",
+ P2TR_SVG_NEWLINE);
+
+ /* Close the SVG tag */
+ fprintf (out, ">%s", P2TR_SVG_NEWLINE);
+
+ fprintf (out, "<g transform=\"scale(1,-1)\">%s",
+ P2TR_SVG_NEWLINE);
+}
+
+void
+p2tr_render_svg_finish (FILE *out)
+{
+ fprintf (out, "</g>%s", P2TR_SVG_NEWLINE);
+ fprintf (out, "</svg>%s", P2TR_SVG_NEWLINE);
+}
+
+static void
+p2tr_render_svg_style (FILE *out,
+ P2trSVGContext *context,
+ gboolean no_fill)
+{
+ fprintf (out, "style=\"");
+ {
+ if (context->stroke)
+ {
+ fprintf (out, "stroke: #%02x%02x%02x; stroke-opacity: %f; ",
+ context->stroke_color[0], context->stroke_color[1],
+ context->stroke_color[2], context->stroke_color[3] / 255.0);
+ fprintf (out, "stroke-:width: %f; stroke-linejoin: round; ",
+ context->stroke_width);
+ }
+
+ if (context->fill && ! no_fill)
+ fprintf (out, "fill: #%02x%02x%02x; fill-opacity: %f; ",
+ context->fill_color[0], context->fill_color[1],
+ context->fill_color[2], context->fill_color[3] / 255.0);
+
+ if (context->opacity != 1)
+ fprintf (out, "opacity: %f; ", context->opacity);
+ }
+ fprintf (out, "\"");
+}
+
+void
+p2tr_render_svg_draw_line (FILE *out,
+ P2trSVGContext *context,
+ const P2trVector2 *start,
+ const P2trVector2 *end)
+{
+ fprintf (out, "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" ",
+ start->x, start->y, end->x, end->y);
+ p2tr_render_svg_style (out, context, TRUE);
+ fprintf (out, " />%s", P2TR_SVG_NEWLINE);
+}
+
+void
+p2tr_render_svg_draw_triangle (FILE *out,
+ P2trSVGContext *context,
+ const P2trVector2 *p1,
+ const P2trVector2 *p2,
+ const P2trVector2 *p3)
+{
+ fprintf (out, "<polygon points=\"%f,%f %f,%f %f,%f\" ",
+ p1->x, p1->y, p2->x, p2->y, p3->x, p3->y);
+ p2tr_render_svg_style (out, context, FALSE);
+ fprintf (out, " />%s", P2TR_SVG_NEWLINE);
+}
+
+void
+p2tr_render_svg_draw_circle (FILE *out,
+ P2trSVGContext *context,
+ const P2trVector2 *center,
+ gdouble radius)
+{
+ fprintf (out, "<circle cx=\"%f\" cy=\"%f\" r=\"%f\" ",
+ center->x, center->y, radius);
+ p2tr_render_svg_style (out, context, FALSE);
+ fprintf (out, " />%s", P2TR_SVG_NEWLINE);
+}
+
+void
+p2tr_render_svg (P2trMesh *mesh,
+ FILE *out)
+{
+ P2trHashSetIter siter;
+ P2trTriangle *tr;
+ P2trPoint *pt;
+
+ /* Colors taken from the Tango Icon Theme color palette */
+ P2trSVGContext TRI = {
+ TRUE,
+ 1,
+ /* Sky Blue 3 */
+ { 32, 74, 135, 255 },
+ TRUE,
+ /* Sky Blue 1 */
+ { 114, 159, 207, 255 },
+ 1
+ };
+
+ P2trSVGContext PT = {
+ FALSE,
+ 0,
+ /* Orange 3 */
+ { 206, 92, 0, 1 },
+ TRUE,
+ /* Orange 1 */
+ { 245, 121, 0, 255 },
+ 1
+ };
+
+ P2trVector2 bottom_left, top_right;
+
+ p2tr_mesh_get_bounds (mesh,
+ &bottom_left.x, &bottom_left.y,
+ &top_right.x, &top_right.y);
+
+ bottom_left.x -= 10;
+ bottom_left.y -= 10;
+ top_right.x += 10;
+ top_right.y += 10;
+ p2tr_render_svg_init (out, &bottom_left, &top_right);
+
+ p2tr_hash_set_iter_init (&siter, mesh->triangles);
+ while (p2tr_hash_set_iter_next (&siter, (gpointer*)&tr))
+ p2tr_render_svg_draw_triangle (out, &TRI,
+ &P2TR_TRIANGLE_GET_POINT(tr, 0)->c,
+ &P2TR_TRIANGLE_GET_POINT(tr, 1)->c,
+ &P2TR_TRIANGLE_GET_POINT(tr, 2)->c);
+
+ p2tr_hash_set_iter_init (&siter, mesh->points);
+ while (p2tr_hash_set_iter_next (&siter, (gpointer*)&pt))
+ p2tr_render_svg_draw_circle (out, &PT, &pt->c, 1);
+
+ p2tr_render_svg_finish (out);
+}
diff --git a/libs/poly2tri-c/poly2tri-c/render/svg-plot.h b/libs/poly2tri-c/poly2tri-c/render/svg-plot.h
new file mode 100644
index 0000000..a94acd6
--- /dev/null
+++ b/libs/poly2tri-c/poly2tri-c/render/svg-plot.h
@@ -0,0 +1,75 @@
+/*
+ * 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_RENDER_SVG_PLOT_H__
+#define __P2TC_RENDER_SVG_PLOT_H__
+
+#include <poly2tri-c/refine/refine.h>
+
+typedef guint8 P2trSVGColor[4];
+
+typedef struct
+{
+ gboolean stroke;
+ gdouble stroke_width;
+ P2trSVGColor stroke_color;
+ gboolean fill;
+ P2trSVGColor fill_color;
+ gdouble opacity;
+} P2trSVGContext;
+
+void p2tr_render_svg_init (FILE *out,
+ const P2trVector2 *bottom_left,
+ const P2trVector2 *top_right);
+
+void p2tr_render_svg_draw_line (FILE *out,
+ P2trSVGContext *context,
+ const P2trVector2 *start,
+ const P2trVector2 *end);
+
+void p2tr_render_svg_draw_triangle (FILE *out,
+ P2trSVGContext *context,
+ const P2trVector2 *p1,
+ const P2trVector2 *p2,
+ const P2trVector2 *p3);
+
+void p2tr_render_svg_draw_circle (FILE *out,
+ P2trSVGContext *context,
+ const P2trVector2 *center,
+ gdouble radius);
+
+void p2tr_render_svg_finish (FILE *out);
+
+void p2tr_render_svg (P2trMesh *mesh,
+ FILE *out);
+
+#endif
diff --git a/operations/common/seamless-clone/Makefile.am b/operations/common/seamless-clone/Makefile.am
index fb3c060..951e75b 100644
--- a/operations/common/seamless-clone/Makefile.am
+++ b/operations/common/seamless-clone/Makefile.am
@@ -18,6 +18,4 @@ seamless_clone_compose_la_SOURCES = seamless-clone-compose.c
opdir = $(libdir)/gegl- GEGL_API_VERSION@
-if HAVE_P2TC
op_LTLIBRARIES = seamless-clone.la seamless-clone-render.la seamless-clone-prepare.la seamless-clone-compose.la
-endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]