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:
Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS);
-Datum ST_AddMeasure(PG_FUNCTION_ARGS);
typedef struct
{
/*
-* 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)
{
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);
}
---\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