From: Sandro Santilli Date: Wed, 27 Jun 2012 14:26:47 +0000 (+0000) Subject: Add lwgeom_delaunay_triangulation (#1215) X-Git-Tag: 2.1.0beta2~854 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=080978de4ba971665aae2f768b51f140ed97593c;p=postgis Add lwgeom_delaunay_triangulation (#1215) git-svn-id: http://svn.osgeo.org/postgis/trunk@9993 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/liblwgeom/cunit/Makefile.in b/liblwgeom/cunit/Makefile.in index 5bce1da03..fc3f399f9 100644 --- a/liblwgeom/cunit/Makefile.in +++ b/liblwgeom/cunit/Makefile.in @@ -36,6 +36,7 @@ OBJS= \ cu_libgeom.o \ cu_split.o \ cu_stringbuffer.o \ + cu_triangulate.o \ cu_homogenize.o \ cu_out_wkt.o \ cu_out_wkb.o \ diff --git a/liblwgeom/cunit/cu_tester.c b/liblwgeom/cunit/cu_tester.c index 9befc6c88..9e2998164 100644 --- a/liblwgeom/cunit/cu_tester.c +++ b/liblwgeom/cunit/cu_tester.c @@ -34,6 +34,7 @@ extern CU_SuiteInfo split_suite; extern CU_SuiteInfo geodetic_suite; extern CU_SuiteInfo geos_suite; extern CU_SuiteInfo tree_suite; +extern CU_SuiteInfo triangulate_suite; extern CU_SuiteInfo homogenize_suite; extern CU_SuiteInfo stringbuffer_suite; extern CU_SuiteInfo surface_suite; @@ -70,6 +71,7 @@ int main(int argc, char *argv[]) geodetic_suite, geos_suite, tree_suite, + triangulate_suite, stringbuffer_suite, surface_suite, homogenize_suite, diff --git a/liblwgeom/cunit/cu_triangulate.c b/liblwgeom/cunit/cu_triangulate.c new file mode 100644 index 000000000..2ee337272 --- /dev/null +++ b/liblwgeom/cunit/cu_triangulate.c @@ -0,0 +1,58 @@ +/********************************************************************** + * + * PostGIS - Spatial Types for PostgreSQL + * http://postgis.refractions.net + * + * Copyright (C) 2012 Sandro Santilli + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU General Public Licence. See the COPYING file. + * + **********************************************************************/ + +#include "CUnit/Basic.h" +#include "cu_tester.h" + +#include "liblwgeom.h" +#include "liblwgeom_internal.h" + +static void test_lwgeom_delaunay_triangulation(void) +{ +#if POSTGIS_GEOS_VERSION >= 34 + LWGEOM *in, *tmp, *out; + char *wkt, *exp_wkt; + + /* Because i don't trust that much prior tests... ;) */ + cu_error_msg_reset(); + + in = lwgeom_from_wkt("MULTIPOINT(10 0, 20 0, 5 5)", LW_PARSER_CHECK_NONE); + + tmp = lwgeom_delaunay_triangulation(in, 0, 0); + lwgeom_free(in); + out = lwgeom_normalize(tmp); + lwgeom_free(tmp); + + wkt = lwgeom_to_ewkt(out); + lwgeom_free(out); + + exp_wkt = "GEOMETRYCOLLECTION(POLYGON((5 5,20 0,10 0,5 5)))"; + if ( strcmp(wkt, exp_wkt) ) + { + fprintf(stderr, "\nExp: %s\nObt: %s\n", exp_wkt, wkt); + } + CU_ASSERT_STRING_EQUAL(wkt, exp_wkt); + lwfree(wkt); + +#endif /* POSTGIS_GEOS_VERSION >= 33 */ +} + + +/* +** Used by test harness to register the tests in this file. +*/ +CU_TestInfo triangulate_tests[] = +{ + PG_TEST(test_lwgeom_delaunay_triangulation), + CU_TEST_INFO_NULL +}; +CU_SuiteInfo triangulate_suite = {"triangulate", NULL, NULL, triangulate_tests}; diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in index 325d40f04..afb151a92 100644 --- a/liblwgeom/liblwgeom.h.in +++ b/liblwgeom/liblwgeom.h.in @@ -1915,5 +1915,16 @@ LWGEOM* lwgeom_split(const LWGEOM* lwgeom_in, const LWGEOM* blade_in); */ LWGEOM* lwgeom_node(const LWGEOM* lwgeom_in); +/** + * Take vertices of a geometry and build a delaunay + * triangulation on them. + * + * @param geom the input geometry + * @param tolerance an optional snapping tolerance for improved tolerance + * @param edgeOnly if non-zero the result will be a MULTILINESTRING, + * otherwise it'll be a COLLECTION of polygons. + */ +LWGEOM* lwgeom_delaunay_triangulation(const LWGEOM *geom, double tolerance, int edgeOnly); + #endif /* !defined _LIBLWGEOM_H */ diff --git a/liblwgeom/lwgeom_geos.c b/liblwgeom/lwgeom_geos.c index 74fe45e36..9e0c64e2e 100644 --- a/liblwgeom/lwgeom_geos.c +++ b/liblwgeom/lwgeom_geos.c @@ -3,7 +3,7 @@ * PostGIS - Spatial Types for PostgreSQL * http://postgis.refractions.net * - * Copyright 2011 Sandro Santilli + * Copyright 2011-2012 Sandro Santilli * * This is free software; you can redistribute and/or modify it under * the terms of the GNU General Public Licence. See the COPYING file. @@ -1299,3 +1299,49 @@ lwgeom_offsetcurve(const LWLINE *lwline, double size, int quadsegs, int joinStyl #endif /* POSTGIS_GEOS_VERSION < 32 */ } + +LWGEOM* +lwgeom_delaunay_triangulation(const LWGEOM *lwgeom_in, double tolerance, int edgeOnly) +{ +#if POSTGIS_GEOS_VERSION < 34 + lwerror("lwgeom_delaunay_triangulation: GEOS 3.4 or higher required"); +#else + GEOSGeometry *g1, *g3; + LWGEOM *lwgeom_result; + + initGEOS(lwnotice, lwgeom_geos_error); + + g1 = (GEOSGeometry *)LWGEOM2GEOS(lwgeom_in); + if ( ! g1 ) + { + lwerror("lwgeom_delaunay_triangulation: Geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); + return NULL; + } + + g3 = GEOSDelaunayTriangulation(g1, tolerance, edgeOnly); + + /* Don't need input geometry anymore */ + GEOSGeom_destroy(g1); + + if (g3 == NULL) + { + lwerror("GEOSDelaunayTriangulation: %s", lwgeom_geos_errmsg); + return NULL; + } + + /* LWDEBUGF(3, "result: %s", GEOSGeomToWKT(g3)); */ + + GEOSSetSRID(g3, lwgeom_get_srid(lwgeom_in)); + lwgeom_result = GEOS2LWGEOM(g3, lwgeom_has_z(lwgeom_in)); + GEOSGeom_destroy(g3); + + if (lwgeom_result == NULL) + { + lwerror("lwgeom_delaunay_triangulation: GEOS2LWGEOM returned null"); + return NULL; + } + + return lwgeom_result; + +#endif /* POSTGIS_GEOS_VERSION < 34 */ +}