From: Paul Ramsey Date: Thu, 11 Jun 2015 21:09:13 +0000 (+0000) Subject: #2717, support startpoint, endpoint, pointn, numpoints for compoundcurve X-Git-Tag: 2.2.0rc1~362 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a64ea968f0a6c05317828cea94ab627ed290ef51;p=postgis #2717, support startpoint, endpoint, pointn, numpoints for compoundcurve git-svn-id: http://svn.osgeo.org/postgis/trunk@13664 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in index ef0b7cbc0..9bac3af5e 100644 --- a/liblwgeom/liblwgeom.h.in +++ b/liblwgeom/liblwgeom.h.in @@ -1147,8 +1147,13 @@ extern void lwgeom_affine(LWGEOM *geom, const AFFINE *affine); extern void lwgeom_scale(LWGEOM *geom, const POINT4D *factors); extern int lwgeom_dimension(const LWGEOM *geom); -extern LWPOINT* lwline_get_lwpoint(LWLINE *line, int where); -extern LWPOINT* lwcircstring_get_lwpoint(LWCIRCSTRING *circ, int where); +extern LWPOINT* lwline_get_lwpoint(const LWLINE *line, int where); +extern LWPOINT* lwcircstring_get_lwpoint(const LWCIRCSTRING *circ, int where); + +extern LWPOINT* lwcompound_get_startpoint(const LWCOMPOUND *lwcmp); +extern LWPOINT* lwcompound_get_endpoint(const LWCOMPOUND *lwcmp); +extern LWPOINT* lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, int where); + extern double ptarray_length_2d(const POINTARRAY *pts); extern double ptarray_length(const POINTARRAY *pts); diff --git a/liblwgeom/lwcircstring.c b/liblwgeom/lwcircstring.c index 3361cd603..573bc391f 100644 --- a/liblwgeom/lwcircstring.c +++ b/liblwgeom/lwcircstring.c @@ -284,7 +284,7 @@ double lwcircstring_length_2d(const LWCIRCSTRING *circ) * Returns freshly allocated #LWPOINT that corresponds to the index where. * Returns NULL if the geometry is empty or the index invalid. */ -LWPOINT* lwcircstring_get_lwpoint(LWCIRCSTRING *circ, int where) { +LWPOINT* lwcircstring_get_lwpoint(const LWCIRCSTRING *circ, int where) { POINT4D pt; LWPOINT *lwpoint; POINTARRAY *pa; diff --git a/liblwgeom/lwcompound.c b/liblwgeom/lwcompound.c index 5478c44c3..8c28400e2 100644 --- a/liblwgeom/lwcompound.c +++ b/liblwgeom/lwcompound.c @@ -200,3 +200,65 @@ lwcompound_construct_from_lwline(const LWLINE *lwline) /* ogeom->bbox = lwline->bbox; */ return ogeom; } + +LWPOINT* +lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, int where) +{ + int i; + int count = 0; + int npoints = 0; + if ( lwgeom_is_empty((LWGEOM*)lwcmp) ) + return NULL; + + npoints = lwgeom_count_vertices((LWGEOM*)lwcmp); + if ( where < 0 || where >= npoints ) + { + lwerror("%s: index %d is not in range of number of vertices (%d) in input", __func__, where, npoints); + return NULL; + } + + for ( i = 0; i < lwcmp->ngeoms; i++ ) + { + LWGEOM* part = lwcmp->geoms[i]; + int npoints_part = lwgeom_count_vertices(part); + if ( where >= count && where < count + npoints_part ) + { + return lwline_get_lwpoint((LWLINE*)part, where - count); + } + else + { + count += npoints_part; + } + } + + return NULL; +} + + + +LWPOINT * +lwcompound_get_startpoint(const LWCOMPOUND *lwcmp) +{ + return lwcompound_get_lwpoint(lwcmp, 0); +} + +LWPOINT * +lwcompound_get_endpoint(const LWCOMPOUND *lwcmp) +{ + LWLINE *lwline; + if ( lwcmp->ngeoms < 1 ) + { + return NULL; + } + + lwline = (LWLINE*)(lwcmp->geoms[lwcmp->ngeoms-1]); + + if ( (!lwline) || (!lwline->points) || (lwline->points->npoints < 1) ) + { + return NULL; + } + + return lwline_get_lwpoint(lwline, lwline->points->npoints-1); +} + + \ No newline at end of file diff --git a/liblwgeom/lwline.c b/liblwgeom/lwline.c index b787eedca..f28a04986 100644 --- a/liblwgeom/lwline.c +++ b/liblwgeom/lwline.c @@ -292,7 +292,7 @@ lwline_from_lwmpoint(int srid, const LWMPOINT *mpoint) * Returns NULL if the geometry is empty or the index invalid. */ LWPOINT* -lwline_get_lwpoint(LWLINE *line, int where) +lwline_get_lwpoint(const LWLINE *line, int where) { POINT4D pt; LWPOINT *lwpoint; diff --git a/postgis/lwgeom_ogc.c b/postgis/lwgeom_ogc.c index 4d9b748eb..a4d82cca3 100644 --- a/postgis/lwgeom_ogc.c +++ b/postgis/lwgeom_ogc.c @@ -200,8 +200,9 @@ Datum LWGEOM_numpoints_linestring(PG_FUNCTION_ARGS) GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0); LWGEOM *lwgeom = lwgeom_from_gserialized(geom); int count = -1; + int type = lwgeom->type; - if ( lwgeom->type == LINETYPE || lwgeom->type == CIRCSTRINGTYPE ) + if ( type == LINETYPE || type == CIRCSTRINGTYPE || type == COMPOUNDTYPE ) count = lwgeom_count_vertices(lwgeom); lwgeom_free(lwgeom); @@ -545,6 +546,10 @@ Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS) /* OGC index starts at one, so we substract first. */ lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, where - 1); } + else if ( type == COMPOUNDTYPE ) + { + lwpoint = lwcompound_get_lwpoint((LWCOMPOUND*)lwgeom, where - 1); + } lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); @@ -698,6 +703,10 @@ Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS) { lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, 0); } + else if ( type == COMPOUNDTYPE ) + { + lwpoint = lwcompound_get_startpoint((LWCOMPOUND*)lwgeom); + } lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); @@ -726,6 +735,10 @@ Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS) if ( line->points ) lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, line->points->npoints - 1); } + else if ( type == COMPOUNDTYPE ) + { + lwpoint = lwcompound_get_endpoint((LWCOMPOUND*)lwgeom); + } lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); diff --git a/regress/sql-mm-compoundcurve.sql b/regress/sql-mm-compoundcurve.sql index 53c964242..feed3b47d 100644 --- a/regress/sql-mm-compoundcurve.sql +++ b/regress/sql-mm-compoundcurve.sql @@ -316,7 +316,7 @@ SELECT 'valid wkb compound curve 2', ST_asEWKT(ST_GeomFromEWKB(decode('010900000 SELECT 'valid wkb compound curve 3', ST_asEWKT(ST_GeomFromEWKB(decode('0109000000010000000102000000030000000CE586D73CF36240BBC46888F0523BC0102E91C951E76240DF90A1BEC0F841C0F970C100FFD7624074ADE6CE86CD3BC0', 'hex'))); SELECT 'valid wkb compound curve 4', ST_asEWKT(ST_GeomFromEWKB(decode('0109000000020000000102000000030000009FE5797057376340E09398B1B2373BC05AAE0A165F0963409F6760A2493D3DC0DB6286DFB057634082D8A1B32F843EC0010800000005000000DB6286DFB057634082D8A1B32F843EC0DB6286DFB057634082D8A1B32F843EC075B4E4D0C60C634031FA5D1A371540C0D7197CED9B636340A3CB59A7630A41C050F4A72AC0FB6240974769FCE3CF41C0', 'hex'))); SELECT 'valid wkb compound curve 5', ST_asEWKT(ST_GeomFromEWKB(decode('010900000003000000010800000003000000468280E724BC6340BF4B46210B973BC0F890AEA18D8063402D9664151D483CC0EED64BB6EE726340903CA5BDA0863AC0010200000004000000EED64BB6EE726340903CA5BDA0863AC09FE5797057376340E09398B1B2373BC05AAE0A165F0963409F6760A2493D3DC0DB6286DFB057634082D8A1B32F843EC0010800000005000000DB6286DFB057634082D8A1B32F843EC0DB6286DFB057634082D8A1B32F843EC075B4E4D0C60C634031FA5D1A371540C0D7197CED9B636340A3CB59A7630A41C050F4A72AC0FB6240974769FCE3CF41C0', 'hex'))); -SELECT 'null response', ST_NumPoints(ST_GeomFromEWKT('COMPOUNDCURVE(CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3),(4 3, 4 5, 1 4, 0 0))')); +SELECT 'st_numpoints', ST_NumPoints(ST_GeomFromEWKT('COMPOUNDCURVE(CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3),(4 3, 4 5, 1 4, 0 0))')); SELECT 'minpoints issues - pass', encode(ST_AsBinary(ST_GeomFromText('COMPOUNDCURVE((0 0,1 1))'),'ndr'),'hex'); SELECT 'minpoints issues - pass', encode(ST_AsBinary(ST_GeomFromText('COMPOUNDCURVE(CIRCULARSTRING(0 0,0 1,1 1))'),'ndr'),'hex'); SELECT 'minpoints issues - fail', ST_GeomFromText('COMPOUNDCURVE(CIRCULARSTRING(0 0,1 1))'); diff --git a/regress/sql-mm-compoundcurve_expected b/regress/sql-mm-compoundcurve_expected index 6d535db06..07e3d09d3 100644 --- a/regress/sql-mm-compoundcurve_expected +++ b/regress/sql-mm-compoundcurve_expected @@ -79,7 +79,7 @@ valid wkb compound curve 2|COMPOUNDCURVE((153.72942375 -27.2175704,152.29285719 valid wkb compound curve 3|COMPOUNDCURVE((151.60117699 -27.32398274,151.22873381 -35.9433821,150.74987829 -27.80283826)) valid wkb compound curve 4|COMPOUNDCURVE((153.72942375 -27.2175704,152.29285719 -29.23940482,154.74034096 -30.51635287),CIRCULARSTRING(154.74034096 -30.51635287,154.74034096 -30.51635287,152.39926953 -32.16574411,155.11278414 -34.08116619,151.86720784 -35.62414508)) valid wkb compound curve 5|COMPOUNDCURVE(CIRCULARSTRING(157.87950492 -27.59001358,156.01728901 -28.28169378,155.59163966 -26.52589021),(155.59163966 -26.52589021,153.72942375 -27.2175704,152.29285719 -29.23940482,154.74034096 -30.51635287),CIRCULARSTRING(154.74034096 -30.51635287,154.74034096 -30.51635287,152.39926953 -32.16574411,155.11278414 -34.08116619,151.86720784 -35.62414508)) -null response| +st_numpoints|9 minpoints issues - pass|01090000000100000001020000000200000000000000000000000000000000000000000000000000f03f000000000000f03f minpoints issues - pass|010900000001000000010800000003000000000000000000000000000000000000000000000000000000000000000000f03f000000000000f03f000000000000f03f ERROR: geometry requires more points diff --git a/regress/tickets.sql b/regress/tickets.sql index 444ff87f1..8373721be 100644 --- a/regress/tickets.sql +++ b/regress/tickets.sql @@ -879,6 +879,18 @@ SELECT '#2704', ST_AsText(ST_GeomFromGML(' SELECT '#2712', ST_AsText(ST_Segmentize('LINESTRING EMPTY'::geometry, 0.5)); +SELECT '#2717', + ST_AsText(ST_StartPoint(g)), + ST_AsText(ST_EndPoint(g)), + ST_AsText(ST_PointN(g, 1)), + ST_AsText(ST_PointN(g, 2)), + ST_AsText(ST_PointN(g, 3)), + ST_AsText(ST_PointN(g, 4)), + ST_AsText(ST_PointN(g, 5)) + FROM ( + SELECT 'COMPOUNDCURVE((-1 -1, 1 1), CIRCULARSTRING(1 1, 2 2, 3 1))'::geometry AS g + ) AS foo; + SELECT '#2788', valid, reason, ST_AsText(location) from ST_IsValidDetail('POLYGON((0 0, 0 1, 2 1, 2 2, 1 2, 1 0, 0 0))'::geometry); SELECT '#2870', ST_Summary('Point(151.215289 -33.856885)'::geometry::bytea::geography) ; diff --git a/regress/tickets_expected b/regress/tickets_expected index aa6ef40d7..a7863fee8 100644 --- a/regress/tickets_expected +++ b/regress/tickets_expected @@ -258,6 +258,7 @@ ERROR: invalid GML representation #2556|1|0 #2704|POLYGON((0 0,0 1,1 1,1 0,0 0)) #2712|LINESTRING EMPTY +#2717|POINT(-1 -1)|POINT(3 1)|POINT(-1 -1)|POINT(1 1)|POINT(1 1)|POINT(2 2)|POINT(3 1) #2788|f|Self-intersection|POINT(1 1) #2870|Point[GS] #2956|t