]> granicus.if.org Git - postgis/commitdiff
Bind ST_LocateAlong() to the new LRS function that supports offsets.
authorPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 10 Jan 2012 23:14:28 +0000 (23:14 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 10 Jan 2012 23:14:28 +0000 (23:14 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@8757 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/lwlinearreferencing.c
postgis/lwgeom_functions_lrs.c
postgis/postgis.sql.in.c

index bbe4096ca40ed4596a176897e20426186d7ddb8a..f3c698d0253d0c2e180485a41dda7e7df905812b 100644 (file)
@@ -154,13 +154,29 @@ lwmline_locate_along(const LWMLINE *lwmline, double m, double offset)
        return lwmpoint;
 }
 
+static LWPOINT*
+lwpoint_locate_along(const LWPOINT *lwpoint, double m, double offset)
+{
+       LWGEOM *lwg = lwpoint_as_lwgeom(lwpoint);
+       double point_m = lwpoint_get_m(lwpoint);
+       if ( FP_EQUALS(m, point_m) )
+               return lwpoint_clone(lwpoint);
+       else
+               return lwpoint_construct_empty(lwgeom_get_srid(lwg), lwgeom_has_z(lwg), lwgeom_has_m(lwg));
+}
+
 LWGEOM*
 lwgeom_locate_along(const LWGEOM *lwin, double m, double offset)
 {
        if ( ! lwin ) return NULL;
+
+       if ( ! lwgeom_has_m(lwin) )
+               lwerror("Input geometry does not have a measure dimension");    
        
        switch (lwin->type)
        {
+       case POINTTYPE:
+               return (LWGEOM*)lwpoint_locate_along((LWPOINT*)lwin, m, offset);
        case LINETYPE:
                return (LWGEOM*)lwline_locate_along((LWLINE*)lwin, m, offset);
        case MULTILINETYPE:
index e51f8bb198d8ff5f2bc9bce577d29d487e996ce0..ef7ff6409647c0241590fbf7f01ed5ef57754148 100644 (file)
@@ -18,7 +18,6 @@
 
 
 Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS);
-Datum ST_AddMeasure(PG_FUNCTION_ARGS);
 
 typedef struct
 {
@@ -520,11 +519,11 @@ Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS)
 
 
 /*
-* CREATE OR REPLACE FUNCTION ST_AddMeasure(geometry, float8, float8)
-* RETURNS geometry
-* AS '$libdir/postgis-1.5', 'ST_AddMeasure'
-* LANGUAGE 'C' IMMUTABLE STRICT;
+* Add a measure dimension to a line, interpolating linearly from the
+* start value to the end value.
+* ST_AddMeasure(Geometry, StartMeasure, EndMeasure) returns Geometry
 */
+Datum ST_AddMeasure(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(ST_AddMeasure);
 Datum ST_AddMeasure(PG_FUNCTION_ARGS)
 {
@@ -554,7 +553,37 @@ Datum ST_AddMeasure(PG_FUNCTION_ARGS)
                PG_RETURN_NULL();
 
        gout = geometry_serialize(lwout);
-       lwgeom_release(lwout);
+       lwgeom_free(lwout);
+
+       PG_RETURN_POINTER(gout);
+}
+
+
+/*
+* Locate a point along a feature based on a measure value.
+* ST_LocateAlong(Geometry, Measure, [Offset]) returns Geometry
+*/
+Datum ST_LocateAlong(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(ST_LocateAlong);
+Datum ST_LocateAlong(PG_FUNCTION_ARGS)
+{
+       GSERIALIZED *gin = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       GSERIALIZED *gout;
+       LWGEOM *lwin = NULL, *lwout = NULL;
+       double measure = PG_GETARG_FLOAT8(1);
+       double offset = PG_GETARG_FLOAT8(2);;
+       
+       lwnotice("offset %g",offset);
+       lwin = lwgeom_from_gserialized(gin);
+       lwout = lwgeom_locate_along(lwin, measure, offset);
+       lwgeom_free(lwin);
+       PG_FREE_IF_COPY(gin, 0);
+       
+       if ( ! lwout )
+               PG_RETURN_NULL();
+       
+       gout = geometry_serialize(lwout);
+       lwgeom_free(lwout);
 
        PG_RETURN_POINTER(gout);
 }
index c454925e3fc0f6e02a749300af37c809bc07441f..c6008884cf4e642974f76394bbf7417eff997cdf 100644 (file)
@@ -4512,27 +4512,17 @@ CREATE OR REPLACE FUNCTION ST_WKBToSQL(bytea)
 ---\r
 -- Linear referencing functions\r
 ---\r
-CREATE OR REPLACE FUNCTION ST_LocateBetween(geometry, float8, float8)\r
+CREATE OR REPLACE FUNCTION ST_LocateBetween(Geometry geometry, Measure1 float8, Measure2 float8, Offsets float8 default 0.0)\r
        RETURNS geometry\r
        AS 'MODULE_PATHNAME', 'LWGEOM_locate_between_m'\r
        LANGUAGE 'C' IMMUTABLE STRICT;\r
        \r
-CREATE OR REPLACE FUNCTION ST_LocateAlong(geometry, float8)\r
+CREATE OR REPLACE FUNCTION ST_LocateAlong(Geometry geometry, Measure float8, Offsets float8 default 0.0)\r
        RETURNS geometry\r
-       AS $$ SELECT ST_LocateBetween($1, $2, $2) $$\r
-       LANGUAGE 'sql' IMMUTABLE STRICT;\r
-\r
--- LRS with offset parameter\r
-CREATE OR REPLACE FUNCTION ST_LocateBetween(geometry, float8, float8, float8)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'LWGEOM_locate_between_m'\r
+       AS 'MODULE_PATHNAME', 'ST_LocateAlong'\r
        LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
        \r
--- LRS with offset parameter\r
-CREATE OR REPLACE FUNCTION ST_LocateAlong(geometry, float8, float8)\r
-       RETURNS geometry\r
-       AS $$ SELECT ST_LocateBetween($1, $2, $2) $$\r
-       LANGUAGE 'sql' IMMUTABLE STRICT;\r
 ---------------------------------------------------------------\r
 -- END\r
 ---------------------------------------------------------------\r