From 863ea35813dbaf582217c81516192e24e8a0086c Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Tue, 22 Aug 2017 12:39:14 +0000 Subject: [PATCH] Add support for curves in lwgeom_reverse/ST_Reverse Includes tests Closes #2411 git-svn-id: http://svn.osgeo.org/postgis/trunk@15566 b70326c6-7e19-0410-871a-916f4a2858ee --- NEWS | 1 + doc/reference_editor.xml | 4 ++ liblwgeom/liblwgeom_internal.h | 5 ++ liblwgeom/lwgeom.c | 7 +++ regress/Makefile.in | 1 + regress/reverse.sql | 98 ++++++++++++++++++++++++++++++++++ regress/reverse_expected | 49 +++++++++++++++++ 7 files changed, 165 insertions(+) create mode 100644 regress/reverse.sql create mode 100644 regress/reverse_expected diff --git a/NEWS b/NEWS index cd3be1b01..449cd340b 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ PostGIS 2.4.0 * New Features * + - #2411, curves support in ST_Reverse (Sandro Santilli) - #2951, ST_Centroid for geography (Danny Götte) - #3788, Allow postgis_restore.pl to work on directory-style (-Fd) dumps (Roger Crew) diff --git a/doc/reference_editor.xml b/doc/reference_editor.xml index 9c23c7a68..9ef0535cb 100644 --- a/doc/reference_editor.xml +++ b/doc/reference_editor.xml @@ -1120,6 +1120,10 @@ UPDATE sometable Description Can be used on any geometry and reverses the order of the vertexes. + + Enhanced: 2.4.0 support for curves was introduced. + &Z_support; + &P_support; diff --git a/liblwgeom/liblwgeom_internal.h b/liblwgeom/liblwgeom_internal.h index 3f5edc110..838262a52 100644 --- a/liblwgeom/liblwgeom_internal.h +++ b/liblwgeom/liblwgeom_internal.h @@ -340,6 +340,11 @@ LWPOLY *lwpoly_clone_deep(const LWPOLY *lwgeom); LWCOLLECTION *lwcollection_clone_deep(const LWCOLLECTION *lwgeom); GBOX *gbox_clone(const GBOX *gbox); +/* + * Reverse + */ +extern void lwcircstring_reverse(LWCIRCSTRING *curve); + /* * Startpoint */ diff --git a/liblwgeom/lwgeom.c b/liblwgeom/lwgeom.c index 87f966c37..ffc249857 100644 --- a/liblwgeom/lwgeom.c +++ b/liblwgeom/lwgeom.c @@ -106,11 +106,18 @@ lwgeom_reverse(LWGEOM *lwgeom) case TRIANGLETYPE: lwtriangle_reverse((LWTRIANGLE *)lwgeom); return; + case CIRCSTRINGTYPE: + lwcircstring_reverse((LWCIRCSTRING *)lwgeom); + return; + case MULTICURVETYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: + case MULTISURFACETYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: case COLLECTIONTYPE: + case COMPOUNDTYPE: + case CURVEPOLYTYPE: col = (LWCOLLECTION *)lwgeom; for (i=0; ingeoms; i++) lwgeom_reverse(col->geoms[i]); diff --git a/regress/Makefile.in b/regress/Makefile.in index 143e2b052..cbee4e869 100644 --- a/regress/Makefile.in +++ b/regress/Makefile.in @@ -123,6 +123,7 @@ TESTS = \ relate \ remove_repeated_points \ removepoint \ + reverse \ setpoint \ simplify \ simplifyvw \ diff --git a/regress/reverse.sql b/regress/reverse.sql new file mode 100644 index 000000000..7176f7056 --- /dev/null +++ b/regress/reverse.sql @@ -0,0 +1,98 @@ +-- Point +SELECT 'pnt1', ST_AsText(ST_Reverse('POINT EMPTY'::geometry)); +SELECT 'pnt2', ST_AsText(ST_Reverse('POINT(0 0)'::geometry)); + +-- Multipoint +SELECT 'mpnt1', ST_AsText(ST_Reverse('MULTIPOINT EMPTY'::geometry)); +SELECT 'mpnt2', ST_AsText(ST_Reverse('MULTIPOINT(0 0)'::geometry)); +SELECT 'mpnt3', ST_AsText(ST_Reverse('MULTIPOINT(0 0,1 1)'::geometry)); + +-- Linestring +SELECT 'lin1', ST_AsText(ST_Reverse('LINESTRING EMPTY'::geometry)); +SELECT 'lin2', ST_AsText(ST_Reverse('LINESTRING(0 0, 1 1)'::geometry)); +SELECT 'lin2m', ST_AsText(ST_Reverse('LINESTRING M (0 0 3,1 1 6)'::geometry)); +SELECT 'lin2z', ST_AsText(ST_Reverse('LINESTRING Z (0 0 3,1 1 6)'::geometry)); + +-- MultiLinestring +SELECT 'mlin1', ST_AsText(ST_Reverse('MULTILINESTRING EMPTY'::geometry)); +SELECT 'mlin2', ST_AsText(ST_Reverse('MULTILINESTRING((0 0, 1 0),(2 0, -3 3))'::geometry)); +SELECT 'mlin2m', ST_AsText(ST_Reverse('MULTILINESTRING M ((0 0 5, 1 0 3),(2 0 2, -3 3 1))'::geometry)); +SELECT 'mlin2z', ST_AsText(ST_Reverse('MULTILINESTRING Z ((0 0 5, 1 0 3),(2 0 2, -3 3 1))'::geometry)); + +-- Polygon +SELECT 'plg1', ST_AsText(ST_Reverse('POLYGON EMPTY'::geometry)); +SELECT 'plg2', ST_AsText(ST_Reverse('POLYGON((0 0,8 0,8 8,0 8,0 0),(2 2,2 4,4 4,4 2,2 2))'::geometry)); +SELECT 'plg2m', ST_AsText(ST_Reverse('POLYGON M ((0 0 9,8 0 8,8 8 7,0 8 8,0 0 9),(2 2 1,2 4 2,4 4 3,4 2 2,2 2 1))'::geometry)); +SELECT 'plg2z', ST_AsText(ST_Reverse('POLYGON Z ((0 0 9,8 0 8,8 8 7,0 8 8,0 0 9),(2 2 1,2 4 2,4 4 3,4 2 2,2 2 1))'::geometry)); + +-- MultiPolygon +SELECT 'mplg1', ST_AsText(ST_Reverse('MULTIPOLYGON EMPTY'::geometry)); +SELECT 'mplg2', ST_AsText(ST_Reverse('MULTIPOLYGON(((0 0,5 0,5 5,0 5,0 0),(2 2,2 4,4 4,4 2,2 2)),((6 6,7 6,7 7,6 6)))'::geometry)); +SELECT 'mplg2m', ST_AsText(ST_Reverse('MULTIPOLYGON M (((0 0 1,5 0 2,5 5 3,0 5 4,0 0 1),(2 2 0,2 4 1,4 4 2,4 2 3,2 2 0)),((6 6 2,7 6 4,7 7 6,6 6 2)))'::geometry)); +SELECT 'mplg2z', ST_AsText(ST_Reverse('MULTIPOLYGON Z (((0 0 1,5 0 2,5 5 3,0 5 4,0 0 1),(2 2 0,2 4 1,4 4 2,4 2 3,2 2 0)),((6 6 2,7 6 4,7 7 6,6 6 2)))'::geometry)); + +-- CircularString +SELECT 'cstr1', ST_AsText(ST_Reverse('CIRCULARSTRING EMPTY'::geometry)); +SELECT 'cstr2', ST_AsText(ST_Reverse('CIRCULARSTRING(0 0,1 1,2 0,3 -1,4 0)'::geometry)); +SELECT 'cstr2m', ST_AsText(ST_Reverse('CIRCULARSTRING M (0 0 1,1 1 2,2 0 3,3 -1 4,4 0 5)'::geometry)); +SELECT 'cstr2z', ST_AsText(ST_Reverse('CIRCULARSTRING Z (0 0 1,1 1 2,2 0 3,3 -1 4,4 0 5)'::geometry)); + +-- CompoundCurve +SELECT 'ccrv1', ST_AsText(ST_Reverse('COMPOUNDCURVE EMPTY'::geometry)); +SELECT 'ccrv2', ST_AsText(ST_Reverse('COMPOUNDCURVE(CIRCULARSTRING(0 0,1 1,1 0),(1 0,0 1))'::geometry)); +SELECT 'ccrv2m', ST_AsText(ST_Reverse('COMPOUNDCURVE M (CIRCULARSTRING(0 0 3,1 1 2,1 0 1),(1 0 6,0 1 7))'::geometry)); +SELECT 'ccrv2z', ST_AsText(ST_Reverse('COMPOUNDCURVE Z (CIRCULARSTRING(0 0 3,1 1 2,1 0 1),(1 0 6,0 1 7))'::geometry)); + +-- CurvePolygon +SELECT 'cplg1', ST_AsText(ST_Reverse('CURVEPOLYGON EMPTY'::geometry)); +SELECT 'cplg2', ST_AsText(ST_Reverse('CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0,1 1,1 0),(1 0,0 1),(0 1,0 0)))'::geometry)); +SELECT 'cplg2m', ST_AsText(ST_Reverse('CURVEPOLYGON M (COMPOUNDCURVE (CIRCULARSTRING (0 0 2,1 1 2,1 0 2),(1 0 2,0 1 2),(0 1 2, 0 0 2)))'::geometry)); +SELECT 'cplg2z', ST_AsText(ST_Reverse('CURVEPOLYGON Z (COMPOUNDCURVE (CIRCULARSTRING (0 0 2,1 1 2,1 0 2),(1 0 2,0 1 2),(0 1 2, 0 0 2)))'::geometry)); + +-- MultiCurve +SELECT 'mc1', ST_AsText(ST_Reverse('MULTICURVE EMPTY'::geometry)); +SELECT 'mc2', ST_AsText(ST_Reverse('MULTICURVE ((5 5, 3 5, 3 3, 0 3), CIRCULARSTRING (0 0, 0.2 1, 0.5 1.4), COMPOUNDCURVE (CIRCULARSTRING (0 0,1 1,1 0),(1 0,0 1)))'::geometry)); +SELECT 'mc2zm', ST_AsText(ST_Reverse('MULTICURVE ZM ((5 5 0 1, 3 5 2 3, 3 3 7 5, 0 3 9 8), CIRCULARSTRING (0 0 1 3, 0.2 1 4 2, 0.5 1.4 5 1), COMPOUNDCURVE (CIRCULARSTRING (0 0 -1 -2,1 1 0 4,1 0 5 6),(1 0 4 2,0 1 3 4)))'::geometry)); + +-- MultiSurface +SELECT 'ms1', ST_AsText(ST_Reverse('MULTISURFACE EMPTY'::geometry)); +SELECT 'ms2', ST_AsText(ST_Reverse('MULTISURFACE (CURVEPOLYGON (CIRCULARSTRING (-2 0, -1 -1, 0 0, 1 -1, 2 0, 0 2, -2 0), (-1 0, 0 0.5, 1 0, 0 1, -1 0)), ((7 8, 10 10, 6 14, 4 11, 7 8)))'::geometry)); +SELECT 'ms2m', ST_AsText(ST_Reverse( +'MULTISURFACE M (CURVEPOLYGON M (CIRCULARSTRING M (-2 0 0, -1 -1 1, 0 0 2, 1 -1 3, 2 0 4, 0 2 2, -2 0 0), (-1 0 1, 0 0.5 2, 1 0 3, 0 1 3, -1 0 1)), ((7 8 7, 10 10 5, 6 14 3, 4 11 4, 7 8 7)))' +::geometry)); +SELECT 'ms2z', ST_AsText(ST_Reverse( +'MULTISURFACE Z (CURVEPOLYGON Z (CIRCULARSTRING Z (-2 0 0, -1 -1 1, 0 0 2, 1 -1 3, 2 0 4, 0 2 2, -2 0 0), (-1 0 1, 0 0.5 2, 1 0 3, 0 1 3, -1 0 1)), ((7 8 7, 10 10 5, 6 14 3, 4 11 4, 7 8 7)))' +::geometry)); + +-- PolyedralSurface (TODO) +SELECT 'ps1', ST_AsText(ST_Reverse( +'POLYHEDRALSURFACE EMPTY' +::geometry)); +SELECT 'ps2', ST_AsText(ST_Reverse( +'POLYHEDRALSURFACE (((0 0,0 0,0 1,0 0)),((0 0,0 1,1 0,0 0)),((0 0,1 0,0 0,0 0)),((1 0,0 1,0 0,1 0)))' +::geometry)); + +-- Triangle +SELECT 'tri1', ST_AsText(ST_Reverse( +'TRIANGLE EMPTY' +::geometry)); +SELECT 'tri2', ST_AsText(ST_Reverse( +'TRIANGLE ((1 2,4 5,7 8,1 2))' +::geometry)); +SELECT 'tri2z', ST_AsText(ST_Reverse( +'TRIANGLE Z ((1 2 3,4 5 6,7 8 9,1 2 3))' +::geometry)); + +-- TIN +SELECT 'tin1', ST_AsText(ST_Reverse( 'TIN EMPTY' ::geometry)); +SELECT 'tin2', ST_AsText(ST_Reverse( +'TIN ( ((0 0, 0 0, 0 1, 0 0)), ((0 0, 0 1, 1 1, 0 0)) )' +::geometry)); + +-- GeometryCollection +SELECT 'gc1', ST_AsText(ST_Reverse( +'GEOMETRYCOLLECTION EMPTY' +::geometry)); +SELECT 'gc2', ST_AsText(ST_Reverse( +'GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(2 2,2 5,5 5,5 2,2 2))),POINT(0 0),MULTILINESTRING((0 0, 2 0),(1 1, 2 2)))' +::geometry)); diff --git a/regress/reverse_expected b/regress/reverse_expected new file mode 100644 index 000000000..110d2df02 --- /dev/null +++ b/regress/reverse_expected @@ -0,0 +1,49 @@ +pnt1|POINT EMPTY +pnt2|POINT(0 0) +mpnt1|MULTIPOINT EMPTY +mpnt2|MULTIPOINT(0 0) +mpnt3|MULTIPOINT(0 0,1 1) +lin1|LINESTRING EMPTY +lin2|LINESTRING(1 1,0 0) +lin2m|LINESTRING M (1 1 6,0 0 3) +lin2z|LINESTRING Z (1 1 6,0 0 3) +mlin1|MULTILINESTRING EMPTY +mlin2|MULTILINESTRING((1 0,0 0),(-3 3,2 0)) +mlin2m|MULTILINESTRING M ((1 0 3,0 0 5),(-3 3 1,2 0 2)) +mlin2z|MULTILINESTRING Z ((1 0 3,0 0 5),(-3 3 1,2 0 2)) +plg1|POLYGON EMPTY +plg2|POLYGON((0 0,0 8,8 8,8 0,0 0),(2 2,4 2,4 4,2 4,2 2)) +plg2m|POLYGON M ((0 0 9,0 8 8,8 8 7,8 0 8,0 0 9),(2 2 1,4 2 2,4 4 3,2 4 2,2 2 1)) +plg2z|POLYGON Z ((0 0 9,0 8 8,8 8 7,8 0 8,0 0 9),(2 2 1,4 2 2,4 4 3,2 4 2,2 2 1)) +mplg1|MULTIPOLYGON EMPTY +mplg2|MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0),(2 2,4 2,4 4,2 4,2 2)),((6 6,7 7,7 6,6 6))) +mplg2m|MULTIPOLYGON M (((0 0 1,0 5 4,5 5 3,5 0 2,0 0 1),(2 2 0,4 2 3,4 4 2,2 4 1,2 2 0)),((6 6 2,7 7 6,7 6 4,6 6 2))) +mplg2z|MULTIPOLYGON Z (((0 0 1,0 5 4,5 5 3,5 0 2,0 0 1),(2 2 0,4 2 3,4 4 2,2 4 1,2 2 0)),((6 6 2,7 7 6,7 6 4,6 6 2))) +cstr1|CIRCULARSTRING EMPTY +cstr2|CIRCULARSTRING(4 0,3 -1,2 0,1 1,0 0) +cstr2m|CIRCULARSTRING M (4 0 5,3 -1 4,2 0 3,1 1 2,0 0 1) +cstr2z|CIRCULARSTRING Z (4 0 5,3 -1 4,2 0 3,1 1 2,0 0 1) +ccrv1|COMPOUNDCURVE EMPTY +ccrv2|COMPOUNDCURVE(CIRCULARSTRING(1 0,1 1,0 0),(0 1,1 0)) +ccrv2m|COMPOUNDCURVE M (CIRCULARSTRING M (1 0 1,1 1 2,0 0 3),(0 1 7,1 0 6)) +ccrv2z|COMPOUNDCURVE Z (CIRCULARSTRING Z (1 0 1,1 1 2,0 0 3),(0 1 7,1 0 6)) +cplg1|CURVEPOLYGON EMPTY +cplg2|CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING(1 0,1 1,0 0),(0 1,1 0),(0 0,0 1))) +cplg2m|CURVEPOLYGON M (COMPOUNDCURVE M (CIRCULARSTRING M (1 0 2,1 1 2,0 0 2),(0 1 2,1 0 2),(0 0 2,0 1 2))) +cplg2z|CURVEPOLYGON Z (COMPOUNDCURVE Z (CIRCULARSTRING Z (1 0 2,1 1 2,0 0 2),(0 1 2,1 0 2),(0 0 2,0 1 2))) +mc1|MULTICURVE EMPTY +mc2|MULTICURVE((0 3,3 3,3 5,5 5),CIRCULARSTRING(0.5 1.4,0.2 1,0 0),COMPOUNDCURVE(CIRCULARSTRING(1 0,1 1,0 0),(0 1,1 0))) +mc2zm|MULTICURVE ZM ((0 3 9 8,3 3 7 5,3 5 2 3,5 5 0 1),CIRCULARSTRING ZM (0.5 1.4 5 1,0.2 1 4 2,0 0 1 3),COMPOUNDCURVE ZM (CIRCULARSTRING ZM (1 0 5 6,1 1 0 4,0 0 -1 -2),(0 1 3 4,1 0 4 2))) +ms1|MULTISURFACE EMPTY +ms2|MULTISURFACE(CURVEPOLYGON(CIRCULARSTRING(-2 0,0 2,2 0,1 -1,0 0,-1 -1,-2 0),(-1 0,0 1,1 0,0 0.5,-1 0)),((7 8,4 11,6 14,10 10,7 8))) +ms2m|MULTISURFACE M (CURVEPOLYGON M (CIRCULARSTRING M (-2 0 0,0 2 2,2 0 4,1 -1 3,0 0 2,-1 -1 1,-2 0 0),(-1 0 1,0 1 3,1 0 3,0 0.5 2,-1 0 1)),((7 8 7,4 11 4,6 14 3,10 10 5,7 8 7))) +ms2z|MULTISURFACE Z (CURVEPOLYGON Z (CIRCULARSTRING Z (-2 0 0,0 2 2,2 0 4,1 -1 3,0 0 2,-1 -1 1,-2 0 0),(-1 0 1,0 1 3,1 0 3,0 0.5 2,-1 0 1)),((7 8 7,4 11 4,6 14 3,10 10 5,7 8 7))) +ps1|POLYHEDRALSURFACE EMPTY +ps2|POLYHEDRALSURFACE(((0 0,0 1,0 0,0 0)),((0 0,1 0,0 1,0 0)),((0 0,0 0,1 0,0 0)),((1 0,0 0,0 1,1 0))) +tri1|TRIANGLE EMPTY +tri2|TRIANGLE((1 2,7 8,4 5,1 2)) +tri2z|TRIANGLE Z ((1 2 3,7 8 9,4 5 6,1 2 3)) +tin1|TIN EMPTY +tin2|TIN(((0 0,0 1,0 0,0 0)),((0 0,1 1,0 1,0 0))) +gc1|GEOMETRYCOLLECTION EMPTY +gc2|GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0),(2 2,5 2,5 5,2 5,2 2))),POINT(0 0),MULTILINESTRING((2 0,0 0),(2 2,1 1))) -- 2.50.1