[postgis-tickets] r14683 - Negative indexing for ST_PointN and ST_SetPoint (R?\195?\169mi Cura)
Daniel Baston
dbaston at gmail.com
Wed Feb 24 08:04:07 PST 2016
Author: dbaston
Date: 2016-02-24 08:04:06 -0800 (Wed, 24 Feb 2016)
New Revision: 14683
Modified:
trunk/doc/introduction.xml
trunk/doc/reference_accessor.xml
trunk/doc/reference_editor.xml
trunk/postgis/lwgeom_functions_basic.c
trunk/postgis/lwgeom_ogc.c
trunk/regress/regress_ogc.sql
trunk/regress/regress_ogc_expected
trunk/regress/setpoint.sql
trunk/regress/setpoint_expected
trunk/regress/sfcgal/regress_ogc_expected
Log:
Negative indexing for ST_PointN and ST_SetPoint (R?\195?\169mi Cura)
Modified: trunk/doc/introduction.xml
===================================================================
--- trunk/doc/introduction.xml 2016-02-24 16:02:25 UTC (rev 14682)
+++ trunk/doc/introduction.xml 2016-02-24 16:04:06 UTC (rev 14683)
@@ -227,6 +227,7 @@
Norman Vine,
Rafal Magda,
Ralph Mason,
+RĂ©mi Cura,
Richard Greenwood,
Silvio Grosso,
Steffen Macke,
Modified: trunk/doc/reference_accessor.xml
===================================================================
--- trunk/doc/reference_accessor.xml 2016-02-24 16:02:25 UTC (rev 14682)
+++ trunk/doc/reference_accessor.xml 2016-02-24 16:04:06 UTC (rev 14683)
@@ -2004,8 +2004,8 @@
<refnamediv>
<refname>ST_PointN</refname>
- <refpurpose>Return the Nth point in the first linestring or circular linestring in the
- geometry. Return NULL if there is no linestring in the
+ <refpurpose>Return the Nth point in the first LineString or circular LineString in the
+ geometry. Negative values are counted backwards from the end of the LineString. Returns NULL if there is no linestring in the
geometry.</refpurpose>
</refnamediv>
@@ -2023,11 +2023,12 @@
<title>Description</title>
<para>Return the Nth point in a single linestring or circular linestring in the
- geometry. Return NULL if there is no linestring in the
+ geometry. Negative values are counted backwards from the end of the LineString, so that -1 is the last point. Returns NULL if there is no linestring in the
geometry.</para>
<note>
<para>Index is 1-based as for OGC specs since version 0.8.0.
+ Backward indexing (negative index) is not in OGC
Previous versions implemented this as 0-based instead.</para>
</note>
@@ -2042,7 +2043,10 @@
<para>&curve_support;</para>
<note><para>Changed: 2.0.0 no longer works with single geometry multilinestrings. In older
versions of PostGIS -- a single line multilinestring would work happily with this
- function and return the start point. In 2.0.0 it just returns NULL like any other multilinestring.</para></note>
+ function and return the start point. In 2.0.0 it just returns NULL like any other multilinestring.</para>
+ <para> Changed: 2.3.0 : negative indexing available (-1 is last point)
+ </para>
+ </note>
</refsection>
@@ -2071,6 +2075,15 @@
st_astext
----------
POINT(3 2)
+
+SELECT st_astext(f)
+FROM ST_GeometryFromtext('LINESTRING(0 0 0, 1 1 1, 2 2 2)') as g
+ ,ST_PointN(g, -2) AS f -- 1 based index
+
+st_astext
+----------
+"POINT Z (1 1 1)"
+
</programlisting>
</refsection>
Modified: trunk/doc/reference_editor.xml
===================================================================
--- trunk/doc/reference_editor.xml 2016-02-24 16:02:25 UTC (rev 14682)
+++ trunk/doc/reference_editor.xml 2016-02-24 16:04:06 UTC (rev 14683)
@@ -1401,7 +1401,7 @@
<refnamediv>
<refname>ST_SetPoint</refname>
<refpurpose>Replace point N of linestring with given point. Index is
- 0-based.</refpurpose>
+ 0-based. Negative indexes are counted backwards, so that -1 is the last point.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
@@ -1418,9 +1418,10 @@
<title>Description</title>
<para>Replace point N of linestring with given point. Index is
- 0-based.
+ 0-based.Negative index are counted backwards, so that -1 is last point.
This is especially useful in triggers when trying to maintain relationship of joints when one vertex moves.</para>
<para>Availability: 1.1.0</para>
+ <para>Updated 2.3.0 : negative indexing</para>
<para>&Z_support;</para>
</refsection>
@@ -1440,6 +1441,14 @@
st_asewkt
-----------------------
LINESTRING(-1 2 3,-1 3 4,-1 1 3)
+
+SELECT ST_AsText(ST_SetPoint(g, -3, p))
+FROM ST_GEomFromText('LINESTRING(0 0, 1 1, 2 2, 3 3, 4 4)') AS g
+ , ST_PointN(g,1) as p;
+ st_astext
+-----------------------
+LINESTRING(0 0,1 1,0 0,3 3,4 4)
+
</programlisting>
</refsection>
<refsection>
Modified: trunk/postgis/lwgeom_functions_basic.c
===================================================================
--- trunk/postgis/lwgeom_functions_basic.c 2016-02-24 16:02:25 UTC (rev 14682)
+++ trunk/postgis/lwgeom_functions_basic.c 2016-02-24 16:04:06 UTC (rev 14683)
@@ -2249,7 +2249,7 @@
LWLINE *line;
LWPOINT *lwpoint;
POINT4D newpoint;
- uint32 which;
+ int32 which;
POSTGIS_DEBUG(2, "LWGEOM_setpoint_linestring called.");
@@ -2279,9 +2279,13 @@
elog(ERROR, "First argument must be a LINESTRING");
PG_RETURN_NULL();
}
- if ( which > line->points->npoints-1 )
+ if(which < 0){
+ /* Use backward indexing for negative values */
+ which = which + line->points->npoints ;
+ }
+ if ( which > line->points->npoints-1 || which < 0 )
{
- elog(ERROR, "Point index out of range (%d..%d)", 0, line->points->npoints-1);
+ elog(ERROR, "abs(Point index) out of range (-)(%d..%d)", 0, line->points->npoints-1);
PG_RETURN_NULL();
}
Modified: trunk/postgis/lwgeom_ogc.c
===================================================================
--- trunk/postgis/lwgeom_ogc.c 2016-02-24 16:02:25 UTC (rev 14682)
+++ trunk/postgis/lwgeom_ogc.c 2016-02-24 16:04:06 UTC (rev 14683)
@@ -545,11 +545,23 @@
LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
LWPOINT *lwpoint = NULL;
int type = lwgeom->type;
+
+ /* If index is negative, count backward */
+ if( where < 1 )
+ {
+ int count = -1;
+ if ( type == LINETYPE || type == CIRCSTRINGTYPE || type == COMPOUNDTYPE )
+ count = lwgeom_count_vertices(lwgeom);
+ if(count >0)
+ {
+ /* only work if we found the total point number */
+ /* converting where to positive backward indexing, +1 because 1 indexing */
+ where = where + count + 1;
+ }
+ if (where < 1)
+ PG_RETURN_NULL();
+ }
- /* Can't handle crazy index! */
- if ( where < 1 )
- PG_RETURN_NULL();
-
if ( type == LINETYPE || type == CIRCSTRINGTYPE )
{
/* OGC index starts at one, so we substract first. */
Modified: trunk/regress/regress_ogc.sql
===================================================================
--- trunk/regress/regress_ogc.sql 2016-02-24 16:02:25 UTC (rev 14682)
+++ trunk/regress/regress_ogc.sql 2016-02-24 16:04:06 UTC (rev 14683)
@@ -192,6 +192,9 @@
select 'ST_PointN4', ST_AsText(ST_PointN('LINESTRING(0 0, 1 1, 2 2)'::geometry,0));
select 'ST_PointN5', ST_AsText(ST_PointN('LINESTRING(0 0, 1 1, 2 2)'::geometry,1));
select 'ST_PointN6', ST_AsText(ST_PointN('POLYGON((0 0, 1 1, 0 1, 0 0))'::geometry,1));
+select 'ST_PointN7', ST_AsText(ST_PointN('LINESTRING(0 0, 1 1, 2 2,3 3, 4 4)'::geometry,-2)); --testing negativ index
+select 'ST_PointN8', ST_AsText(ST_PointN('LINESTRING(0 0, 1 1, 2 2,3 3, 4 4)'::geometry,-6));
+select 'ST_PointN9', ST_AsText(ST_PointN('LINESTRING(0 0 0, 1 1 1,2 2 2,3 3 3,4 4 4)'::geometry,2)); --testing 3D
-- issues with EMPTY --
select 'ST_Buffer(empty)', ST_AsText(ST_Buffer('POLYGON EMPTY'::geometry, 0.5));
Modified: trunk/regress/regress_ogc_expected
===================================================================
--- trunk/regress/regress_ogc_expected 2016-02-24 16:02:25 UTC (rev 14682)
+++ trunk/regress/regress_ogc_expected 2016-02-24 16:04:06 UTC (rev 14683)
@@ -112,4 +112,7 @@
ST_PointN4|
ST_PointN5|POINT(0 0)
ST_PointN6|
+ST_PointN7|POINT(3 3)
+ST_PointN8|
+ST_PointN9|POINT Z (1 1 1)
ST_Buffer(empty)|POLYGON EMPTY
Modified: trunk/regress/setpoint.sql
===================================================================
--- trunk/regress/setpoint.sql 2016-02-24 16:02:25 UTC (rev 14682)
+++ trunk/regress/setpoint.sql 2016-02-24 16:04:06 UTC (rev 14683)
@@ -1,7 +1,8 @@
-- Repeat all tests with new function names.
-- Out of range indexes
SELECT ST_SetPoint('LINESTRING(0 0, 1 1, 2 2)', 3, 'POINT(9 9)');
-SELECT ST_SetPoint('LINESTRING(0 0, 1 1, 2 2)', -1, 'POINT(9 9)');
+SELECT ST_asewkt(ST_SetPoint('LINESTRING(0 0, 1 1, 2 2)', -1, 'POINT(9 9)'));
+SELECT ST_SetPoint('LINESTRING(0 0, 1 1, 2 2)', -10, 'POINT(9 9)');
-- Invalid inputs
SELECT ST_SetPoint('MULTIPOINT(0 0, 1 1, 2 2)', 3, 'POINT(9 9)');
Modified: trunk/regress/setpoint_expected
===================================================================
--- trunk/regress/setpoint_expected 2016-02-24 16:02:25 UTC (rev 14682)
+++ trunk/regress/setpoint_expected 2016-02-24 16:04:06 UTC (rev 14683)
@@ -1,5 +1,6 @@
-ERROR: Point index out of range (0..2)
-ERROR: Point index out of range (0..2)
+ERROR: abs(Point index) out of range (-)(0..2)
+LINESTRING(0 0,1 1,9 9)
+ERROR: abs(Point index) out of range (-)(0..2)
ERROR: First argument must be a LINESTRING
ERROR: Third argument must be a POINT
LINESTRING(90 91 92,1 1 1,2 2 2)
Modified: trunk/regress/sfcgal/regress_ogc_expected
===================================================================
--- trunk/regress/sfcgal/regress_ogc_expected 2016-02-24 16:02:25 UTC (rev 14682)
+++ trunk/regress/sfcgal/regress_ogc_expected 2016-02-24 16:04:06 UTC (rev 14683)
@@ -112,4 +112,7 @@
ST_PointN4|
ST_PointN5|POINT(0 0)
ST_PointN6|
+ST_PointN7|POINT(3 3)
+ST_PointN8|
+ST_PointN9|POINT Z (1 1 1)
ST_Buffer(empty)|POLYGON EMPTY
More information about the postgis-tickets
mailing list