31 #include "../postgis_config.h" 33 #include "lwgeom_pg.h" 46 double start_measure = PG_GETARG_FLOAT8(1);
47 double end_measure = PG_GETARG_FLOAT8(2);
54 lwpgerror(
"Only LINESTRING and MULTILINESTRING are supported");
72 PG_RETURN_POINTER(gout);
86 LWGEOM *lwin = NULL, *lwout = NULL;
87 double measure = PG_GETARG_FLOAT8(1);
88 double offset = PG_GETARG_FLOAT8(2);;
93 PG_FREE_IF_COPY(gin, 0);
101 PG_RETURN_POINTER(gout);
113 double from = PG_GETARG_FLOAT8(1);
114 double to = PG_GETARG_FLOAT8(2);
115 double offset = PG_GETARG_FLOAT8(3);
118 static char ordinate =
'M';
122 elog(ERROR,
"This function only accepts geometries that have an M dimension.");
129 PG_RETURN_DATUM(DirectFunctionCall3(
ST_LocateAlong, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), PG_GETARG_DATUM(3)));
135 PG_FREE_IF_COPY(geom_in, 0);
139 elog(ERROR,
"lwline_clip_to_ordinate_range returned null");
154 double from = PG_GETARG_FLOAT8(1);
155 double to = PG_GETARG_FLOAT8(2);
158 static char ordinate =
'Z';
159 static double offset = 0.0;
163 elog(ERROR,
"This function only accepts LINESTRING or MULTILINESTRING with Z dimensions.");
170 PG_FREE_IF_COPY(geom_in, 0);
174 elog(ERROR,
"lwline_clip_to_ordinate_range returned null");
186 GSERIALIZED *gser_line = PG_GETARG_GSERIALIZED_P(0);
187 GSERIALIZED *gser_point = PG_GETARG_GSERIALIZED_P(1);
193 elog(ERROR,
"ST_InterpolatePoint: 1st argument isn't a line");
198 elog(ERROR,
"ST_InterpolatePoint: 2st argument isn't a point");
206 elog(ERROR,
"ST_InterpolatePoint only accepts geometries that have an M dimension");
231 elog(ERROR,
"line_locate_point: 1st arg isn't a line");
236 elog(ERROR,
"line_locate_point: 2st arg isn't a point");
250 PG_RETURN_FLOAT8(ret);
274 LWGEOM *lwin,
double m0,
double m1);
277 LWLINE *lwline_in,
double m0,
double m1);
280 LWPOINT *lwpoint,
double m0,
double m1);
305 double dM0, dM1, dX, dY, dZ;
310 POSTGIS_DEBUGF(3,
"m0: %g m1: %g", m0, m1);
313 if ( p1->
m == p2->
m )
316 if ( p1->
m < m0 || p1->
m > m1 )
338 if ( p2->
m < m0 || p1->
m > m1 )
345 if ( p1->
m >= m0 && p2->
m <= m1 )
358 dM0=(m0-p1->
m)/(p2->
m-p1->
m);
359 dM1=(m1-p2->
m)/(p2->
m-p1->
m);
364 POSTGIS_DEBUGF(3,
"dM0:%g dM1:%g", dM0, dM1);
365 POSTGIS_DEBUGF(3,
"dX:%g dY:%g dZ:%g", dX, dY, dZ);
366 POSTGIS_DEBUGF(3,
"swapped: %d", swapped);
378 if (m0 == m1 && p2->
m <= m1)
380 memcpy(p1, p2,
sizeof(
POINT4D));
382 POSTGIS_DEBUG(3,
"Projected p1 on range (as copy of p2)");
392 POSTGIS_DEBUG(3,
"Projected p1 on range");
395 if ( swapped ) ret |= 0x0100;
409 if (m0 == m1 && p1->
m >= m0)
411 memcpy(p2, p1,
sizeof(
POINT4D));
413 POSTGIS_DEBUG(3,
"Projected p2 on range (as copy of p1)");
423 POSTGIS_DEBUG(3,
"Projected p2 on range");
426 if ( swapped ) ret |= 0x0010;
453 POSTGIS_DEBUGF(2,
"ptarray_locate...: called for pointarray %p, m0:%g, m1:%g",
465 POSTGIS_DEBUGF(3,
" segment %d-%d [ %g %g %g %g - %g %g %g %g ]",
467 p1.
x, p1.
y, p1.
z, p1.
m,
468 p2.
x, p2.
y, p2.
z, p2.
m);
473 if (! clipval )
continue;
475 POSTGIS_DEBUGF(3,
" clipped to: [ %g %g %g %g - %g %g %g %g ] clipval: %d", p1.
x, p1.
y, p1.
z, p1.
m,
476 p2.
x, p2.
y, p2.
z, p2.
m, clipval);
482 POSTGIS_DEBUGF(3,
" 1 creating new POINTARRAY with first point %g,%g,%g,%g", p1.
x, p1.
y, p1.
z, p1.
m);
495 if ( clipval & 0x0100 || i == ipa->
npoints-1 )
497 POSTGIS_DEBUGF(3,
" closing pointarray %p with %d points", dpa, dpa->
npoints);
508 if ( dpa != NULL ) lwpgerror(
"Something wrong with algorithm");
523 POSTGIS_DEBUGF(2,
"lwpoint_locate_between called for lwpoint %p", lwpoint);
526 if ( p3dm.
m >= m0 && p3dm.
m <= m1)
528 POSTGIS_DEBUG(3,
" lwpoint... returning a clone of input");
534 POSTGIS_DEBUG(3,
" lwpoint... returning a clone of input");
560 const int pointflag=0x01;
561 const int lineflag=0x10;
564 POSTGIS_DEBUGF(2,
"lwline_locate_between called for lwline %p", lwline_in);
566 POSTGIS_DEBUGF(3,
" ptarray_locate... returned %d pointarrays",
577 for (i=0; i<ngeoms; i++)
588 geoms[i]=(
LWGEOM *)lwpoint;
596 geoms[i]=(
LWGEOM *)lwline;
603 lwpgerror(
"ptarray_locate_between_m returned a POINARRAY set containing POINTARRAY with 0 points");
620 lwline_in->
srid, NULL, ngeoms, geoms);
635 POSTGIS_DEBUGF(2,
"lwcollection_locate_between_m called for lwcoll %p", lwcoll);
638 for (i=0; i<lwcoll->
ngeoms; i++)
643 geoms[ngeoms++] = sub;
646 if ( ngeoms == 0 )
return NULL;
649 lwcoll->
srid, NULL, ngeoms, geoms);
664 POSTGIS_DEBUGF(2,
"lwgeom_locate_between called for lwgeom %p", lwin);
684 lwpgerror(
"Areal geometries are not supported by locate_between_measures");
688 lwpgerror(
"Unkonwn geometry type (%s:%d)", __FILE__, __LINE__);
706 double start_measure = PG_GETARG_FLOAT8(1);
707 double end_measure = PG_GETARG_FLOAT8(2);
713 elog(WARNING,
"ST_Locate_Between_Measures and ST_Locate_Along_Measure were deprecated in 2.2.0. Please use ST_LocateAlong and ST_LocateBetween");
715 if ( end_measure < start_measure )
717 lwpgerror(
"locate_between_m: 2nd arg must be bigger then 1st arg");
726 lwpgerror(
"Geometry argument does not have an 'M' ordinate");
738 lwpgerror(
"Areal or Collection types are not supported");
745 start_measure, end_measure);
758 PG_RETURN_POINTER(gout);
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area...
LWLINE * lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end)
Add a measure dimension to a line, interpolating linearly from the start to the end value...
static POINTARRAYSET ptarray_locate_between_m(POINTARRAY *ipa, double m0, double m1)
static LWGEOM * lwcollection_locate_between_m(LWCOLLECTION *lwcoll, double m0, double m1)
PG_FUNCTION_INFO_V1(ST_AddMeasure)
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_has_m(const GSERIALIZED *gser)
Check if a GSERIALIZED has an M ordinate.
Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS)
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
void lwgeom_free(LWGEOM *geom)
Datum ST_LocateBetween(PG_FUNCTION_ARGS)
Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS)
void error_if_srid_mismatch(int srid1, int srid2)
Datum ST_InterpolatePoint(PG_FUNCTION_ARGS)
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
static LWGEOM * lwline_locate_between_m(LWLINE *lwline_in, double m0, double m1)
double lwgeom_interpolate_point(const LWGEOM *lwin, const LWPOINT *lwpt)
Find the measure value at the location on the line closest to the point.
static LWGEOM * lwgeom_locate_between_m(LWGEOM *lwin, double m0, double m1)
double ptarray_locate_point(const POINTARRAY *pa, const POINT4D *pt, double *dist, POINT4D *p_located)
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE, then a duplicate point will not be added.
Datum ST_LocateAlong(PG_FUNCTION_ARGS)
LWPOINT * lwpoint_clone(const LWPOINT *lwgeom)
#define LW_TRUE
Return types for functions with status returns.
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
static LWGEOM * lwpoint_locate_between_m(LWPOINT *lwpoint, double m0, double m1)
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
LWCOLLECTION * lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, double to, double offset)
Given a geometry clip based on the from/to range of one of its ordinates (x, y, z, m).
LWMLINE * lwmline_measured_from_lwmline(const LWMLINE *lwmline, double m_start, double m_end)
Re-write the measure ordinate (or add one, if it isn't already there) interpolating the measure betwe...
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
LWGEOM * lwgeom_locate_along(const LWGEOM *lwin, double m, double offset)
Determine the location(s) along a measured line where m occurs and return as a multipoint.
Datum LWGEOM_line_locate_point(PG_FUNCTION_ARGS)
int lwpoint_getPoint3dm_p(const LWPOINT *point, POINT3DM *out)
Datum ST_AddMeasure(PG_FUNCTION_ARGS)
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
#define FLAGS_GET_M(flags)
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
void * lwalloc(size_t size)
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
static int clip_seg_by_m_range(POINT4D *p1, POINT4D *p2, double m0, double m1)
This library is the generic geometry handling section of PostGIS.