<pre>Hello!<br><br>Add GEOS simplify functions to PostGIS <br>(testing only with PostGIS 1.1.6 and geos-3.0.0rc2)<br><br>With them, you can use big tolerance without get null result value...
<br>SQL : simplify_geos(geometry,float8) = GEOS DouglasPeuckerSimplifier::simplify(g1, tolerance)<br>SQL : simplifytopologypreserve_geos(geometry,float8) = GEOS TopologyPreservingSimplifier::simplify(g1, tolerance)<br><br>
Thanks a lots for PostGIS!!!<br><br>François<br><br>diff -r -c /postgis-1.1.6/lwgeom/lwgeom_geos.c /new/postgis-1.1.6/lwgeom/lwgeom_geos.c<br>*** /postgis-1.1.6/lwgeom/lwgeom_geos.c        Mon Dec 12 09:40:50 2005<br>--- /new/postgis-
1.1.6/lwgeom/lwgeom_geos.c        Fri Nov 17 08:30:15 2006<br>***************<br>*** 66,71 ****<br>--- 66,75 ----<br>  Datum linemerge(PG_FUNCTION_ARGS);<br>  Datum LWGEOM_buildarea(PG_FUNCTION_ARGS);<br>  <br>+<br>+ Datum simplify_geos(PG_FUNCTION_ARGS);
<br>+ Datum simplifytopologypreserve_geos(PG_FUNCTION_ARGS);<br>+<br>  <br>  typedef  struct Geometry Geometry;<br>  <br>***************<br>*** 101,106 ****<br>--- 105,115 ----<br>  extern Geometry *GEOSGetCentroid(Geometry *g, int *failure);
<br>  extern bool GEOSHasZ(Geometry *g1);<br>  <br>+<br>+ extern Geometry *GEOSSimplify(Geometry *g1, double tolerance);<br>+ extern Geometry *GEOSTopologyPreserveSimplify(Geometry *g1, double tolerance);<br>+<br>+ <br>  extern void GEOSSetSRID(Geometry *g, int SRID);
<br>  extern void GEOSdeleteChar(char *a);<br>  extern void GEOSdeleteGeometry(Geometry *a);<br>***************<br>*** 2896,2898 ****<br>--- 2905,3089 ----<br>          PG_RETURN_NULL();<br>  }<br>  <br>+<br>+ PG_FUNCTION_INFO_V1(simplify_geos);
<br>+ Datum simplify_geos(PG_FUNCTION_ARGS)<br>+ {<br>+         PG_LWGEOM *geom1;<br>+         double tolerance;<br>+         GEOSGeom g1,g2;<br>+         PG_LWGEOM *result;<br>+         int is3d;<br>+         int SRID;<br>+    <br>+ #ifdef PROFILE<br>+         profstart(PROF_QRUN);
<br>+ #endif<br>+ <br>+         geom1 = (PG_LWGEOM *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));<br>+         tolerance = PG_GETARG_FLOAT8(1);<br>+ <br>+         is3d = ( TYPE_HASZ(geom1-&gt;type) );<br>+     SRID = pglwgeom_getSRID(geom1);<br>+         initGEOS(lwnotice, lwnotice);
<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot;simplify starting&quot;);<br>+ #endif<br>+ <br>+ #ifdef PROFILE<br>+         profstart(PROF_P2G1);<br>+ #endif<br>+         g1 = POSTGIS2GEOS(geom1);<br>+ #ifdef PROFILE<br>+         profstop(PROF_P2G1);
<br>+ #endif<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot; constructed geometry - calling geos&quot;);<br>+         elog(NOTICE,&quot; g1 = %s&quot;, GEOSGeomToWKT(g1));<br>+ /*elog(NOTICE,&quot;g1 is valid = %i&quot;,GEOSisvalid(g1)); */
<br>+ #endif<br>+ <br>+ #ifdef PROFILE<br>+         profstart(PROF_GRUN);<br>+ #endif <br>+         g2 = GEOSSimplify(g1,tolerance);<br>+ #ifdef PROFILE<br>+         profstop(PROF_GRUN);<br>+ #endif<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot;simplify finished&quot;);
<br>+ #endif<br>+ <br>+         if (g2 == NULL)<br>+         {<br>+                 elog(ERROR,&quot;GEOS Simplify() threw an error!&quot;);<br>+                 GEOSGeom_destroy(g1);<br>+                 PG_RETURN_NULL(); /* never get here */<br>+         }<br>+ #ifdef PGIS_DEBUG<br>
+         elog(NOTICE,&quot;result: %s&quot;, GEOSGeomToWKT(g2) ) ;<br>+ #endif<br>+         GEOSSetSRID(g2, SRID);<br>+ #ifdef PROFILE<br>+         profstart(PROF_G2P);<br>+ #endif<br>+         result = GEOS2POSTGIS(g2, is3d);<br>+ #ifdef PROFILE<br>
+         profstop(PROF_G2P);<br>+ #endif<br>+ <br>+         if (result == NULL)<br>+         {<br>+                 GEOSGeom_destroy(g1);<br>+                 GEOSGeom_destroy(g2);<br>+                 elog(ERROR,&quot;GEOS Simplify() threw an error (result postgis geometry formation)!&quot;);
<br>+                 PG_RETURN_NULL(); /* never get here */<br>+         }<br>+         GEOSGeom_destroy(g1);<br>+         GEOSGeom_destroy(g2);<br>+ <br>+         /* compressType(result); */<br>+ <br>+ #ifdef PROFILE<br>+         profstop(PROF_QRUN);<br>+         profreport(&quot;geos&quot;,geom1, result);
<br>+ #endif<br>+         PG_FREE_IF_COPY(geom1, 0);<br>+ <br>+         PG_RETURN_POINTER(result);<br>+ }<br>+ <br>+ PG_FUNCTION_INFO_V1(simplifytopologypreserve_geos);<br>+ Datum simplifytopologypreserve_geos(PG_FUNCTION_ARGS)<br>+ {<br>
+         PG_LWGEOM *geom1;<br>+         double tolerance;<br>+         GEOSGeom g1,g2;<br>+         PG_LWGEOM *result;<br>+         int is3d;<br>+         int SRID;<br>+    <br>+ #ifdef PROFILE<br>+         profstart(PROF_QRUN);<br>+ #endif<br>+ <br>+         geom1 = (PG_LWGEOM *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
<br>+         tolerance = PG_GETARG_FLOAT8(1);<br>+ <br>+         is3d = ( TYPE_HASZ(geom1-&gt;type) );<br>+     SRID = pglwgeom_getSRID(geom1);<br>+         initGEOS(lwnotice, lwnotice);<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot;simplify starting&quot;);
<br>+ #endif<br>+ <br>+ #ifdef PROFILE<br>+         profstart(PROF_P2G1);<br>+ #endif<br>+         g1 = POSTGIS2GEOS(geom1);<br>+ #ifdef PROFILE<br>+         profstop(PROF_P2G1);<br>+ #endif<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot; constructed geometry - calling geos&quot;);
<br>+         elog(NOTICE,&quot; g1 = %s&quot;, GEOSGeomToWKT(g1));<br>+ /*elog(NOTICE,&quot;g1 is valid = %i&quot;,GEOSisvalid(g1)); */<br>+ #endif<br>+ <br>+ #ifdef PROFILE<br>+         profstart(PROF_GRUN);<br>+ #endif <br>+         g2 = GEOSTopologyPreserveSimplify(g1,tolerance);
<br>+ #ifdef PROFILE<br>+         profstop(PROF_GRUN);<br>+ #endif<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot;simplify finished&quot;);<br>+ #endif<br>+ <br>+         if (g2 == NULL)<br>+         {<br>+                 elog(ERROR,&quot;GEOS TopologyPreserveSimplify() threw an error!&quot;);
<br>+                 GEOSGeom_destroy(g1);<br>+                 PG_RETURN_NULL(); /* never get here */<br>+         }<br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot;result: %s&quot;, GEOSGeomToWKT(g2) ) ;<br>+ #endif<br>+         GEOSSetSRID(g2, SRID);<br>+ #ifdef PROFILE
<br>+         profstart(PROF_G2P);<br>+ #endif<br>+         result = GEOS2POSTGIS(g2, is3d);<br>+ #ifdef PROFILE<br>+         profstop(PROF_G2P);<br>+ #endif<br>+ <br>+         if (result == NULL)<br>+         {<br>+                 GEOSGeom_destroy(g1);<br>+                 GEOSGeom_destroy(g2);
<br>+                 elog(ERROR,&quot;GEOS TopologyPreserveSimplify() threw an error (result postgis geometry formation)!&quot;);<br>+                 PG_RETURN_NULL(); /* never get here */<br>+         }<br>+         GEOSGeom_destroy(g1);<br>+         GEOSGeom_destroy(g2);
<br>+ <br>+         /* compressType(result); */<br>+ <br>+ #ifdef PROFILE<br>+         profstop(PROF_QRUN);<br>+         profreport(&quot;geos&quot;,geom1, result);<br>+ #endif<br>+         PG_FREE_IF_COPY(geom1, 0);<br>+ <br>+         PG_RETURN_POINTER(result);
<br>+ }<br>+<br>+ <br>diff -r -c /postgis-1.1.6/lwgeom/lwgeom_geos_c.c /new/postgis-1.1.6/lwgeom/lwgeom_geos_c.c<br>*** /postgis-1.1.6/lwgeom/lwgeom_geos_c.c        Wed Oct 25 03:23:00 2006<br>--- /new/postgis-1.1.6/lwgeom/lwgeom_geos_c.c        Fri Nov 17 08:15:59 2006
<br>***************<br>*** 67,72 ****<br>--- 67,76 ----<br>  Datum LWGEOM_buildarea(PG_FUNCTION_ARGS);<br>  Datum linemerge(PG_FUNCTION_ARGS);<br>  <br>+<br>+ Datum simplify_geos(PG_FUNCTION_ARGS);<br>+ Datum simplifytopologypreserve_geos(PG_FUNCTION_ARGS);
<br>+<br>  <br>  LWGEOM *GEOS2LWGEOM(GEOSGeom geom, char want3d);<br>  PG_LWGEOM *GEOS2POSTGIS(GEOSGeom geom, char want3d);<br>***************<br>*** 2974,2976 ****<br>--- 2978,3162 ----<br>          PG_RETURN_POINTER(result);<br>
  <br>  }<br>+ <br>+<br>+ PG_FUNCTION_INFO_V1(simplify_geos);<br>+ Datum simplify_geos(PG_FUNCTION_ARGS)<br>+ {<br>+         PG_LWGEOM *geom1;<br>+         double tolerance;<br>+         GEOSGeom g1,g2;<br>+         PG_LWGEOM *result;<br>+         int is3d;
<br>+         int SRID;<br>+    <br>+ #ifdef PROFILE<br>+         profstart(PROF_QRUN);<br>+ #endif<br>+ <br>+         geom1 = (PG_LWGEOM *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));<br>+         tolerance = PG_GETARG_FLOAT8(1);<br>+ <br>+         is3d = ( TYPE_HASZ(geom1-&gt;type) );
<br>+     SRID = pglwgeom_getSRID(geom1);<br>+         initGEOS(lwnotice, lwnotice);<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot;simplify starting&quot;);<br>+ #endif<br>+ <br>+ #ifdef PROFILE<br>+         profstart(PROF_P2G1);
<br>+ #endif<br>+         g1 = POSTGIS2GEOS(geom1);<br>+ #ifdef PROFILE<br>+         profstop(PROF_P2G1);<br>+ #endif<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot; constructed geometry - calling geos&quot;);<br>+         elog(NOTICE,&quot; g1 = %s&quot;, GEOSGeomToWKT(g1));
<br>+ /*elog(NOTICE,&quot;g1 is valid = %i&quot;,GEOSisvalid(g1)); */<br>+ #endif<br>+ <br>+ #ifdef PROFILE<br>+         profstart(PROF_GRUN);<br>+ #endif <br>+         g2 = GEOSSimplify(g1,tolerance);<br>+ #ifdef PROFILE<br>+         profstop(PROF_GRUN);
<br>+ #endif<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot;simplify finished&quot;);<br>+ #endif<br>+ <br>+         if (g2 == NULL)<br>+         {<br>+                 elog(ERROR,&quot;GEOS Simplify() threw an error!&quot;);<br>+                 GEOSGeom_destroy(g1);
<br>+                 PG_RETURN_NULL(); /* never get here */<br>+         }<br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot;result: %s&quot;, GEOSGeomToWKT(g2) ) ;<br>+ #endif<br>+         GEOSSetSRID(g2, SRID);<br>+ #ifdef PROFILE<br>+         profstart(PROF_G2P);
<br>+ #endif<br>+         result = GEOS2POSTGIS(g2, is3d);<br>+ #ifdef PROFILE<br>+         profstop(PROF_G2P);<br>+ #endif<br>+ <br>+         if (result == NULL)<br>+         {<br>+                 GEOSGeom_destroy(g1);<br>+                 GEOSGeom_destroy(g2);<br>+                 elog(ERROR,&quot;GEOS Simplify() threw an error (result postgis geometry formation)!&quot;);
<br>+                 PG_RETURN_NULL(); /* never get here */<br>+         }<br>+         GEOSGeom_destroy(g1);<br>+         GEOSGeom_destroy(g2);<br>+ <br>+         /* compressType(result); */<br>+ <br>+ #ifdef PROFILE<br>+         profstop(PROF_QRUN);<br>+         profreport(&quot;geos&quot;,geom1, result);
<br>+ #endif<br>+         PG_FREE_IF_COPY(geom1, 0);<br>+ <br>+         PG_RETURN_POINTER(result);<br>+ }<br>+ <br>+ PG_FUNCTION_INFO_V1(simplifytopologypreserve_geos);<br>+ Datum simplifytopologypreserve_geos(PG_FUNCTION_ARGS)<br>+ {<br>
+         PG_LWGEOM *geom1;<br>+         double tolerance;<br>+         GEOSGeom g1,g2;<br>+         PG_LWGEOM *result;<br>+         int is3d;<br>+         int SRID;<br>+    <br>+ #ifdef PROFILE<br>+         profstart(PROF_QRUN);<br>+ #endif<br>+ <br>+         geom1 = (PG_LWGEOM *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
<br>+         tolerance = PG_GETARG_FLOAT8(1);<br>+ <br>+         is3d = ( TYPE_HASZ(geom1-&gt;type) );<br>+     SRID = pglwgeom_getSRID(geom1);<br>+         initGEOS(lwnotice, lwnotice);<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot;simplify starting&quot;);
<br>+ #endif<br>+ <br>+ #ifdef PROFILE<br>+         profstart(PROF_P2G1);<br>+ #endif<br>+         g1 = POSTGIS2GEOS(geom1);<br>+ #ifdef PROFILE<br>+         profstop(PROF_P2G1);<br>+ #endif<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot; constructed geometry - calling geos&quot;);
<br>+         elog(NOTICE,&quot; g1 = %s&quot;, GEOSGeomToWKT(g1));<br>+ /*elog(NOTICE,&quot;g1 is valid = %i&quot;,GEOSisvalid(g1)); */<br>+ #endif<br>+ <br>+ #ifdef PROFILE<br>+         profstart(PROF_GRUN);<br>+ #endif <br>+         g2 = GEOSTopologyPreserveSimplify(g1,tolerance);
<br>+ #ifdef PROFILE<br>+         profstop(PROF_GRUN);<br>+ #endif<br>+ <br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot;simplify finished&quot;);<br>+ #endif<br>+ <br>+         if (g2 == NULL)<br>+         {<br>+                 elog(ERROR,&quot;GEOS TopologyPreserveSimplify() threw an error!&quot;);
<br>+                 GEOSGeom_destroy(g1);<br>+                 PG_RETURN_NULL(); /* never get here */<br>+         }<br>+ #ifdef PGIS_DEBUG<br>+         elog(NOTICE,&quot;result: %s&quot;, GEOSGeomToWKT(g2) ) ;<br>+ #endif<br>+         GEOSSetSRID(g2, SRID);<br>+ #ifdef PROFILE
<br>+         profstart(PROF_G2P);<br>+ #endif<br>+         result = GEOS2POSTGIS(g2, is3d);<br>+ #ifdef PROFILE<br>+         profstop(PROF_G2P);<br>+ #endif<br>+ <br>+         if (result == NULL)<br>+         {<br>+                 GEOSGeom_destroy(g1);<br>+                 GEOSGeom_destroy(g2);
<br>+                 elog(ERROR,&quot;GEOS TopologyPreserveSimplify() threw an error (result postgis geometry formation)!&quot;);<br>+                 PG_RETURN_NULL(); /* never get here */<br>+         }<br>+         GEOSGeom_destroy(g1);<br>+         GEOSGeom_destroy(g2);
<br>+ <br>+         /* compressType(result); */<br>+ <br>+ #ifdef PROFILE<br>+         profstop(PROF_QRUN);<br>+         profreport(&quot;geos&quot;,geom1, result);<br>+ #endif<br>+         PG_FREE_IF_COPY(geom1, 0);<br>+ <br>+         PG_RETURN_POINTER(result);
<br>+ }<br>+<br>diff -r -c /postgis-1.1.6/lwgeom/lwgeom_geos_wrapper.cpp /new/postgis-1.1.6/lwgeom/lwgeom_geos_wrapper.cpp<br>*** /postgis-1.1.6/lwgeom/lwgeom_geos_wrapper.cpp        Fri Dec 16 00:56:15 2005<br>--- /new/postgis-
1.1.6/lwgeom/lwgeom_geos_wrapper.cpp        Fri Nov 17 07:54:29 2006<br>***************<br>*** 10,15 ****<br>--- 10,21 ----<br>  #include &quot;postgis_geos_version.h&quot;<br>  #include &quot;geos/geom.h&quot;<br>  #include &quot;geos/util.h&quot;
<br>+ <br>+<br>+ //#include &lt;geos/simplify/DouglasPeuckerSimplifier.h&gt;<br>+ //#include &lt;geos/simplify/TopologyPreservingSimplifier.h&gt;<br>+<br>+ <br>  #if GEOS_FIRST_INTERFACE &lt;= 3 &amp;&amp; GEOS_LAST_INTERFACE &gt;= 3
<br>  #include &quot;geos/opValid.h&quot;<br>  #include &quot;geos/opPolygonize.h&quot;<br>***************<br>*** 140,145 ****<br>--- 146,155 ----<br>  extern &quot;C&quot; Geometry *GEOSSymDifference(Geometry *g1,Geometry *g2);
<br>  extern &quot;C&quot; Geometry *GEOSUnion(Geometry *g1,Geometry *g2);<br>  <br>+<br>+ extern &quot;C&quot; Geometry *GEOSSimplify(Geometry *g1, double tolerance);<br>+ extern &quot;C&quot; Geometry *GEOSTopologyPreserveSimplify(Geometry *g1, double tolerance);
<br>+<br>  <br>  extern &quot;C&quot; POINT3D  *GEOSGetCoordinate(Geometry *g1);<br>  extern &quot;C&quot; POINT3D  *GEOSGetCoordinates_Polygon(Polygon *g1);<br>***************<br>*** 1857,1859 ****<br>--- 1867,1917 ----<br>
                  return NULL;<br>          }<br>  }<br>+ <br>+<br>+ Geometry *<br>+ GEOSSimplify(const Geometry *g1, double tolerance)<br>+ {<br>+         using namespace geos::simplify;<br>+ <br>+         try<br>+         {<br>+                 Geometry::AutoPtr g(DouglasPeuckerSimplifier::simplify(g1, tolerance));
<br>+                 return g.release();<br>+         }<br>+         catch (const std::exception &amp;e)<br>+         {<br>+                 ERROR_MESSAGE(&quot;%s&quot;, e.what());<br>+                 return NULL;<br>+         }<br>+ <br>+         catch (...)<br>+         {<br>+                 ERROR_MESSAGE(&quot;Unknown exception thrown&quot;);
<br>+                 return NULL;<br>+         }<br>+ }<br>+ <br>+ Geometry *<br>+ GEOSTopologyPreserveSimplify(const Geometry *g1, double tolerance)<br>+ {<br>+         using namespace geos::simplify;<br>+ <br>+         try<br>+         {<br>+                 Geometry::AutoPtr g(TopologyPreservingSimplifier::simplify(g1, tolerance));
<br>+                 return g.release();<br>+         }<br>+         catch (const std::exception &amp;e)<br>+         {<br>+                 ERROR_MESSAGE(&quot;%s&quot;, e.what());<br>+                 return NULL;<br>+         }<br>+ <br>+         catch (...)<br>+         {<br>+                 ERROR_MESSAGE(&quot;Unknown exception thrown&quot;);
<br>+                 return NULL;<br>+         }<br>+ }<br>+<br>diff -r -c /postgis-1.1.6/lwgeom/lwpostgis.sql.in /new/postgis-1.1.6/lwgeom/lwpostgis.sql.in<br>*** /postgis-1.1.6/lwgeom/lwpostgis.sql.in        Fri Jul  7 06:56:52 2006<br>--- /new/postgis-
1.1.6/lwgeom/lwpostgis.sql.in        Fri Nov 17 08:55:30 2006<br>***************<br>*** 2876,2881 ****<br>--- 2876,2893 ----<br>  -- GEOS<br>  ---------------------------------------------------------------<br>  <br>+<br>+ CREATEFUNCTION simplify_geos(geometry,float8)
<br>+    RETURNS geometry<br>+    AS '@MODULE_FILENAME@','simplify_geos'<br>+    LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable)<br>+ <br>+ CREATEFUNCTION simplifytopologypreserve_geos(geometry,float8)<br>+    RETURNS geometry
<br>+    AS '@MODULE_FILENAME@','simplifytopologypreserve_geos'<br>+    LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable)<br>+<br>+ <br>  CREATEFUNCTION intersection(geometry,geometry)<br>     RETURNS geometry
<br>     AS '@MODULE_FILENAME@','intersection'<br><br><br><br><br></pre>