[gimp/soc-2011-seamless-clone] Work in progress, add triangular mesh rendering support. Depends on poly2tri-c



commit 0ef19875d6be003571c12ce8f25a84d8f99e4e95
Author: Barak Itkin <lightningismyname gmail com>
Date:   Thu Jul 21 23:47:00 2011 +0300

    Work in progress, add triangular mesh rendering support. Depends on poly2tri-c

 app/gegl/Makefile.am                          |   18 +
 app/gegl/gimp-gegl-types.h                    |    1 +
 app/gegl/gimp-gegl.c                          |    2 +
 app/gegl/gimpoperationfindoutline.c           |   31 +-
 app/gegl/gimpoperationfindoutline.h           |    6 +-
 app/gegl/gimpoperationseamlessclone.c         |  291 ++++++++
 app/gegl/gimpoperationseamlessclone.h         |   58 ++
 app/gegl/poly2tri-c/common/cutils.h           |   37 +
 app/gegl/poly2tri-c/common/poly2tri-private.h |   34 +
 app/gegl/poly2tri-c/common/shapes.c           |  732 +++++++++++++++++++
 app/gegl/poly2tri-c/common/shapes.h           |  150 ++++
 app/gegl/poly2tri-c/common/utils.c            |   95 +++
 app/gegl/poly2tri-c/common/utils.h            |   63 ++
 app/gegl/poly2tri-c/poly2tri.h                |   39 +
 app/gegl/poly2tri-c/sweep/advancing_front.c   |  215 ++++++
 app/gegl/poly2tri-c/sweep/advancing_front.h   |   87 +++
 app/gegl/poly2tri-c/sweep/cdt.c               |   90 +++
 app/gegl/poly2tri-c/sweep/cdt.h               |  101 +++
 app/gegl/poly2tri-c/sweep/sweep.c             |  932 +++++++++++++++++++++++++
 app/gegl/poly2tri-c/sweep/sweep.h             |  270 +++++++
 app/gegl/poly2tri-c/sweep/sweep_context.c     |  313 +++++++++
 app/gegl/poly2tri-c/sweep/sweep_context.h     |  133 ++++
 app/tools/gimpseamlessclonetool.c             |   39 +-
 23 files changed, 3702 insertions(+), 35 deletions(-)
---
diff --git a/app/gegl/Makefile.am b/app/gegl/Makefile.am
index bcd5143..c62a4a1 100644
--- a/app/gegl/Makefile.am
+++ b/app/gegl/Makefile.am
@@ -73,9 +73,27 @@ libappgegl_a_sources = \
 	gimpoperationlevels.h		\
 	gimpoperationposterize.c	\
 	gimpoperationposterize.h	\
+	gimpoperationseamlessclone.c	\
+	gimpoperationseamlessclone.h	\
 	gimpoperationthreshold.c	\
 	gimpoperationthreshold.h	\
 	\
+	poly2tri-c/poly2tri.h		\
+	poly2tri-c/common/cutils.h	\
+	poly2tri-c/common/poly2tri-private.h	\
+	poly2tri-c/common/shapes.c	\
+	poly2tri-c/common/shapes.h	\
+	poly2tri-c/common/utils.c	\
+	poly2tri-c/common/utils.h	\
+	poly2tri-c/sweep/advancing_front.c	\
+	poly2tri-c/sweep/advancing_front.h	\
+	poly2tri-c/sweep/cdt.c		\
+	poly2tri-c/sweep/cdt.h		\
+	poly2tri-c/sweep/sweep.c	\
+	poly2tri-c/sweep/sweep.h	\
+	poly2tri-c/sweep/sweep_context.c	\
+	poly2tri-c/sweep/sweep_context.h	\
+	\
 	gimpoperationpointlayermode.c	\
 	gimpoperationpointlayermode.h	\
 	gimpoperationdissolvemode.c     \
diff --git a/app/gegl/gimp-gegl-types.h b/app/gegl/gimp-gegl-types.h
index 413d341..612f369 100644
--- a/app/gegl/gimp-gegl-types.h
+++ b/app/gegl/gimp-gegl-types.h
@@ -41,6 +41,7 @@ typedef struct _GimpOperationFindOutline      GimpOperationFindOutline;
 typedef struct _GimpOperationHueSaturation    GimpOperationHueSaturation;
 typedef struct _GimpOperationLevels           GimpOperationLevels;
 typedef struct _GimpOperationPosterize        GimpOperationPosterize;
+typedef struct _GimpOperationSeamlessClone    GimpOperationSeamlessClone;
 typedef struct _GimpOperationThreshold        GimpOperationThreshold;
 
 typedef struct _GimpOperationPointLayerMode   GimpOperationPointLayerMode;
diff --git a/app/gegl/gimp-gegl.c b/app/gegl/gimp-gegl.c
index c07f380..3707a48 100644
--- a/app/gegl/gimp-gegl.c
+++ b/app/gegl/gimp-gegl.c
@@ -41,6 +41,7 @@
 #include "gimpoperationhuesaturation.h"
 #include "gimpoperationlevels.h"
 #include "gimpoperationposterize.h"
+#include "gimpoperationseamlessclone.h"
 #include "gimpoperationthreshold.h"
 #include "gimpoperationtilesink.h"
 #include "gimpoperationtilesource.h"
@@ -108,6 +109,7 @@ gimp_gegl_init (Gimp *gimp)
   g_type_class_ref (GIMP_TYPE_OPERATION_HUE_SATURATION);
   g_type_class_ref (GIMP_TYPE_OPERATION_LEVELS);
   g_type_class_ref (GIMP_TYPE_OPERATION_POSTERIZE);
+  g_type_class_ref (GIMP_TYPE_OPERATION_SEAMLESS_CLONE);
   g_type_class_ref (GIMP_TYPE_OPERATION_THRESHOLD);
 
   g_type_class_ref (GIMP_TYPE_OPERATION_POINT_LAYER_MODE);
diff --git a/app/gegl/gimpoperationfindoutline.c b/app/gegl/gimpoperationfindoutline.c
index b54bc72..b3e21a4 100644
--- a/app/gegl/gimpoperationfindoutline.c
+++ b/app/gegl/gimpoperationfindoutline.c
@@ -90,10 +90,10 @@ gimp_operation_find_outline_class_init (GimpOperationFindOutlineClass *klass)
                                                          G_PARAM_READWRITE));
 
   g_object_class_install_property (object_class, PROP_THRESHOLD,
-                                   g_param_spec_double ("threshold",
+                                   g_param_spec_float ("threshold",
                                                          "Threshold",
                                                          "The threshold for determining the difference between black and white (white >= thres)",
-                                                         -G_MAXDOUBLE, G_MAXDOUBLE, 0.5,
+                                                         -G_MAXFLOAT, G_MAXFLOAT, 0.5f,
                                                          G_PARAM_READWRITE));
 
   /* Workaround around wrong ROI calculation in GEGL for Sink ops when needs_full is set */
@@ -145,7 +145,7 @@ gimp_operation_find_outline_get_property (GObject    *object,
       g_value_set_pointer (value, self->ptList);
       break;
     case PROP_THRESHOLD:
-      g_value_set_double (value, self->threshold);
+      g_value_set_float (value, self->threshold);
       break;
     case PROP_X:
       g_value_set_int (value, self->x);
@@ -180,7 +180,7 @@ gimp_operation_find_outline_set_property (GObject      *object,
       self->ptList = g_value_get_pointer (value);
       break;
     case PROP_THRESHOLD:
-      self->threshold = g_value_get_double (value);
+      self->threshold = g_value_get_float (value);
       break;
     case PROP_X:
       self->x = g_value_get_int (value);
@@ -241,6 +241,7 @@ typedef enum {
 #define isEast(s) (((s) == D_NE) || ((s) == D_E) || ((s) == D_SE))
 #define isWest(s) (((s) == D_NW) || ((s) == D_W) || ((s) == D_SW))
 
+#define BABL_FORMAT
 typedef struct {
   gint x, y;
 } SPoint;
@@ -278,7 +279,7 @@ gimp_operation_find_outline_is_inside (OutlineProcPrivate *OPP, SPoint *pt)
          && in_range (pt->y, OPP->ymin, OPP->ymax);
 }
 
-#define get_value(OPP,x,y)  (((OPP)->im)[((y)-(OPP)->ymin)*(OPP)->rowstride+(x)-(OPP)->xmin])
+#define get_value(OPP,x,y)  (((OPP)->im)[(((y)-(OPP)->ymin)*(OPP)->rowstride+(x)-(OPP)->xmin)*4+3])
 #define get_valuePT(OPP,pt) get_value(OPP,(pt)->x,(pt)->y)
 
 static inline gboolean
@@ -394,27 +395,13 @@ gimp_operation_find_outline_process (GeglOperation       *operation,
   OPP->ymax = self->y + self->height - 1;
 
   OPP->threshold = self->threshold;
-  OPP->im = g_new (gdouble,(rect.width) * rect.height);
+  OPP->im = g_new (gfloat,4 * (rect.width) * rect.height);
   OPP->rowstride = rect.width;
 
-  gegl_buffer_get (input, 1.0, &rect, babl_format("Y double"), OPP->im, GEGL_AUTO_ROWSTRIDE);
+  gegl_buffer_get (input, 1.0, &rect, babl_format("RGBA float"), OPP->im, GEGL_AUTO_ROWSTRIDE);
 
   gimp_operation_find_outline_find_outline_ccw (OPP, self->ptList);
 
-//  gint x, y;
-//  /* First of all try to find a white pixel */
-//  for (y = OPP->ymin; y < OPP->ymax; y++)
-//  {
-//    for (x = OPP->xmin; x < OPP->xmax; x++)
-//    {
-//      if (get_value (OPP, x, y) >= OPP->threshold)
-//        printf ("1");
-//      else
-//        printf ("0");
-//    }
-//    printf("\n");
-//  }
-
   g_free (OPP->im);
   OPP->im = NULL;
 
@@ -426,5 +413,5 @@ gimp_operation_find_outline_prepare (GeglOperation *operation)
 {
   printf ("Preparing!\n");
 
-  gegl_operation_set_format (operation, "input", babl_format("Y double"));
+  gegl_operation_set_format (operation, "input", babl_format("RGBA float"));
 }
diff --git a/app/gegl/gimpoperationfindoutline.h b/app/gegl/gimpoperationfindoutline.h
index ba80bc9..5685410 100644
--- a/app/gegl/gimpoperationfindoutline.h
+++ b/app/gegl/gimpoperationfindoutline.h
@@ -40,8 +40,8 @@ typedef struct
   gint    xmin, xmax;
   gint    ymin, ymax;
   gint    rowstride;
-  gdouble  threshold;
-  gdouble *im;
+  float   threshold;
+  float   *im;
 } OutlineProcPrivate;
 
 struct _GimpOperationFindOutline
@@ -50,7 +50,7 @@ struct _GimpOperationFindOutline
 
   GPtrArray             *ptList;
   gint                   x, y, width, height;
-  gdouble                threshold;
+  float                  threshold;
 
   /* Remains from old versions. Merge with properties above one day */
   OutlineProcPrivate    *opp;
diff --git a/app/gegl/gimpoperationseamlessclone.c b/app/gegl/gimpoperationseamlessclone.c
new file mode 100644
index 0000000..f3e20ed
--- /dev/null
+++ b/app/gegl/gimpoperationseamlessclone.c
@@ -0,0 +1,291 @@
+/* GIMP - The GNU Image Manipulation Program
+ *
+ * gimpoperationseamlessclone.c
+ * Copyright (C) 2011 Barak Itkin <lightningismyname gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* TODO: release resources, mainly the mesh pattern and points */
+
+#include "config.h"
+#include <gegl.h>
+#include <cairo.h>
+
+#include "gimp-gegl-types.h"
+
+#include "gimpoperationseamlessclone.h"
+#include "poly2tri-c/poly2tri.h"
+
+#include <stdio.h> /* TODO: get rid of this debugging way! */
+
+enum
+{
+  PROP0,
+  PROP_POINTS,
+  PROP_X,
+  PROP_Y
+};
+
+static void
+gimp_operation_seamless_clone_init (GimpOperationSeamlessClone *self);
+
+static void
+gimp_operation_seamless_clone_get_property (GObject    *object,
+                                            guint       property_id,
+                                            GValue     *value,
+                                            GParamSpec *pspec);
+
+static void
+gimp_operation_seamless_clone_set_property (GObject      *object,
+                                            guint         property_id,
+                                            const GValue *value,
+                                            GParamSpec   *pspec);
+
+static gboolean
+gimp_operation_seamless_clone_process (GeglOperation       *operation,
+                                       GeglBuffer          *output,
+                                       const GeglRectangle *roi);
+
+static GeglRectangle
+gimp_operation_seamless_clone_get_bounding_box (GeglOperation *operation);
+
+static void
+gimp_operation_seamless_clone_prepare (GeglOperation *operation);
+
+G_DEFINE_TYPE (GimpOperationSeamlessClone, gimp_operation_seamless_clone,
+               GEGL_TYPE_OPERATION_SOURCE)
+
+#define parent_class gimp_operation_seamless_clone_parent_class
+
+static void
+gimp_operation_seamless_clone_class_init (GimpOperationSeamlessCloneClass *klass)
+{
+  GObjectClass             *object_class    = G_OBJECT_CLASS (klass);
+  GeglOperationClass       *operation_class = GEGL_OPERATION_CLASS (klass);
+  GeglOperationSourceClass *source_class    = GEGL_OPERATION_SOURCE_CLASS (klass);
+
+  object_class->set_property = gimp_operation_seamless_clone_set_property;
+  object_class->get_property = gimp_operation_seamless_clone_get_property;
+
+  operation_class->prepare          = gimp_operation_seamless_clone_prepare;
+  operation_class->get_bounding_box = gimp_operation_seamless_clone_get_bounding_box;
+  operation_class->name             = "gimp:seamless-clone";
+  operation_class->categories       = "programming";
+  operation_class->description      = "GIMP seamless clone operation";
+
+  source_class->process    = gimp_operation_seamless_clone_process;
+
+  g_object_class_install_property (object_class, PROP_POINTS,
+                                   g_param_spec_pointer ("points",
+                                                         "Points",
+                                                         "A GPtrArray* of struct {gint x, y;} containing the points",
+                                                         G_PARAM_READWRITE));
+
+  /* Workaround around wrong ROI calculation in GEGL for Sink ops when needs_full is set */
+  g_object_class_install_property (object_class, PROP_X,
+                                   g_param_spec_int ("x",
+                                                     "X",
+                                                     "The minimal x of the scaning rect",
+                                                     -G_MAXINT, G_MAXINT, 0,
+                                                     G_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, PROP_Y,
+                                   g_param_spec_int ("y",
+                                                     "Y",
+                                                     "The minimal Y of the scaning rect",
+                                                     -G_MAXINT, G_MAXINT, 0,
+                                                     G_PARAM_READWRITE));
+
+}
+
+static void
+gimp_operation_seamless_clone_init (GimpOperationSeamlessClone *self)
+{
+  self->mesh = NULL;
+}
+
+static void
+gimp_operation_seamless_clone_get_property (GObject    *object,
+                                            guint       property_id,
+                                            GValue     *value,
+                                            GParamSpec *pspec)
+{
+  GimpOperationSeamlessClone *self = GIMP_OPERATION_SEAMLESS_CLONE (object);
+
+  switch (property_id)
+    {
+    case PROP_POINTS:
+      g_value_set_pointer (value, self->ptList);
+      break;
+    case PROP_X:
+      g_value_set_int (value, self->x);
+      break;
+    case PROP_Y:
+      g_value_set_int (value, self->y);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_operation_seamless_clone_set_property (GObject      *object,
+                                            guint         property_id,
+                                            const GValue *value,
+                                            GParamSpec   *pspec)
+{
+  GimpOperationSeamlessClone *self = GIMP_OPERATION_SEAMLESS_CLONE (object);
+
+  switch (property_id)
+    {
+    case PROP_POINTS:
+      self->ptList = g_value_get_pointer (value);
+      break;
+    case PROP_X:
+      self->x = g_value_get_int (value);
+      break;
+    case PROP_Y:
+      self->y = g_value_get_int (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+typedef struct {
+  gint x, y;
+} SPoint;
+
+static void
+gimp_operation_seamless_clone_make_mesh (GimpOperationSeamlessClone *self)
+{
+  P2tCDT *CDT;
+  SPoint *pt;
+  gint    i;
+
+  gint min_x = G_MAXINT, max_x = -G_MAXINT, min_y = G_MAXINT, max_y = -G_MAXINT;
+
+  GPtrArray *tmpPts, *tris;
+
+  if (self->mesh != NULL)
+    return;
+
+  tmpPts = g_ptr_array_new ();
+
+  printf ("Making mesh from %d points!\n", self->ptList->len);
+
+  for (i = 0; i < self->ptList->len; i++)
+    {
+      pt = (SPoint*) g_ptr_array_index (self->ptList, i);
+      min_x = MIN (pt->x, min_x);
+      min_y = MIN (pt->y, min_y);
+      max_x = MAX (pt->x, max_x);
+      max_y = MAX (pt->y, max_y);
+      g_ptr_array_add (tmpPts, p2t_point_new_dd (pt->x, pt->y));
+    }
+
+  self->mesh_bounds.x = min_x;
+  self->mesh_bounds.y = min_y;
+  self->mesh_bounds.width = max_x - min_x;
+  self->mesh_bounds.height = max_y - min_y;
+
+  CDT = p2t_cdt_new (tmpPts);
+  p2t_cdt_triangulate (CDT);
+
+  tris = p2t_cdt_get_triangles (CDT);
+  printf ("The mesh has %d triangles!\n", tris->len);
+
+  self->mesh = cairo_pattern_create_mesh ();
+
+  for (i = 0; i < tris->len; i++)
+    {
+      P2tPoint* tpt;
+      cairo_mesh_pattern_begin_patch (self->mesh);
+
+      tpt = p2t_triangle_get_point (triangle_index(tris,i), 0);
+      cairo_mesh_pattern_move_to (self->mesh, tpt->x, tpt->y);
+
+      tpt = p2t_triangle_get_point (triangle_index(tris,i), 1);
+      cairo_mesh_pattern_line_to (self->mesh, tpt->x, tpt->y);
+
+      tpt = p2t_triangle_get_point (triangle_index(tris,i), 2);
+      cairo_mesh_pattern_line_to (self->mesh, tpt->x, tpt->y);
+
+      tpt = p2t_triangle_get_point (triangle_index(tris,i), 0);
+      cairo_mesh_pattern_line_to (self->mesh, tpt->x, tpt->y);
+
+      cairo_mesh_pattern_set_corner_color_rgb (self->mesh, 0, 1, 0, 0);
+      cairo_mesh_pattern_set_corner_color_rgb (self->mesh, 1, 0, 1, 0);
+      cairo_mesh_pattern_set_corner_color_rgb (self->mesh, 2, 0, 0, 1);
+
+      cairo_mesh_pattern_end_patch (self->mesh);
+    }
+
+  p2t_cdt_free (CDT);
+}
+
+static GeglRectangle
+gimp_operation_seamless_clone_get_bounding_box (GeglOperation *operation)
+{
+  return GIMP_OPERATION_SEAMLESS_CLONE (operation)->mesh_bounds;
+}
+
+static gboolean
+gimp_operation_seamless_clone_process (GeglOperation       *operation,
+                                       GeglBuffer          *output,
+                                       const GeglRectangle *roi)
+{
+  GimpOperationSeamlessClone *self = GIMP_OPERATION_SEAMLESS_CLONE (operation);
+
+  guchar          *data = g_new0 (guchar, roi->width * roi->height * 4);
+  cairo_t         *cr;
+  cairo_surface_t *surface;
+
+  surface = cairo_image_surface_create_for_data (data,
+                                                 CAIRO_FORMAT_ARGB32,
+                                                 roi->width,
+                                                 roi->height,
+                                                 roi->width * 4);
+
+  cr = cairo_create (surface);
+  // cairo_translate (cr, -roi->x, -roi->y);
+  cairo_set_source (cr, self->mesh);
+  cairo_paint (cr);
+
+  gegl_buffer_set (output, roi, babl_format ("B'aG'aR'aA u8"), data,
+                   GEGL_AUTO_ROWSTRIDE);
+
+  cairo_destroy (cr);
+  cairo_surface_destroy (surface);
+  g_free (data);
+
+  return  TRUE;
+}
+
+static void
+gimp_operation_seamless_clone_prepare (GeglOperation *operation)
+{
+  GimpOperationSeamlessClone *self = GIMP_OPERATION_SEAMLESS_CLONE (operation);
+
+  printf ("Preparing!\n");
+
+  gegl_operation_set_format (operation, "output", babl_format ("RaGaBaA float"));
+
+  gimp_operation_seamless_clone_make_mesh (self);
+}
diff --git a/app/gegl/gimpoperationseamlessclone.h b/app/gegl/gimpoperationseamlessclone.h
new file mode 100644
index 0000000..477cd52
--- /dev/null
+++ b/app/gegl/gimpoperationseamlessclone.h
@@ -0,0 +1,58 @@
+/* GIMP - The GNU Image Manipulation Program
+ *
+ * gimpoperationseamlessclone.h
+ * Copyright (C) 2011 Barak Itkin <lightningismyname gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_OPERATION_SEAMLESS_CLONE_H__
+#define __GIMP_OPERATION_SEAMLESS_CLONE_H__
+
+
+#include <gegl-plugin.h>
+#include <operation/gegl-operation-source.h>
+#include <cairo.h>
+
+#define GIMP_TYPE_OPERATION_SEAMLESS_CLONE            (gimp_operation_seamless_clone_get_type ())
+#define GIMP_OPERATION_SEAMLESS_CLONE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_SEAMLESS_CLONE, GimpOperationSeamlessClone))
+#define GIMP_OPERATION_SEAMLESS_CLONE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GIMP_TYPE_OPERATION_SEAMLESS_CLONE, GimpOperationSeamlessCloneClass))
+#define GIMP_IS_OPERATION_SEAMLESS_CLONE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPERATION_SEAMLESS_CLONE))
+#define GIMP_IS_OPERATION_SEAMLESS_CLONE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIMP_TYPE_OPERATION_SEAMLESS_CLONE))
+#define GIMP_OPERATION_SEAMLESS_CLONE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIMP_TYPE_OPERATION_SEAMLESS_CLONE, GimpOperationSeamlessCloneClass))
+
+
+typedef struct _GimpOperationSeamlessCloneClass GimpOperationSeamlessCloneClass;
+
+struct _GimpOperationSeamlessClone
+{
+  GeglOperationSource      parent_instance;
+
+  GPtrArray             *ptList;
+  gint                   x, y;
+
+  cairo_pattern_t       *mesh;
+  GeglRectangle          mesh_bounds;
+};
+
+struct _GimpOperationSeamlessCloneClass
+{
+  GeglOperationSourceClass  parent_class;
+};
+
+
+GType   gimp_operation_seamless_clone_get_type (void) G_GNUC_CONST;
+
+
+#endif /* __GIMP_OPERATION_SEAMLESS_CLONE_H__ */
diff --git a/app/gegl/poly2tri-c/common/cutils.h b/app/gegl/poly2tri-c/common/cutils.h
new file mode 100644
index 0000000..45bfe9d
--- /dev/null
+++ b/app/gegl/poly2tri-c/common/cutils.h
@@ -0,0 +1,37 @@
+/* 
+ * File:   cutils.h
+ * Author: user
+ *
+ * Created on 28 ××× 2011, 02:24
+ */
+
+#ifndef CUTILS_H
+#define	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))
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* CUTILS_H */
+
diff --git a/app/gegl/poly2tri-c/common/poly2tri-private.h b/app/gegl/poly2tri-c/common/poly2tri-private.h
new file mode 100644
index 0000000..4fe6da7
--- /dev/null
+++ b/app/gegl/poly2tri-c/common/poly2tri-private.h
@@ -0,0 +1,34 @@
+/* 
+ * File:   poly2tri-private.h
+ * Author: user
+ *
+ * Created on 4 ×××× 2011, 13:22
+ */
+
+#ifndef POLY2TRI_PRIVATE_H
+#define	POLY2TRI_PRIVATE_H
+
+#ifdef	__cplusplus
+extern "C"
+{
+#endif
+
+typedef struct Node_ P2tNode;
+typedef struct AdvancingFront_ P2tAdvancingFront;
+typedef struct CDT_ P2tCDT;
+typedef struct Edge_ P2tEdge;
+typedef struct Point_ P2tPoint;
+typedef struct Triangle_ 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/app/gegl/poly2tri-c/common/shapes.c b/app/gegl/poly2tri-c/common/shapes.c
new file mode 100644
index 0000000..4bd4160
--- /dev/null
+++ b/app/gegl/poly2tri-c/common/shapes.c
@@ -0,0 +1,732 @@
+/* 
+ * 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_new (P2tPoint, 1);
+  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_new (P2tPoint, 1);
+  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_free (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_new (P2tEdge, 1);
+  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_free (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;
+}
+
+//  /// Add two points_ component-wise.
+//
+//  Point operator + (const Point& a, const Point& b)
+//  {
+//    return Point (a.x + b.x, a.y + b.y);
+//  }
+//
+//  /// Subtract two points_ component-wise.
+//
+//  Point operator - (const Point& a, const Point& b)
+//  {
+//    return Point (a.x - b.x, a.y - b.y);
+//  }
+//
+//  /// Multiply point by scalar
+//
+//  Point operator * (double s, const Point& a)
+//  {
+//    return Point (s * a.x, s * a.y);
+//  }
+
+//  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;
+}
+//
+//  gboolean operator != (const Point& a, const Point& b)
+//  {
+//    return a.x != b.x && a.y != b.y;
+//  }
+
+//  /// Peform the dot product on two vectors.
+//
+//  double
+//  Dot (const Point& a, const Point& b)
+//  {
+//    return a.x * b.x + a.y * b.y;
+//  }
+//
+//  /// Perform the cross product on two vectors. In 2D this produces a scalar.
+//
+//  double
+//  Cross (const Point& a, const Point& b)
+//  {
+//    return a.x * b.y - a.y * b.x;
+//  }
+//
+//  /// Perform the cross product on a point and a scalar. In 2D this produces
+//  /// a point.
+//
+//  Point
+//  Cross (const Point& a, double s)
+//  {
+//    return Point (s * a.y, -s * a.x);
+//  }
+//
+//  /// Perform the cross product on a scalar and a point. In 2D this produces
+//  /// a point.
+//
+//  Point
+//  Cross (const double s, const Point& a)
+//  {
+//    return Point (-s * a.y, s * a.x);
+//  }
+
+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/app/gegl/poly2tri-c/common/shapes.h b/app/gegl/poly2tri-c/common/shapes.h
new file mode 100644
index 0000000..03686dc
--- /dev/null
+++ b/app/gegl/poly2tri-c/common/shapes.h
@@ -0,0 +1,150 @@
+/*
+ * 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 guard
+#ifndef SHAPES_H
+#define SHAPES_H
+
+#include <stddef.h>
+#include <assert.h>
+#include <math.h>
+#include "poly2tri-private.h"
+#include "cutils.h"
+
+struct Point_
+{
+  double x, y;
+  /// The edges this point constitutes an upper ending point
+  P2tEdgePtrArray edge_list;
+};
+
+void p2t_point_init_dd (P2tPoint* THIS, double x, double y);
+P2tPoint* p2t_point_new_dd (double x, double y);
+void p2t_point_init (P2tPoint* THIS);
+P2tPoint* p2t_point_new ();
+
+void p2t_point_destroy (P2tPoint* THIS);
+void
+p2t_point_free (P2tPoint* THIS);
+
+// Represents a simple polygon's edge
+
+struct Edge_
+{
+  P2tPoint* p, *q;
+};
+
+void p2t_edge_init (P2tEdge* THIS, P2tPoint* p1, P2tPoint* p2);
+P2tEdge* p2t_edge_new (P2tPoint* p1, P2tPoint* p2);
+
+void p2t_edge_destroy (P2tEdge* 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"
+
+struct Triangle_
+{
+  /// Flags to determine if an edge is a Constrained edge
+  gboolean constrained_edge[3];
+  /// Flags to determine if an edge is a Delauney edge
+  gboolean delaunay_edge[3];
+
+  //private:
+
+  /// Triangle points
+  P2tPoint * points_[3];
+  /// Neighbor list
+  struct Triangle_ * neighbors_[3];
+
+  /// Has this triangle been marked as an interior triangle?
+  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/app/gegl/poly2tri-c/common/utils.c b/app/gegl/poly2tri-c/common/utils.c
new file mode 100644
index 0000000..24ce71b
--- /dev/null
+++ b/app/gegl/poly2tri-c/common/utils.c
@@ -0,0 +1,95 @@
+
+/*
+ * 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)
+{
+  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;
+
+  if (oabd <= EPSILON)
+    {
+      return FALSE;
+    }
+
+  double cdx = pc->x - pdx;
+  double cdy = pc->y - pdy;
+
+  double cdxady = cdx * ady;
+  double adxcdy = adx * cdy;
+  double ocad = cdxady - adxcdy;
+
+  if (ocad <= EPSILON)
+    {
+      return FALSE;
+    }
+
+  return TRUE;
+}
diff --git a/app/gegl/poly2tri-c/common/utils.h b/app/gegl/poly2tri-c/common/utils.h
new file mode 100644
index 0000000..83188c8
--- /dev/null
+++ b/app/gegl/poly2tri-c/common/utils.h
@@ -0,0 +1,63 @@
+/* 
+ * 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 UTILS_H
+#define UTILS_H
+
+#include <glib.h>
+#include "poly2tri-private.h"
+#include "cutils.h"
+#include "shapes.h"
+
+#define PI_3div4 (3 * M_PI / 4)
+#define EPSILON  (1e-12)
+
+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/app/gegl/poly2tri-c/poly2tri.h b/app/gegl/poly2tri-c/poly2tri.h
new file mode 100644
index 0000000..487755e
--- /dev/null
+++ b/app/gegl/poly2tri-c/poly2tri.h
@@ -0,0 +1,39 @@
+/* 
+ * 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 POLY2TRI_H
+#define POLY2TRI_H
+
+#include "common/shapes.h"
+#include "sweep/cdt.h"
+
+#endif
+
diff --git a/app/gegl/poly2tri-c/sweep/advancing_front.c b/app/gegl/poly2tri-c/sweep/advancing_front.c
new file mode 100644
index 0000000..2b387f9
--- /dev/null
+++ b/app/gegl/poly2tri-c/sweep/advancing_front.c
@@ -0,0 +1,215 @@
+/*
+ * 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_new (P2tNode, 1);
+  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_new (P2tNode, 1);
+  p2t_node_init_pt_tr (THIS, p, t);
+  return 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_new (P2tAdvancingFront, 1);
+  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_free (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/app/gegl/poly2tri-c/sweep/advancing_front.h b/app/gegl/poly2tri-c/sweep/advancing_front.h
new file mode 100644
index 0000000..c232fae
--- /dev/null
+++ b/app/gegl/poly2tri-c/sweep/advancing_front.h
@@ -0,0 +1,87 @@
+/*
+ * 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 ADVANCED_FRONT_H
+#define ADVANCED_FRONT_H
+
+#include "../common/poly2tri-private.h"
+#include "../common/shapes.h"
+
+// Advancing front node
+
+struct Node_
+{
+  P2tPoint* point;
+  P2tTriangle* triangle;
+
+  struct Node_* next;
+  struct Node_* 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);
+
+// 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/app/gegl/poly2tri-c/sweep/cdt.c b/app/gegl/poly2tri-c/sweep/cdt.c
new file mode 100644
index 0000000..9a0b679
--- /dev/null
+++ b/app/gegl/poly2tri-c/sweep/cdt.c
@@ -0,0 +1,90 @@
+/* 
+ * 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_new (P2tCDT, 1);
+  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_free (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/app/gegl/poly2tri-c/sweep/cdt.h b/app/gegl/poly2tri-c/sweep/cdt.h
new file mode 100644
index 0000000..bd40198
--- /dev/null
+++ b/app/gegl/poly2tri-c/sweep/cdt.h
@@ -0,0 +1,101 @@
+/* 
+ * 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 CDT_H
+#define 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/app/gegl/poly2tri-c/sweep/sweep.c b/app/gegl/poly2tri-c/sweep/sweep.c
new file mode 100644
index 0000000..2718bb3
--- /dev/null
+++ b/app/gegl/poly2tri-c/sweep/sweep.c
@@ -0,0 +1,932 @@
+/*
+ * 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.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++)
+    {
+      g_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)
+{
+  if (p2t_sweep_is_edge_side_of_triangle (THIS, triangle, ep, eq))
+    {
+      return;
+    }
+
+  P2tPoint* p1 = p2t_triangle_point_ccw (triangle, point);
+  P2tOrientation 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;
+    }
+
+  P2tPoint* p2 = p2t_triangle_point_cw (triangle, point);
+  P2tOrientation 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)
+    {
+      p2t_triangle_mark_constrained_edge_i (triangle, index);
+      P2tTriangle* 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);
+
+  p2t_triangle_mark_neighbor_tr (triangle, node->triangle);
+  p2t_sweepcontext_add_to_map (tcx, triangle);
+
+  P2tNode* 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)
+    {
+      double angle = p2t_sweep_hole_angle (THIS, node);
+      if (angle > M_PI_2 || angle < -M_PI_2) break;
+      p2t_sweep_fill (THIS, tcx, node);
+      node = node->next;
+    }
+
+  // Fill left holes
+  node = n->prev;
+
+  while (node->prev)
+    {
+      double angle = p2t_sweep_hole_angle (THIS, node);
+      if (angle > M_PI_2 || angle < -M_PI_2) 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);
+        }
+    }
+}
+
+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++)
+    {
+      if (t->delaunay_edge[i])
+        continue;
+
+      P2tTriangle* 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);
+
+          // 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;
+            }
+
+          gboolean inside = p2t_sweep_incircle (THIS, p, p2t_triangle_point_ccw (t, p), p2t_triangle_point_cw (t, p), op);
+
+          if (inside)
+            {
+              // 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
+              gboolean 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;
+
+  if (oabd <= 0)
+    return FALSE;
+
+  double cdx = pc->x - pd->x;
+  double cdy = pc->y - pd->y;
+
+  double cdxady = cdx * ady;
+  double adxcdy = adx * cdy;
+  double ocad = cdxady - adxcdy;
+
+  if (ocad <= 0)
+    return FALSE;
+
+  double bdxcdy = bdx * cdy;
+  double cdxbdy = cdx * bdy;
+
+  double alift = adx * adx + ady * ady;
+  double blift = bdx * bdx + bdy * bdy;
+  double clift = cdx * cdx + cdy * cdy;
+
+  double 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;
+  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);
+
+  gboolean ce1, ce2, ce3, ce4;
+  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);
+
+  gboolean de1, de2, de3, de4;
+  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)
+{
+  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
+  int 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/app/gegl/poly2tri-c/sweep/sweep.h b/app/gegl/poly2tri-c/sweep/sweep.h
new file mode 100644
index 0000000..d1d2da3
--- /dev/null
+++ b/app/gegl/poly2tri-c/sweep/sweep.h
@@ -0,0 +1,270 @@
+/*
+ * 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 SWEEP_H
+#define 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);
+
+  /**
+   *
+   * @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/app/gegl/poly2tri-c/sweep/sweep_context.c b/app/gegl/poly2tri-c/sweep/sweep_context.c
new file mode 100644
index 0000000..2e41e5e
--- /dev/null
+++ b/app/gegl/poly2tri-c/sweep/sweep_context.c
@@ -0,0 +1,313 @@
+/*
+ * 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_);
+  g_free (THIS->af_head_);
+  g_free (THIS->af_middle_);
+  g_free (THIS->af_tail_);
+
+  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;
+
+  // 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;
+    }
+
+  double dx = kAlpha * (xmax - xmin);
+  double 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 intuitive 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/app/gegl/poly2tri-c/sweep/sweep_context.h b/app/gegl/poly2tri-c/sweep/sweep_context.h
new file mode 100644
index 0000000..0e9a033
--- /dev/null
+++ b/app/gegl/poly2tri-c/sweep/sweep_context.h
@@ -0,0 +1,133 @@
+/*
+ * 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 SWEEP_CONTEXT_H
+#define 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/app/tools/gimpseamlessclonetool.c b/app/tools/gimpseamlessclonetool.c
index 0354d42..a023517 100644
--- a/app/tools/gimpseamlessclonetool.c
+++ b/app/tools/gimpseamlessclonetool.c
@@ -61,7 +61,8 @@
 
 #include "gimp-intl.h"
 
-#define DBG_CALL_NAME() g_print ("@@@ %s @@@\n", __func__)
+#define DBG_CALL_NAME() g_print ("@@@ start %s @@@\n", __func__)
+#define DBG_CALL_NAME_E() g_print ("@@@ finish %s @@@\n", __func__)
 #define SEAMLESS_CLONE_LIVE_PREVIEW TRUE
 
 enum
@@ -210,10 +211,12 @@ gimp_seamless_clone_tool_init (GimpSeamlessCloneTool *self)
   self->state           = SEAMLESS_CLONE_STATE_NOTHING;
 
   self->paste_buf       = NULL;
+  self->paste_node      = NULL;
   self->render_node     = NULL;
   self->image_map       = NULL;
   self->translate_op    = NULL;
   self->outline         = NULL;
+  DBG_CALL_NAME_E();
 }
 
 static void
@@ -271,6 +274,7 @@ gimp_seamless_clone_tool_control (GimpTool       *tool,
     }
 
   GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
+  DBG_CALL_NAME_E();
 }
 
 /**
@@ -299,6 +303,7 @@ gimp_seamless_clone_tool_update_image_map_easy (GimpSeamlessCloneTool *sct)
     }
 
   gimp_seamless_clone_tool_image_map_update (sct);
+  DBG_CALL_NAME_E();
 }
 
 /* When one of the tool options was modified, we wish to take the following
@@ -333,6 +338,8 @@ gimp_seamless_clone_tool_options_notify (GimpTool         *tool,
 
   /* Allow drawing to continue */
   gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
+
+  DBG_CALL_NAME_E();
 }
 
 static void
@@ -344,7 +351,7 @@ gimp_seamless_clone_tool_start (GimpSeamlessCloneTool *sct,
   gimp_draw_tool_start (GIMP_DRAW_TOOL (sct), display);
   // TODO free and update stuff
 
-
+  DBG_CALL_NAME_E();
 }
 static void
 gimp_seamless_clone_tool_button_press (GimpTool            *tool,
@@ -441,6 +448,7 @@ gimp_seamless_clone_tool_motion (GimpTool         *tool,
 #endif
 
   gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
+  DBG_CALL_NAME_E();
 }
 
 void
@@ -480,6 +488,7 @@ gimp_seamless_clone_tool_button_release (GimpTool              *tool,
     }
 
   gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
+  DBG_CALL_NAME_E();
 }
 
 static void
@@ -499,6 +508,7 @@ gimp_seamless_clone_tool_cursor_update (GimpTool         *tool,
     gimp_tool_control_set_cursor_modifier (tool->control, GIMP_CURSOR_MODIFIER_NONE);
 
   GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
+  DBG_CALL_NAME_E();
 }
 
 typedef struct {
@@ -537,6 +547,7 @@ gimp_seamless_clone_tool_draw (GimpDrawTool *draw_tool)
         (gdouble)(sct->paste_y + (gint)(sct->cursor_y - sct->movement_start_y + sct->paste_h / 2)));
 
   gimp_draw_tool_pop_group (draw_tool);
+  DBG_CALL_NAME_E();
 }
 
 /* TODO - extract this logic for general gimp->gegl buffer conversion.
@@ -585,6 +596,7 @@ gimp_buffer_to_gegl_buffer_with_progress (GimpSeamlessCloneTool *sct)
                                  "points",    sct->outline,
                                  "width",     gimp_buffer_get_width (gimpbuf),
                                  "height",    gimp_buffer_get_height (gimpbuf),
+                                 "threshold", 0.5f,
                                  NULL);
 
   gegl_node_connect_to (input, "output",
@@ -627,6 +639,7 @@ gimp_buffer_to_gegl_buffer_with_progress (GimpSeamlessCloneTool *sct)
   sct->paste_h = tempR.height;
 
   tile_manager_unref (tiles);
+  DBG_CALL_NAME_E();
 }
 
 /* The final graph would be
@@ -674,7 +687,8 @@ gimp_seamless_clone_tool_create_render_node (GimpSeamlessCloneTool *sct)
                               NULL);
 
   interpolate = gegl_node_new_child (node,
-                                     "operation", "gegl:nop",
+                                     "operation", "gimp:seamless-clone",
+                                     "points", sct->outline,
                                      NULL);
 
   sct->translate_op = gegl_node_new_child (node,
@@ -683,13 +697,13 @@ gimp_seamless_clone_tool_create_render_node (GimpSeamlessCloneTool *sct)
                                            "filter", "nearest", NULL);
 
   add = gegl_node_new_child (node,
-                              "operation", "gegl:add",
-                              NULL);
+                             "operation", "gegl:add",
+                             NULL);
 
   paste = gegl_node_new_child (node,
-                              "operation", "gegl:buffer-source",
-                              "buffer", sct->paste_buf,
-                              NULL);
+                               "operation", "gegl:buffer-source",
+                               "buffer", sct->paste_buf,
+                               NULL);
 
   sct->paste_node = paste;
 
@@ -705,8 +719,8 @@ gimp_seamless_clone_tool_create_render_node (GimpSeamlessCloneTool *sct)
   gegl_node_connect_to (input, "output",
                         diff, "aux");
 
-  gegl_node_connect_to (diff, "output",
-                        interpolate, "input");
+//  gegl_node_connect_to (diff, "output",
+//                        interpolate, "input");
 
   gegl_node_connect_to (interpolate, "output",
                         add, "aux");
@@ -715,6 +729,7 @@ gimp_seamless_clone_tool_create_render_node (GimpSeamlessCloneTool *sct)
                         output, "input");
 
   sct->render_node = node;
+  DBG_CALL_NAME_E();
 }
 
 static void
@@ -722,6 +737,7 @@ gimp_seamless_clone_tool_render_node_update (GimpSeamlessCloneTool *sct)
 {
   DBG_CALL_NAME();
   /* For now, do nothing */
+  DBG_CALL_NAME_E();
 }
 
 static void
@@ -741,6 +757,7 @@ gimp_seamless_clone_tool_create_image_map (GimpSeamlessCloneTool *sct,
   g_signal_connect (sct->image_map, "flush",
                     G_CALLBACK (gimp_seamless_clone_tool_image_map_flush),
                     sct);
+  DBG_CALL_NAME_E();
 }
 
 static void
@@ -752,6 +769,7 @@ gimp_seamless_clone_tool_image_map_flush (GimpImageMap *image_map,
   DBG_CALL_NAME();
   gimp_projection_flush_now (gimp_image_get_projection (image));
   gimp_display_flush_now (tool->display);
+  DBG_CALL_NAME();
 }
 
 static void
@@ -792,4 +810,5 @@ gimp_seamless_clone_tool_image_map_update (GimpSeamlessCloneTool *ct)
   visible.y -= off_y;
 
   gimp_image_map_apply (ct->image_map, &visible);
+  DBG_CALL_NAME_E();
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]