From 816f40e8aa1866e9be645e214a1ab22322e07e45 Mon Sep 17 00:00:00 2001 From: Paul Ramsey Date: Thu, 12 Jan 2012 19:55:30 +0000 Subject: [PATCH] Add support for MULTIPOINT and POINT to ST_LocateBetween git-svn-id: http://svn.osgeo.org/postgis/trunk@8793 b70326c6-7e19-0410-871a-916f4a2858ee --- liblwgeom/liblwgeom.h.in | 10 --- liblwgeom/liblwgeom_internal.h | 21 +++++++ liblwgeom/lwlinearreferencing.c | 107 +++++++++++++++++++++++++++++++- 3 files changed, 127 insertions(+), 11 deletions(-) diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in index c09463755..524861ddb 100644 --- a/liblwgeom/liblwgeom.h.in +++ b/liblwgeom/liblwgeom.h.in @@ -1274,16 +1274,6 @@ int lwline_crossing_direction(const LWLINE *l1, const LWLINE *l2); */ LWCOLLECTION* lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, double to); -/** -* Clip a line based on the from/to range of one of its ordinates. Use for m- and z- clipping -*/ -LWCOLLECTION *lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to); - -/** -* Clip a multi-line based on the from/to range of one of its ordinates. Use for m- and z- clipping -*/ -LWCOLLECTION *lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to); - /* * Export functions */ diff --git a/liblwgeom/liblwgeom_internal.h b/liblwgeom/liblwgeom_internal.h index b770459f6..8e00dbc84 100644 --- a/liblwgeom/liblwgeom_internal.h +++ b/liblwgeom/liblwgeom_internal.h @@ -218,6 +218,27 @@ void lwpoint_set_ordinate(POINT4D *p, char ordinate, double value); */ int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int hasz, int hasm, char ordinate, double interpolation_value); + +/** +* Clip a line based on the from/to range of one of its ordinates. Use for m- and z- clipping +*/ +LWCOLLECTION *lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to); + +/** +* Clip a multi-line based on the from/to range of one of its ordinates. Use for m- and z- clipping +*/ +LWCOLLECTION *lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to); + +/** +* Clip a multi-point based on the from/to range of one of its ordinates. Use for m- and z- clipping +*/ +LWCOLLECTION *lwmpoint_clip_to_ordinate_range(const LWMPOINT *mpoint, char ordinate, double from, double to); + +/** +* Clip a point based on the from/to range of one of its ordinates. Use for m- and z- clipping +*/ +LWCOLLECTION *lwpoint_clip_to_ordinate_range(const LWPOINT *mpoint, char ordinate, double from, double to); + /* * Geohash */ diff --git a/liblwgeom/lwlinearreferencing.c b/liblwgeom/lwlinearreferencing.c index 6391856dd..ae67086da 100644 --- a/liblwgeom/lwlinearreferencing.c +++ b/liblwgeom/lwlinearreferencing.c @@ -330,6 +330,107 @@ int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int ha return 1; } + +/** +* Clip an input POINT between two values, on any ordinate input. +*/ +LWCOLLECTION* +lwpoint_clip_to_ordinate_range(const LWPOINT *point, char ordinate, double from, double to) +{ + LWCOLLECTION *lwgeom_out = NULL; + char hasz, hasm; + POINT4D p4d; + double ordinate_value; + + /* Nothing to do with NULL */ + if ( ! point ) + lwerror("Null input geometry."); + + /* Ensure 'from' is less than 'to'. */ + if ( to < from ) + { + double t = from; + from = to; + to = t; + } + + /* Read Z/M info */ + hasz = lwgeom_has_z(lwpoint_as_lwgeom(point)); + hasm = lwgeom_has_m(lwpoint_as_lwgeom(point)); + + /* Prepare return object */ + lwgeom_out = lwcollection_construct_empty(MULTIPOINTTYPE, point->srid, hasz, hasm); + + /* Test if ordinate is in range */ + lwpoint_getPoint4d_p(point, &p4d); + ordinate_value = lwpoint_get_ordinate(&p4d, ordinate); + if ( from <= ordinate_value && to >= ordinate_value ) + { + LWPOINT *lwp = lwpoint_clone(point); + lwcollection_add_lwgeom(lwgeom_out, lwpoint_as_lwgeom(lwp)); + } + + /* Set the bbox */ + lwgeom_drop_bbox((LWGEOM*)lwgeom_out); + lwgeom_add_bbox((LWGEOM*)lwgeom_out); + + return lwgeom_out; +} + + + +/** +* Clip an input MULTIPOINT between two values, on any ordinate input. +*/ +LWCOLLECTION* +lwmpoint_clip_to_ordinate_range(const LWMPOINT *mpoint, char ordinate, double from, double to) +{ + LWCOLLECTION *lwgeom_out = NULL; + char hasz, hasm; + int i; + + /* Nothing to do with NULL */ + if ( ! mpoint ) + lwerror("Null input geometry."); + + /* Ensure 'from' is less than 'to'. */ + if ( to < from ) + { + double t = from; + from = to; + to = t; + } + + /* Read Z/M info */ + hasz = lwgeom_has_z(lwmpoint_as_lwgeom(mpoint)); + hasm = lwgeom_has_m(lwmpoint_as_lwgeom(mpoint)); + + /* Prepare return object */ + lwgeom_out = lwcollection_construct_empty(MULTIPOINTTYPE, mpoint->srid, hasz, hasm); + + /* For each point, is its ordinate value between from and to? */ + for ( i = 0; i < mpoint->ngeoms; i ++ ) + { + POINT4D p4d; + double ordinate_value; + + lwpoint_getPoint4d_p(mpoint->geoms[i], &p4d); + ordinate_value = lwpoint_get_ordinate(&p4d, ordinate); + + if ( from <= ordinate_value && to >= ordinate_value ) + { + LWPOINT *lwp = lwpoint_clone(mpoint->geoms[i]); + lwcollection_add_lwgeom(lwgeom_out, lwpoint_as_lwgeom(lwp)); + } + } + + /* Set the bbox */ + lwgeom_drop_bbox((LWGEOM*)lwgeom_out); + lwgeom_add_bbox((LWGEOM*)lwgeom_out); + + return lwgeom_out; +} + /** * Clip an input MULTILINESTRING between two values, on any ordinate input. */ @@ -650,8 +751,12 @@ lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, do return lwline_clip_to_ordinate_range((LWLINE*)lwin, ordinate, from, to); case MULTILINETYPE: return lwmline_clip_to_ordinate_range((LWMLINE*)lwin, ordinate, from, to); + case MULTIPOINTTYPE: + return lwmpoint_clip_to_ordinate_range((LWMPOINT*)lwin, ordinate, from, to); + case POINTTYPE: + return lwpoint_clip_to_ordinate_range((LWPOINT*)lwin, ordinate, from, to); default: - lwerror("This function only accepts LINESTRING or MULTILINESTRING as arguments."); + lwerror("This function does not accept %s geometries.", lwtype_name(lwin->type)); } return NULL; -- 2.40.0