From 4f34e0f27e87965bb682c79a86f2eaa1ec2f47b0 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Wed, 15 Jun 2016 09:49:50 +0000 Subject: [PATCH] Add ST_Normalize function Includes tests and documentation Closes #1768 git-svn-id: http://svn.osgeo.org/postgis/trunk@14949 b70326c6-7e19-0410-871a-916f4a2858ee --- NEWS | 1 + doc/reference_editor.xml | 61 ++++++++++++++++++++++++++++++++ postgis/lwgeom_functions_basic.c | 27 ++++++++++++++ postgis/postgis.sql.in | 7 ++++ regress/Makefile.in | 1 + regress/normalize.sql | 7 ++++ regress/normalize_expected | 3 ++ 7 files changed, 107 insertions(+) create mode 100644 regress/normalize.sql create mode 100644 regress/normalize_expected diff --git a/NEWS b/NEWS index f88fbfbf8..6dd21f428 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,7 @@ PostGIS 2.3.0 - Add parameters for geography ST_Buffer (Thomas Bonfort) - TopoGeom_addElement, TopoGeom_remElement (Sandro Santilli) - populate_topology_layer (Sandro Santilli) + - #1758, ST_Normalize (Sandro Santilli) - #2259, ST_Voronoi (Dan Baston) - #2991, Enable ST_Transform to use PROJ.4 text (Mike Toews) - #3059, Allow passing per-dimension parameters in ST_Expand (Dan Baston) diff --git a/doc/reference_editor.xml b/doc/reference_editor.xml index 58339c809..6aa3d37ff 100644 --- a/doc/reference_editor.xml +++ b/doc/reference_editor.xml @@ -897,6 +897,67 @@ MULTILINESTRING((0 0, 1 1), (2 2, 3 3)) + + + ST_Normalize + + Returns the geometry in its canonical form. + + + + + + geometry ST_Normalized + geometry geom + + + + + + Description + + + Returns the geometry in its normalized/canonical form. + May reorder vertices in polygon rings, rings in a polygon, + elements in a multi-geometry complex. + + + + Mostly only useful for testing purposes (comparing expected + and obtained results). + + + + + + Examples + + +SELECT ST_AsText(ST_Normalize(ST_GeomFromText( + 'GEOMETRYCOLLECTION( + POINT(2 3), + MULTILINESTRING((0 0, 1 1),(2 2, 3 3)), + POLYGON( + (0 10,0 0,10 0,10 10,0 10), + (4 2,2 2,2 4,4 4,4 2), + (6 8,8 8,8 6,6 6,6 8) + ) + )' +))); + st_astext +---------------------------------------------------------------------------------------------------------------------------------------------------- + GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0),(6 6,8 6,8 8,6 8,6 6),(2 2,4 2,4 4,2 4,2 2)),MULTILINESTRING((2 2,3 3),(0 0,1 1)),POINT(2 3)) +(1 row) + + + + See Also + + , + + + + ST_RemovePoint diff --git a/postgis/lwgeom_functions_basic.c b/postgis/lwgeom_functions_basic.c index dec8e3c60..f023f5aa8 100644 --- a/postgis/lwgeom_functions_basic.c +++ b/postgis/lwgeom_functions_basic.c @@ -1900,6 +1900,33 @@ Datum LWGEOM_noop(PG_FUNCTION_ARGS) PG_RETURN_POINTER(out); } +Datum ST_Normalize(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(ST_Normalize); +Datum ST_Normalize(PG_FUNCTION_ARGS) +{ + GSERIALIZED *in, *out; + LWGEOM *lwgeom_in, *lwgeom_out; + + POSTGIS_DEBUG(2, "ST_Normalize called"); + + in = PG_GETARG_GSERIALIZED_P_COPY(0); + + lwgeom_in = lwgeom_from_gserialized(in); + POSTGIS_DEBUGF(3, "Deserialized: %s", lwgeom_summary(lwgeom_in, 0)); + + lwgeom_out = lwgeom_normalize(lwgeom_in); + POSTGIS_DEBUGF(3, "Normalized: %s", lwgeom_summary(lwgeom_out, 0)); + + out = geometry_serialize(lwgeom_out); + lwgeom_free(lwgeom_in); + lwgeom_free(lwgeom_out); + + PG_FREE_IF_COPY(in, 0); + + PG_RETURN_POINTER(out); +} + + /** * @return: * 0==2d diff --git a/postgis/postgis.sql.in b/postgis/postgis.sql.in index 9082231ea..d53be8df3 100644 --- a/postgis/postgis.sql.in +++ b/postgis/postgis.sql.in @@ -1477,6 +1477,13 @@ CREATE OR REPLACE FUNCTION postgis_noop(geometry) LANGUAGE 'c' VOLATILE STRICT COST 10; +-- Availability: 2.3.0 +CREATE OR REPLACE FUNCTION ST_Normalize(geom geometry) + RETURNS geometry + AS 'MODULE_PATHNAME', 'ST_Normalize' + LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL + COST 20; -- 20 as it delegates to GEOS + -- Deprecation in 1.5.0 CREATE OR REPLACE FUNCTION ST_zmflag(geometry) RETURNS smallint diff --git a/regress/Makefile.in b/regress/Makefile.in index 40b32298a..09abbea8b 100644 --- a/regress/Makefile.in +++ b/regress/Makefile.in @@ -98,6 +98,7 @@ TESTS = \ lwgeom_regress \ measures \ minimum_bounding_circle \ + normalize \ operators \ out_geometry \ out_geography \ diff --git a/regress/normalize.sql b/regress/normalize.sql new file mode 100644 index 000000000..02aac6518 --- /dev/null +++ b/regress/normalize.sql @@ -0,0 +1,7 @@ +select 1, ST_AsText(ST_Normalize( +'GEOMETRYCOLLECTION(POINT(2 3),MULTILINESTRING((0 0, 1 1),(2 2, 3 3)))' +::geometry)); + +select 2, ST_AsText(ST_Normalize( +'POLYGON((0 10,0 0,10 0,10 10,0 10),(4 2,2 2,2 4,4 4,4 2),(6 8,8 8,8 6,6 6,6 8))' +::geometry)); diff --git a/regress/normalize_expected b/regress/normalize_expected new file mode 100644 index 000000000..cf1c4543c --- /dev/null +++ b/regress/normalize_expected @@ -0,0 +1,3 @@ +1|GEOMETRYCOLLECTION(MULTILINESTRING((2 2,3 3),(0 0,1 1)),POINT(2 3)) +2|POLYGON((0 0,0 10,10 10,10 0,0 0),(6 6,8 6,8 8,6 8,6 6),(2 2,4 2,4 4,2 4,2 2)) + -- 2.49.0