57 mprop = (m - m1) / (m2 - m1);
61 pn->
x = p1->
x + (p2->
x - p1->
x) * mprop;
62 pn->
y = p1->
y + (p2->
y - p1->
y) * mprop;
63 pn->
z = p1->
z + (p2->
z - p1->
z) * mprop;
69 double theta = atan2(p2->
y - p1->
y, p2->
x - p1->
x);
70 pn->
x -= sin(theta) * offset;
71 pn->
y += cos(theta) * offset;
86 if ( ! pa || pa->
npoints < 2 )
return NULL;
89 for ( i = 1; i < pa->
npoints; i++ )
115 int hasz, hasm, srid;
118 if ( ! lwline )
return NULL;
155 if ( (!lwmline) || (lwmline->
ngeoms < 1) )
return NULL;
161 for ( i = 0; i < lwmline->
ngeoms; i++ )
168 for ( j = 0; j < along->ngeoms; j++ )
204 for ( i = 0; i < lwin->
ngeoms; i++ )
219 if ( ! lwin )
return NULL;
222 lwerror(
"Input geometry does not have a measure dimension");
255 lwerror(
"Null input geometry.");
259 if ( ! ( ordinate ==
'X' || ordinate ==
'Y' || ordinate ==
'Z' || ordinate ==
'M' ) )
261 lwerror(
"Cannot extract %c ordinate.", ordinate);
265 if ( ordinate ==
'X' )
267 if ( ordinate ==
'Y' )
269 if ( ordinate ==
'Z' )
271 if ( ordinate ==
'M' )
287 lwerror(
"Null input geometry.");
291 if ( ! ( ordinate ==
'X' || ordinate ==
'Y' || ordinate ==
'Z' || ordinate ==
'M' ) )
293 lwerror(
"Cannot set %c ordinate.", ordinate);
297 LWDEBUGF(4,
" setting ordinate %c to %g", ordinate, value);
323 static char* dims =
"XYZM";
329 if ( ! ( ordinate ==
'X' || ordinate ==
'Y' || ordinate ==
'Z' || ordinate ==
'M' ) )
331 lwerror(
"Cannot set %c ordinate.", ordinate);
335 if (
FP_MIN(p1_value, p2_value) > interpolation_value ||
336 FP_MAX(p1_value, p2_value) < interpolation_value )
338 lwerror(
"Cannot interpolate to a value (%g) not between the input points (%g, %g).", interpolation_value, p1_value, p2_value);
342 proportion = fabs((interpolation_value - p1_value) / (p2_value - p1_value));
344 for ( i = 0; i < 4; i++ )
346 double newordinate = 0.0;
347 if ( dims[i] ==
'Z' && ! hasz )
continue;
348 if ( dims[i] ==
'M' && ! hasm )
continue;
351 newordinate = p1_value + proportion * (p2_value - p1_value);
353 LWDEBUGF(4,
" clip ordinate(%c) p1_value(%g) p2_value(%g) proportion(%g) newordinate(%g) ", dims[i], p1_value, p2_value, proportion, newordinate );
369 double ordinate_value;
373 lwerror(
"Null input geometry.");
393 if ( from <= ordinate_value && to >= ordinate_value )
400 if ( lwgeom_out->
bbox )
423 lwerror(
"Null input geometry.");
441 for ( i = 0; i < mpoint->
ngeoms; i ++ )
444 double ordinate_value;
449 if ( from <= ordinate_value && to >= ordinate_value )
457 if ( lwgeom_out->
bbox )
476 lwerror(
"Null input geometry.");
490 char homogeneous = 1;
491 size_t geoms_size = 0;
495 for ( i = 0; i < mline->
ngeoms; i ++ )
504 if ( lwgeom_out->
geoms )
513 for ( j = 0; j < col->
ngeoms; j++ )
528 if ( lwgeom_out->
bbox )
557 int added_last_point = 0;
558 POINT4D *p = NULL, *q = NULL, *
r = NULL;
559 double ordinate_value_p = 0.0, ordinate_value_q = 0.0;
567 lwerror(
"Null input geometry.");
579 LWDEBUGF(4,
"from = %g, to = %g, ordinate = %c", from, to, ordinate);
583 if ( (ordinate ==
'Z' && ! hasz) || (ordinate ==
'M' && ! hasm) )
585 lwerror(
"Cannot clip on ordinate %d in a %d-d geometry.", ordinate, dims);
598 pa_in = line->points;
600 for ( i = 0; i < pa_in->
npoints; i++ )
603 LWDEBUGF(4,
"added_last_point %d", added_last_point);
607 ordinate_value_q = ordinate_value_p;
611 LWDEBUGF(4,
" ordinate_value_p %g (current)", ordinate_value_p);
612 LWDEBUGF(4,
" ordinate_value_q %g (previous)", ordinate_value_q);
615 if ( ordinate_value_p >= from && ordinate_value_p <= to )
617 LWDEBUGF(4,
" inside ordinate range (%g, %g)", from, to);
619 if ( ! added_last_point )
621 LWDEBUG(4,
" new ptarray required");
631 ( ordinate_value_p > from && ordinate_value_p < to ) ||
632 ( ordinate_value_p == from && ordinate_value_q > to ) ||
633 ( ordinate_value_p == to && ordinate_value_q < from ) ) )
635 double interpolation_value;
636 (ordinate_value_q > to) ? (interpolation_value = to) : (interpolation_value = from);
639 LWDEBUGF(4,
"[0] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
644 if ( ordinate_value_p == from || ordinate_value_p == to )
646 added_last_point = 2;
650 added_last_point = 1;
656 LWDEBUGF(4,
" added_last_point (%d)", added_last_point);
657 if ( added_last_point == 1 )
661 double interpolation_value;
662 (ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
665 LWDEBUGF(4,
" [1] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
667 else if ( added_last_point == 2 )
673 (ordinate_value_q == from && ordinate_value_p > from) ||
674 (ordinate_value_q == to && ordinate_value_p < to) ) )
676 double interpolation_value;
677 (ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
680 LWDEBUGF(4,
" [2] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
683 else if ( i && ordinate_value_q < from && ordinate_value_p > to )
695 else if ( i && ordinate_value_q > to && ordinate_value_p < from )
710 LWDEBUG(4,
"saving pointarray to multi-line (1)");
730 added_last_point = 0;
738 LWDEBUG(4,
"saving pointarray to multi-line (2)");
762 if ( lwgeom_out->
bbox && lwgeom_out->
ngeoms > 0 )
780 lwerror(
"lwgeom_clip_to_ordinate_range: null input geometry!");
782 switch ( lwin->
type )
802 if ( out_col == NULL )
803 lwerror(
"lwgeom_clip_to_ordinate_range clipping routine returned NULL");
814 for ( i = 0; i < out_col->
ngeoms; i++ )
819 lwnotice(
"lwgeom_clip_to_ordinate_range cannot offset a clipped point");
828 lwerror(
"lwgeom_offsetcurve returned null");
834 lwerror(
"lwgeom_clip_to_ordinate_range found an unexpected type (%s) in the offset routine",
lwtype_name(type));
845 lwerror(
"Input geometry does not have a measure dimension");
857 lwerror(
"lwgeom_interpolate_point: null input geometry!");
860 lwerror(
"Input geometry does not have a measure dimension");
863 lwerror(
"Input geometry is empty");
865 switch ( lwin->
type )
908 double t0,
double t1)
925 pv.
x = ( p1->
x - p0->
x );
926 pv.
y = ( p1->
y - p0->
y );
927 pv.
z = ( p1->
z - p0->
z );
931 qv.
x = ( q1->
x - q0->
x );
932 qv.
y = ( q1->
y - q0->
y );
933 qv.
z = ( q1->
z - q0->
z );
941 double dv2 =
DOT(dv,dv);
951 w0.
x = ( p0->
x - q0->
x );
952 w0.
y = ( p0->
y - q0->
y );
953 w0.
z = ( p0->
z - q0->
z );
960 double t = -
DOT(w0,dv) / dv2;
985 t = t0 + (t1 - t0) * t;
999 if ( pbuf.
m >= tmin && pbuf.
m <= tmax )
1000 mvals[n++] = pbuf.
m;
1008 double a = *((
double *)pa);
1009 double b = *((
double *)pb);
1023 for (i=1; i<nvals; ++i)
1026 if ( vals[i] != vals[last] )
1028 vals[++last] = vals[i];
1057 for ( i = from+1; i < pa->
npoints; i++ )
1080 double mindist2 = FLT_MAX;
1084 lwerror(
"Both input geometries must have a measure dimension");
1093 lwerror(
"Both input geometries must be linestrings");
1099 lwerror(
"Both input lines must have at least 2 points");
1119 LWDEBUG(1,
"Inputs never exist at the same time");
1129 mvals =
lwalloc(
sizeof(
double) *
1140 nmvals =
uniq(mvals, nmvals);
1146 double t0 = mvals[0];
1148 LWDEBUGF(1,
"Inputs only exist both at a single time (%g)", t0);
1154 lwerror(
"Could not find point with M=%g on first geom", t0);
1160 lwerror(
"Could not find point with M=%g on second geom", t0);
1175 for (i=1; i<nmvals; ++i)
1177 double t0 = mvals[i-1];
1178 double t1 = mvals[i];
1187 if ( -1 == seg )
continue;
1191 if ( -1 == seg )
continue;
1195 if ( -1 == seg )
continue;
1199 if ( -1 == seg )
continue;
1210 dist2 = ( q0.
x - p0.
x ) * ( q0.
x - p0.
x ) +
1211 ( q0.
y - p0.
y ) * ( q0.
y - p0.
y ) +
1212 ( q0.
z - p0.
z ) * ( q0.
z - p0.
z );
1213 if ( dist2 < mindist2 )
1229 *mindist = sqrt(mindist2);
1245 double maxdist2 = maxdist * maxdist;
1250 lwerror(
"Both input geometries must have a measure dimension");
1259 lwerror(
"Both input geometries must be linestrings");
1266 lwerror(
"Both input lines must have at least 2 points");
1286 LWDEBUG(1,
"Inputs never exist at the same time");
1294 mvals =
lwalloc(
sizeof(
double) *
1305 nmvals =
uniq(mvals, nmvals);
1310 double t0 = mvals[0];
1312 LWDEBUGF(1,
"Inputs only exist both at a single time (%g)", t0);
1315 lwnotice(
"Could not find point with M=%g on first geom", t0);
1320 lwnotice(
"Could not find point with M=%g on second geom", t0);
1333 for (i=1; i<nmvals; ++i)
1335 double t0 = mvals[i-1];
1336 double t1 = mvals[i];
1337 #if POSTGIS_DEBUG_LEVEL >= 1 1347 if ( -1 == seg )
continue;
1351 if ( -1 == seg )
continue;
1355 if ( -1 == seg )
continue;
1359 if ( -1 == seg )
continue;
1362 #if POSTGIS_DEBUG_LEVEL >= 1 1373 dist2 = ( q0.
x - p0.
x ) * ( q0.
x - p0.
x ) +
1374 ( q0.
y - p0.
y ) * ( q0.
y - p0.
y ) +
1375 ( q0.
z - p0.
z ) * ( q0.
z - p0.
z );
1376 if ( dist2 <= maxdist2 )
1378 LWDEBUGF(1,
"Within distance %g at time %g, breaking", sqrt(dist2), t);
void ptarray_set_point4d(POINTARRAY *pa, int n, const POINT4D *p4d)
double lwgeom_interpolate_point(const LWGEOM *lwin, const LWPOINT *lwpt)
Find the measure value at the location on the line closest to the point.
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...
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
double lwpoint_get_ordinate(const POINT4D *p, char ordinate)
Given a POINT4D and an ordinate number, return the value of the ordinate.
LWCOLLECTION * lwpoint_clip_to_ordinate_range(const LWPOINT *point, char ordinate, double from, double to)
Clip an input POINT between two values, on any ordinate input.
LWCOLLECTION * lwmpoint_clip_to_ordinate_range(const LWMPOINT *mpoint, char ordinate, double from, double to)
Clip an input MULTIPOINT between two values, on any ordinate input.
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
static LWMPOINT * lwline_locate_along(const LWLINE *lwline, double m, double offset)
static int segment_locate_along(const POINT4D *p1, const POINT4D *p2, double m, double offset, POINT4D *pn)
static int uniq(double *vals, int nvals)
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
void ptarray_free(POINTARRAY *pa)
static int compare_double(const void *pa, const void *pb)
LWMPOINT * lwmpoint_construct(int srid, const POINTARRAY *pa)
LWGEOM * lwgeom_offsetcurve(const LWLINE *lwline, double size, int quadsegs, int joinStyle, double mitreLimit)
void lwline_free(LWLINE *line)
#define LWDEBUG(level, msg)
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
LWGEOM * lwmline_as_lwgeom(const LWMLINE *obj)
int point_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int hasz, int hasm, char ordinate, double interpolation_value)
Given two points, a dimensionality, an ordinate, and an interpolation value generate a new point that...
LWCOLLECTION * lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to)
Take in a LINESTRING and return a MULTILINESTRING of those portions of the LINESTRING between the fro...
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
static POINTARRAY * ptarray_locate_along(const POINTARRAY *pa, double m, double offset)
void lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
LWCOLLECTION * lwgeom_locate_between(const LWGEOM *lwin, double from, double to, double offset)
Determine the segments along a measured line that fall within the m-range given.
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
Calculate bounding box of a geometry, automatically taking into account whether it is cartesian or ge...
double ptarray_locate_point(const POINTARRAY *pa, const POINT4D *pt, double *dist, POINT4D *p_located)
#define FLAGS_SET_Z(flags, value)
void lwmpoint_free(LWMPOINT *mpt)
static int ptarray_collect_mvals(const POINTARRAY *pa, double tmin, double tmax, double *mvals)
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
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.
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)
void lwpoint_set_ordinate(POINT4D *p, char ordinate, double value)
Given a point, ordinate number and value, set that ordinate on the point.
static LWMPOINT * lwmline_locate_along(const LWMLINE *lwmline, double m, double offset)
static int ptarray_locate_along_linear(const POINTARRAY *pa, double m, POINT4D *p, int from)
int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
LWMPOINT * lwmpoint_construct_empty(int srid, char hasz, char hasm)
LWCOLLECTION * lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to)
Clip an input MULTILINESTRING between two values, on any ordinate input.
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.
double lwgeom_tcpa(const LWGEOM *g1, const LWGEOM *g2, double *mindist)
Find the time of closest point of approach.
double lwpoint_get_m(const LWPOINT *point)
int lwgeom_cpa_within(const LWGEOM *g1, const LWGEOM *g2, double maxdist)
Is the closest point of approach within a distance ?
int ptarray_has_m(const POINTARRAY *pa)
static LWMPOINT * lwmpoint_locate_along(const LWMPOINT *lwin, double m, double offset)
double distance3d_pt_pt(const POINT3D *p1, const POINT3D *p2)
LWMPOINT * lwmpoint_add_lwpoint(LWMPOINT *mobj, const LWPOINT *obj)
void * lwrealloc(void *mem, size_t size)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
int lwpoint_is_empty(const LWPOINT *point)
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
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).
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
int ptarray_has_z(const POINTARRAY *pa)
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
void * lwalloc(size_t size)
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
#define LWDEBUGF(level, msg,...)
#define FLAGS_NDIMS(flags)
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
static double segments_tcpa(POINT4D *p0, const POINT4D *p1, POINT4D *q0, const POINT4D *q1, double t0, double t1)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
int p4d_same(const POINT4D *p1, const POINT4D *p2)
static LWMPOINT * lwpoint_locate_along(const LWPOINT *lwpoint, double m, double offset)
#define FLAGS_SET_M(flags, value)
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
LWGEOM * lwmpoint_as_lwgeom(const LWMPOINT *obj)