]> granicus.if.org Git - postgis/commitdiff
Add ST_ApproximateMedialAxis (#3169)
authorSandro Santilli <strk@keybit.net>
Wed, 17 Jun 2015 13:10:33 +0000 (13:10 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 17 Jun 2015 13:10:33 +0000 (13:10 +0000)
Requires SFCGAL (any version).
Uses SFCGAL specific API if available (1.2+),
post-processes StraightSkeleton output otherwise.

Includes regression test and documentation.

git-svn-id: http://svn.osgeo.org/postgis/trunk@13678 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
doc/html/image_src/Makefile.in
doc/html/image_src/st_approximatemedialaxis01.wkt [new file with mode: 0644]
doc/reference_sfcgal.xml
postgis/lwgeom_sfcgal.c
postgis/sfcgal.sql.in
regress/Makefile.in
regress/sfcgal/approximatemedialaxis.sql [new file with mode: 0644]
regress/sfcgal/approximatemedialaxis_expected [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 66c093205294072b79be4e828e91700ae47fa784..bef3afd3524f5c8e653cc5e74e4a9cf8635966aa 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -30,6 +30,7 @@ PostGIS 2.2.0
 
  * New Features *
 
+  - #3169, ST_ApproximateMedialAxis (Sandro Santilli)
   - Add |=| operator with CPA semantic and KNN support with PgSQL 9.5+
     (Sandro Santilli / Boundless)
   - #3131, KNN support for the geography type (Paul Ramsey / CartoDB)
@@ -53,7 +54,7 @@ PostGIS 2.2.0
   - #899, -m shp2pgsql attribute names mapping -m switch
            (Regina Obe / Sandro Santilli)
   - #1678, Added GUC postgis.gdal_datapath to specify GDAL config
-    variable GDAL_DATA
+           variable GDAL_DATA
   - #2843, Support reprojection on raster import
            (Sandro Santilli / Vizzuality)
   - #2349, Support for encoded_polyline input/output (Kashif Rasul)
@@ -65,8 +66,8 @@ PostGIS 2.2.0
     variable GDAL_SKIP
   - Added GUC postgis.enable_outdb_rasters to enable access to
     rasters with out-db bands
-  - #2387 address_standardizer extension as part of PostGIS
-     Stephen Woodbridge (imaptools.com), Walter Sinclair
+  - #2387, address_standardizer extension as part of PostGIS
+           Stephen Woodbridge (imaptools.com), Walter Sinclair
   - #2341, New mask parameter for ST_MapAlgebra
   - #2397, read encoding info automatically in shapefile loader
   - #2430, ST_ForceCurve
@@ -74,11 +75,11 @@ PostGIS 2.2.0
   - #2567, ST_CountAgg()
   - #2632, ST_AsGML() support for curved features
   - #2652, Add --upgrade-path switch to run_test.pl
-  - #2754 sfcgal wrapped as an extension
+  - #2754, sfcgal wrapped as an extension
   - #2227, Simplification with Visvalingam-Whyatt algorithm
            ST_SimplifyVW, ST_SetEffectiveArea (Nicklas Avén)
   - Functions to encode and decode TWKB
-           ST_AsTWKB, ST_GeomFromTWKB (Paul Ramsey / Nicklas Avén / CartoDB)
+    ST_AsTWKB, ST_GeomFromTWKB (Paul Ramsey / Nicklas Avén / CartoDB)
 
  * Enhancements *
 
index 41974ded32382720a0f80fa0b3d693e8cbd19b7b..ce0ae378d094e54deb9f0c218da6c9e4c96d16e8 100644 (file)
@@ -112,6 +112,7 @@ IMAGES= \
        ../images/st_split03.png \
        ../images/st_split04.png \
        ../images/st_straightskeleton01.png \
+       ../images/st_approximatemedialaxis01.png \
        ../images/st_subdivide01.png \
        ../images/st_subdivide02.png \
        ../images/st_symdifference01.png \
diff --git a/doc/html/image_src/st_approximatemedialaxis01.wkt b/doc/html/image_src/st_approximatemedialaxis01.wkt
new file mode 100644 (file)
index 0000000..b40222e
--- /dev/null
@@ -0,0 +1,2 @@
+Style1;POLYGON (( 190 190, 10 190, 10 10, 190 10, 190 20, 160 30, 60 30, 60 130, 190 140, 190 190 ))\r
+Style2;MULTILINESTRING((184.188611699158 15.8113883008419,158.377223398316 20),(50 20,158.377223398316 20),(50 20,35 35),(35 153.150778481549,35 35),(35 153.150778481549,40.6970772062924 159.302922793708),(164.039879739868 164.039879739868,40.6970772062924 159.302922793708))\r
index 2769903d59b2b8cfd7becde8f935ba25ca97be03..830d88027a1a0ca4d20e88e9fe182faf14f1cb81 100644 (file)
 
        </refentry>
 
+       <refentry id="ST_ApproximateMedialAxis">
+         <refnamediv>
+               <refname>ST_ApproximateMedialAxis</refname>
+
+               <refpurpose>Compute the approximate medial axis of an areal geometry.</refpurpose>
+         </refnamediv>
+
+         <refsynopsisdiv>
+               <funcsynopsis>
+                 <funcprototype>
+                       <funcdef>geometry <function>ST_ApproximateMedialAxis</function></funcdef>
+                       <paramdef><type>geometry</type> <parameter>geom</parameter></paramdef>
+                 </funcprototype>
+               </funcsynopsis>
+         </refsynopsisdiv>
+
+         <refsection>
+               <title>Description</title>
+
+    <para>
+Return an approximate medial axis for the areal input based on
+its straight skeleton. Uses an SFCGAL specific API when built against
+a capable version (1.2.0+). Otherwise the function is just a wrapper
+around ST_StraightSkeleton (slower case).
+    </para>
+
+               <para>Availability: 2.2.0</para>
+               <para>&sfcgal_required;</para>
+               <para>&Z_support;</para>
+               <para>&P_support;</para>
+               <para>&T_support;</para>
+         </refsection>
+         
+         <refsection><title>Examples</title>
+                       <programlisting>SELECT ST_ApproximateMedialAxis(ST_GeomFromText('POLYGON (( 190 190, 10 190, 10 10, 190 10, 190 20, 160 30, 60 30, 60 130, 190 140, 190 190 ))'));</programlisting>
+                       
+                <informaltable>
+                                 <tgroup cols="1">
+                                       <tbody>
+                                         <row>
+                                               <entry><para><informalfigure>
+                                                       <mediaobject>
+                                                         <imageobject>
+                                                               <imagedata fileref="images/st_approximatemedialaxis01.png" />
+                                                         </imageobject>
+                                                         <caption><para>A polygon and its approximate medial axis</para></caption>
+                                                       </mediaobject>
+                                                 </informalfigure></para>
+                                         </entry>
+                               </row>
+                               </tbody>
+                               </tgroup>
+                       </informaltable>
+         </refsection>
+
+         <refsection>
+                               <title>See Also</title>
+
+                               <para><xref linkend="ST_StraightSkeleton" /></para>
+               </refsection>
+
+       </refentry>
+
 
        <refentry id="ST_IsPlanar">
          <refnamediv>
index fe91ccb854f2df1f8aedf4d237efa12d1825bfaa..18243da2a3d9e21a335cdeca8191aec6a48fb4d0 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "lwgeom_pg.h"
 #include "lwgeom_sfcgal.h"
+#include "../postgis_config.h"
 
 
 Datum postgis_sfcgal_version(PG_FUNCTION_ARGS);
@@ -33,6 +34,7 @@ Datum sfcgal_intersection(PG_FUNCTION_ARGS);
 Datum sfcgal_intersection3D(PG_FUNCTION_ARGS);
 Datum sfcgal_extrude(PG_FUNCTION_ARGS);
 Datum sfcgal_straight_skeleton(PG_FUNCTION_ARGS);
+Datum sfcgal_approximate_medial_axis(PG_FUNCTION_ARGS);
 Datum sfcgal_is_planar(PG_FUNCTION_ARGS);
 Datum sfcgal_orientation(PG_FUNCTION_ARGS);
 Datum sfcgal_force_lhr(PG_FUNCTION_ARGS);
@@ -414,6 +416,38 @@ Datum sfcgal_straight_skeleton(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(output);
 }
 
+PG_FUNCTION_INFO_V1(sfcgal_approximate_medial_axis);
+Datum sfcgal_approximate_medial_axis(PG_FUNCTION_ARGS)
+{
+#if POSTGIS_SFCGAL_VERSION < 12
+       lwpgerror("The SFCGAL version this PostGIS binary "
+               "was compiled against (%d) doesn't support "
+               "'sfcgal_geometry_approximate_medial_axis' function (1.2.0+ required)",
+               POSTGIS_SFCGAL_VERSION);
+       PG_RETURN_NULL();
+#else /* POSTGIS_SFCGAL_VERSION >= 12 */
+       GSERIALIZED *input, *output;
+       sfcgal_geometry_t *geom;
+       sfcgal_geometry_t *result;
+       srid_t srid;
+
+       sfcgal_postgis_init();
+
+       input = PG_GETARG_GSERIALIZED_P(0);
+       srid = gserialized_get_srid(input);
+       geom = POSTGIS2SFCGALGeometry(input);
+       PG_FREE_IF_COPY(input, 0);
+
+       result = sfcgal_geometry_approximate_medial_axis(geom);
+       sfcgal_geometry_delete(geom);
+
+       output = SFCGALGeometry2POSTGIS(result, 0, srid);
+       sfcgal_geometry_delete(result);
+
+       PG_RETURN_POINTER(output);
+#endif /* POSTGIS_SFCGAL_VERSION >= 12 */
+}
+
 
 PG_FUNCTION_INFO_V1(sfcgal_intersection);      
 Datum sfcgal_intersection(PG_FUNCTION_ARGS)
index 7144f4dc5c3b1c168097d38d7ef8951746496996..a2341981cca8b3e48fe8171aecaed98ce05a8ccb 100644 (file)
@@ -79,6 +79,36 @@ CREATE OR REPLACE FUNCTION ST_StraightSkeleton(geometry)
        LANGUAGE 'c' IMMUTABLE STRICT
        COST 100;
 
+-- Availability: 2.2.0
+CREATE OR REPLACE FUNCTION ST_ApproximateMedialAxis(geometry)
+       RETURNS geometry
+#if POSTGIS_SFCGAL_VERSION < 12
+       AS $$
+       DECLARE
+         poly alias for $1;
+         ret GEOMETRY;
+       BEGIN
+         WITH components AS (
+           SELECT (ST_Dump(ST_StraightSkeleton(poly))).geom
+         ),
+         filtered AS (
+           SELECT ST_Collect(geom) g
+           FROM components
+           WHERE NOT ST_Touches(geom, ST_Boundary(poly))
+         )
+         SELECT
+          COALESCE(g, ST_SetSRID('MULTILINESTRING EMPTY', ST_Srid(poly))) 
+         INTO ret
+         FROM filtered;
+         RETURN ret;
+       END; $$
+       LANGUAGE 'plpgsql'
+#else // POSTGIS_SFCGAL_VERSION >= 12
+       AS 'MODULE_PATHNAME','sfcgal_approximate_medial_axis'
+       LANGUAGE 'c'
+#endif // POSTGIS_SFCGAL_VERSION >= 12
+       IMMUTABLE STRICT COST 100;
+
 -- Availability: 2.2.0       
 CREATE OR REPLACE FUNCTION ST_IsPlanar(geometry)
        RETURNS boolean
index 56769292ac3776487c18a184341bea3ebded41b3..54447745e9d4e21fa51bccdb8811f727f1b8ec79 100644 (file)
@@ -216,7 +216,8 @@ ifeq ($(HAVE_SFCGAL),yes)
                sfcgal/regress.sql \
                sfcgal/tickets.sql \
                sfcgal/concave_hull.sql \
-               sfcgal/wmsservers.sql
+               sfcgal/wmsservers.sql \
+               sfcgal/approximatemedialaxis.sql
 
        SFCGALTESTFLAGS = --sfcgal
 endif
diff --git a/regress/sfcgal/approximatemedialaxis.sql b/regress/sfcgal/approximatemedialaxis.sql
new file mode 100644 (file)
index 0000000..dfbdf3b
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT 'square', ST_AsText(ST_ApproximateMedialAxis('POLYGON((0 0,1 0,1 1,0 1,0 0))'));
+SELECT 'rect1', ST_AsText(ST_ApproximateMedialAxis('POLYGON((0 0,2 0,2 1,0 1,0 0))'));
+
diff --git a/regress/sfcgal/approximatemedialaxis_expected b/regress/sfcgal/approximatemedialaxis_expected
new file mode 100644 (file)
index 0000000..dfcc72e
--- /dev/null
@@ -0,0 +1,2 @@
+square|MULTILINESTRING EMPTY
+rect1|MULTILINESTRING((0.5 0.5,1.5 0.5))