Commit 17f8b260 authored by Barak Itkin's avatar Barak Itkin
Browse files

Update the seamless-clone operation to use the new poly2tri-c lib

* GEGL now depends on poly2tri-c (git commit 566e50 or later)
* The old version of poly2tri-c was removed from GEGL's repo
parent 69df78e5
......@@ -52,6 +52,7 @@ m4_define([pango_required_version], [0.0.0])
m4_define([pangocairo_required_version], [0.0.0])
m4_define([png_required_version], [0.0.0])
m4_define([sdl_required_version], [0.0.0])
m4_define([poly2tri-c_required_version], [0.0.0])
AC_INIT(gegl, gegl_major_version.gegl_minor_version.gegl_micro_version)
......@@ -458,6 +459,14 @@ PKG_CHECK_MODULES(DEP,
DEP_CFLAGS=`$PKG_CONFIG --cflags $GLIB_PACKAGES gthread-2.0`
DEP_LIBS=`$PKG_CONFIG --libs $GLIB_PACKAGES gthread-2.0`
PKG_CHECK_MODULES(P2TC,
poly2tri-c >= poly2tri-c_required_version, ,
AC_MSG_ERROR([
*** Poly2tri-C not found. You can find it on http://code.google.com/p/poly2tri-c/
*** Errors follow:
$P2TC_PKG_ERRORS]))
######################
# gettext i18n support
######################
......@@ -1095,11 +1104,6 @@ operations/core/Makefile
operations/common/Makefile
operations/common/perlin/Makefile
operations/common/seamless-clone/Makefile
operations/common/seamless-clone/poly2tri-c/Makefile
operations/common/seamless-clone/poly2tri-c/common/Makefile
operations/common/seamless-clone/poly2tri-c/refine/Makefile
operations/common/seamless-clone/poly2tri-c/render/Makefile
operations/common/seamless-clone/poly2tri-c/sweep/Makefile
operations/external/Makefile
operations/generated/Makefile
operations/transform/Makefile
......
......@@ -7,6 +7,6 @@ pluginsdir=@libdir@/@PACKAGE_NAME@-@GEGL_API_VERSION@
Name: GEGL
Description: Generic Graphics Library
Version: @GEGL_REAL_VERSION@
Requires: @GLIB_PACKAGES@ babl
Requires: @GLIB_PACKAGES@ babl poly2tri-c
Libs: -L${libdir} -l@PACKAGE_NAME@-@GEGL_API_VERSION@
Cflags: -I${includedir}/@PACKAGE_NAME@-@GEGL_API_VERSION@
SUBDIRS = poly2tri-c
include $(top_srcdir)/operations/Makefile-common.am
AM_LDFLAGS += $(op_libs) poly2tri-c/libpoly2tri-c.la
AM_LDFLAGS += $(op_libs) $(P2TC_LIBS)
AM_CFLAGS += $(op_cflags) $(P2TC_CFLAGS)
sc_common_files = \
make-mesh.c \
......
......@@ -31,8 +31,8 @@
#include <stdio.h> /* TODO: get rid of this debugging way! */
#include "seamless-clone.h"
#include "poly2tri-c/poly2tri.h"
#include "poly2tri-c/refine/triangulation.h"
#include <poly2tri-c/p2t/poly2tri.h>
#include <poly2tri-c/refine/refine.h>
/* Define the directions
*
......
......@@ -26,9 +26,8 @@
#include <gegl.h>
#include <stdio.h> /* TODO: get rid of this debugging way! */
#include "poly2tri-c/poly2tri.h"
#include "poly2tri-c/refine/triangulation.h"
#include "poly2tri-c/refine/refine.h"
#include <poly2tri-c/p2t/poly2tri.h>
#include <poly2tri-c/refine/refine.h>
#include "seamless-clone.h"
#define g_ptr_array_index_cyclic(array,index_) g_ptr_array_index(array,(index_)%((array)->len))
......@@ -186,28 +185,20 @@ sc_sample_list_free (ScSampleList *self)
}
ScMeshSampling*
sc_mesh_sampling_compute (ScOutline *outline,
P2tRTriangulation *mesh)
sc_mesh_sampling_compute (ScOutline *outline,
P2trMesh *mesh)
{
GPtrArray *points = g_ptr_array_new ();
GHashTable *pt2sample = g_hash_table_new (g_direct_hash, g_direct_equal);
gint i;
/* Note that the get_points function increases the refcount of the
* returned points, so we must unref them when done with them
*/
p2tr_triangulation_get_points (mesh, points);
P2trPoint *pt = NULL;
P2trHashSetIter iter;
for (i = 0; i < points->len; i++)
p2tr_hash_set_iter_init (&iter, mesh->points);
while (p2tr_hash_set_iter_next (&iter, (gpointer*) &pt))
{
P2tRPoint *pt = (P2tRPoint*) g_ptr_array_index (points, i);
ScSampleList *sl = sc_sample_list_compute (outline, pt->x, pt->y);
g_hash_table_insert (pt2sample, pt, sl);
}
ScSampleList *sl = sc_sample_list_compute (outline, pt->c.x, pt->c.y);
g_hash_table_insert (pt2sample, pt, sl);
}
/* We will unref the points when freeing the hash table */
g_ptr_array_free (points, TRUE);
return pt2sample;
}
......@@ -217,7 +208,7 @@ sc_mesh_sampling_entry_free_hfunc (gpointer point,
gpointer unused)
{
/* Unref the point returned from triangulation_get_points */
p2tr_point_unref ((P2tRPoint*)point);
p2tr_point_unref ((P2trPoint*)point);
/* Free the sampling list */
sc_sample_list_free ((ScSampleList*)sampling_list);
}
......@@ -236,7 +227,7 @@ sc_mesh_sampling_free (ScMeshSampling *self)
* @mesh_bounds: A rectangle in which the bounds of the mesh should be
* stored
*/
P2tRTriangulation*
P2trMesh*
sc_make_fine_mesh (ScOutline *outline,
GeglRectangle *mesh_bounds,
int max_refine_steps)
......@@ -245,10 +236,13 @@ sc_make_fine_mesh (ScOutline *outline,
gint i, N = realOutline->len;
gint min_x = G_MAXINT, max_x = -G_MAXINT, min_y = G_MAXINT, max_y = -G_MAXINT;
/* An array of P2tRPoint*, holding the outline points */
/* An array of P2tPoint*, holding the outline points */
GPtrArray *mesh_points = g_ptr_array_new ();
P2tRTriangulation *T;
P2tCDT *rough_cdt;
P2trCDT *fine_cdt;
P2trMesh *result;
P2trDelaunayTerminator *refiner;
for (i = 0; i < N; i++)
{
......@@ -261,7 +255,7 @@ sc_make_fine_mesh (ScOutline *outline,
/* No one should care if the points are given in reverse order,
* and prepending to the GList is more efficient */
g_ptr_array_add (mesh_points, p2tr_point_new (pt->x, pt->y));
g_ptr_array_add (mesh_points, p2t_point_new_dd (pt->x, pt->y));
}
mesh_bounds->x = min_x;
......@@ -269,14 +263,26 @@ sc_make_fine_mesh (ScOutline *outline,
mesh_bounds->width = max_x + 1 - min_x;
mesh_bounds->height = max_y + 1 - min_y;
T = p2tr_triangulate_and_refine (mesh_points, max_refine_steps);
rough_cdt = p2t_cdt_new (mesh_points);
p2t_cdt_triangulate (rough_cdt);
fine_cdt = p2tr_cdt_new (rough_cdt);
/* We no longer need the rough CDT */
p2t_cdt_free (rough_cdt);
refiner = p2tr_dt_new (G_PI / 6, p2tr_dt_false_too_big, fine_cdt);
p2tr_dt_refine (refiner, max_refine_steps);
p2tr_dt_free (refiner);
p2tr_mesh_ref (result = fine_cdt->mesh);
p2tr_cdt_free_full (fine_cdt, FALSE);
for (i = 0; i < N; i++)
{
p2tr_point_unref ((P2tRPoint*) g_ptr_array_index (mesh_points, i));
}
p2t_point_free ((P2tPoint*) g_ptr_array_index (mesh_points, i));
}
g_ptr_array_free (mesh_points, TRUE);
return T;
return result;
}
......@@ -31,10 +31,10 @@ typedef GHashTable ScMeshSampling;
ScSampleList* sc_sample_list_compute (ScOutline *outline, gdouble Px, gdouble Py);
void sc_sample_list_free (ScSampleList *self);
ScMeshSampling* sc_mesh_sampling_compute (ScOutline *outline, P2tRTriangulation *mesh);
ScMeshSampling* sc_mesh_sampling_compute (ScOutline *outline, P2trMesh *mesh);
void sc_mesh_sampling_free (ScMeshSampling *self);
P2tRTriangulation* sc_make_fine_mesh (ScOutline *outline, GeglRectangle *mesh_bounds, int max_refine_steps);
P2trMesh* sc_make_fine_mesh (ScOutline *outline, GeglRectangle *mesh_bounds, int max_refine_steps);
#endif
/Makefile
/Makefile.in
/.deps
/.libs
/*.la
/*.lo
/*.so
SUBDIRS = \
common \
sweep \
refine \
render
noinst_LTLIBRARIES = libpoly2tri-c.la
libpoly2tri_c_la_SOURCES = poly2tri.h
libpoly2tri_c_la_LIBADD = \
common/libpoly2tri-c-common.la \
sweep/libpoly2tri-c-sweep.la \
refine/libpoly2tri-c-refine.la \
render/libpoly2tri-c-render.la
libpoly2tri_c_la_CFLAGS = $(DEP_CFLAGS) -fPIC
bin_PROGRAMS = p2tc
p2tc_SOURCES = main.c poly2tri.h
p2tc_LDADD = libpoly2tri-c.la $(GLIB_LIBS) -lm
p2tc_CFLAGS = $(DEP_CFLAGS) -fPIC
/Makefile
/Makefile.in
/.deps
/.libs
/*.la
/*.lo
/*.so
noinst_LTLIBRARIES = libpoly2tri-c-common.la
libpoly2tri_c_common_la_SOURCES = \
cutils.h \
poly2tri-private.h \
shapes.c \
shapes.h \
utils.c \
utils.h
libpoly2tri_c_common_la_CFLAGS = $(GLIB_CFLAGS)
/*
* 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))
#define g_ptr_array_index_cyclic(array,index_) g_ptr_array_index(array,(index_)%((array)->len))
#ifdef __cplusplus
}
#endif
#endif /* CUTILS_H */
/*
* 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 _P2tNode P2tNode;
typedef struct AdvancingFront_ P2tAdvancingFront;
typedef struct CDT_ P2tCDT;
typedef struct _P2tEdge P2tEdge;
typedef struct _P2tPoint P2tPoint;
typedef struct _P2tTriangle P2tTriangle;
typedef struct SweepContext_ P2tSweepContext;
typedef struct Sweep_ P2tSweep;
typedef struct P2tSweepContextBasin_ P2tSweepContextBasin;
typedef struct P2tSweepContextEdgeEvent_ P2tSweepContextEdgeEvent;
#ifdef __cplusplus
}
#endif
#endif /* POLY2TRI_PRIVATE_H */
/*
* This file is a part of Poly2Tri-C - The C port of the Poly2Tri library
* Porting to C done by (c) Barak Itkin <lightningismyname@gmail.com>
* http://code.google.com/p/poly2tri-c/
*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "shapes.h"
#include <stdio.h>
#include <stdlib.h>
/// Default constructor does nothing (for performance).
void
p2t_point_init (P2tPoint* THIS)
{
THIS->x = 0;
THIS->y = 0;
THIS->edge_list = g_ptr_array_new ();
}
P2tPoint*
p2t_point_new ()
{
P2tPoint* THIS = g_slice_new (P2tPoint);
p2t_point_init (THIS);
return THIS;
}
/// Construct using coordinates.
void
p2t_point_init_dd (P2tPoint* THIS, double x, double y)
{
THIS->x = x;
THIS->y = y;
THIS->edge_list = g_ptr_array_new ();
}
P2tPoint*
p2t_point_new_dd (double x, double y)
{
P2tPoint* THIS = g_slice_new (P2tPoint);
p2t_point_init_dd (THIS, x, y);
return THIS;
}
void
p2t_point_destroy (P2tPoint* THIS)
{
g_ptr_array_free (THIS->edge_list, TRUE);
}
void
p2t_point_free (P2tPoint* THIS)
{
p2t_point_destroy (THIS);
g_slice_free (P2tPoint, THIS);
}
/// Constructor
void
p2t_edge_init (P2tEdge* THIS, P2tPoint* p1, P2tPoint* p2)
{
THIS->p = p1;
THIS->q = p2;
if (p1->y > p2->y)
{
THIS->q = p1;
THIS->p = p2;
}
else if (p1->y == p2->y)
{
if (p1->x > p2->x)
{
THIS->q = p1;
THIS->p = p2;
}
else if (p1->x == p2->x)
{
// Repeat points
assert (FALSE);
}
}
g_ptr_array_add (THIS->q->edge_list, THIS);
}
P2tEdge*
p2t_edge_new (P2tPoint* p1, P2tPoint* p2)
{
P2tEdge* THIS = g_slice_new (P2tEdge);
p2t_edge_init (THIS, p1, p2);
return THIS;
}
void
p2t_edge_destroy (P2tEdge* THIS) { }
void
p2t_edge_free (P2tEdge* THIS)
{
p2t_edge_destroy (THIS);
g_slice_free (P2tEdge, THIS);
}
P2tTriangle*
p2t_triangle_new (P2tPoint* a, P2tPoint* b, P2tPoint* c)
{
P2tTriangle *tr = g_new (P2tTriangle, 1);
p2t_triangle_init (tr, a, b, c);
return tr;
}
void
p2t_triangle_init (P2tTriangle* THIS, P2tPoint* a, P2tPoint* b, P2tPoint* c)
{
THIS->points_[0] = a;
THIS->points_[1] = b;
THIS->points_[2] = c;
THIS->neighbors_[0] = NULL;
THIS->neighbors_[1] = NULL;
THIS->neighbors_[2] = NULL;
THIS->constrained_edge[0] = THIS->constrained_edge[1] = THIS->constrained_edge[2] = FALSE;
THIS->delaunay_edge[0] = THIS->delaunay_edge[1] = THIS->delaunay_edge[2] = FALSE;
THIS->interior_ = FALSE;
}
// Update neighbor pointers
void
p2t_triangle_mark_neighbor_pt_pt_tr (P2tTriangle* THIS, P2tPoint* p1, P2tPoint* p2, P2tTriangle* t)
{
if ((p1 == THIS->points_[2] && p2 == THIS->points_[1]) || (p1 == THIS->points_[1] && p2 == THIS->points_[2]))
THIS->neighbors_[0] = t;
else if ((p1 == THIS->points_[0] && p2 == THIS->points_[2]) || (p1 == THIS->points_[2] && p2 == THIS->points_[0]))
THIS->neighbors_[1] = t;
else if ((p1 == THIS->points_[0] && p2 == THIS->points_[1]) || (p1 == THIS->points_[1] && p2 == THIS->points_[0]))
THIS->neighbors_[2] = t;
else
assert (0);
}
// Exhaustive search to update neighbor pointers
void
p2t_triangle_mark_neighbor_tr (P2tTriangle* THIS, P2tTriangle *t)
{
if (p2t_triangle_contains_pt_pt (t, THIS->points_[1], THIS->points_[2]))
{
THIS->neighbors_[0] = t;
p2t_triangle_mark_neighbor_pt_pt_tr (t, THIS->points_[1], THIS->points_[2], THIS);
}
else if (p2t_triangle_contains_pt_pt (t, THIS->points_[0], THIS->points_[2]))
{
THIS->neighbors_[1] = t;
p2t_triangle_mark_neighbor_pt_pt_tr (t, THIS->points_[0], THIS->points_[2], THIS);
}
else if (p2t_triangle_contains_pt_pt (t, THIS->points_[0], THIS->points_[1]))
{
THIS->neighbors_[2] = t;
p2t_triangle_mark_neighbor_pt_pt_tr (t, THIS->points_[0], THIS->points_[1], THIS);
}
}
/**
* Clears all references to all other triangles and points
*/
void
p2t_triangle_clear (P2tTriangle* THIS)
{
int i;
P2tTriangle *t;
for (i = 0; i < 3; i++)
{
t = THIS->neighbors_[i];
if (t != NULL)
{
p2t_triangle_clear_neighbor_tr (t, THIS);
}
}
p2t_triangle_clear_neighbors (THIS);
THIS->points_[0] = THIS->points_[1] = THIS->points_[2] = NULL;
}
void
p2t_triangle_clear_neighbor_tr (P2tTriangle* THIS, P2tTriangle *triangle)
{
if (THIS->neighbors_[0] == triangle)
{
THIS->neighbors_[0] = NULL;
}
else if (THIS->neighbors_[1] == triangle)
{
THIS->neighbors_[1] = NULL;
}
else
{
THIS->neighbors_[2] = NULL;
}
}
void
p2t_triangle_clear_neighbors (P2tTriangle* THIS)
{
THIS->neighbors_[0] = NULL;
THIS->neighbors_[1] = NULL;
THIS->neighbors_[2] = NULL;
}
void
p2t_triangle_clear_delunay_edges (P2tTriangle* THIS)
{
THIS->delaunay_edge[0] = THIS->delaunay_edge[1] = THIS->delaunay_edge[2] = FALSE;
}
P2tPoint*
p2t_triangle_opposite_point (P2tTriangle* THIS, P2tTriangle* t, P2tPoint* p)
{
P2tPoint *cw = p2t_triangle_point_cw (t, p);
double x = cw->x;
double y = cw->y;
x = p->x;
y = p->y;
P2tPoint* ham = p2t_triangle_point_cw (THIS, cw);
return p2t_triangle_point_cw (THIS, cw);
}
// Legalized triangle by rotating clockwise around point(0)
void
p2t_triangle_legalize_pt (P2tTriangle* THIS, P2tPoint *point)
{
THIS->points_[1] = THIS->points_[0];
THIS->points_[0] = THIS->points_[2];
THIS->points_[2] = point;
}
// Legalize triagnle by rotating clockwise around oPoint
void
p2t_triangle_legalize_pt_pt (P2tTriangle* THIS, P2tPoint *opoint, P2tPoint *npoint)
{
if (opoint == THIS->points_[0])