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);
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 )
422 lwerror(
"Null input geometry.");
440 for ( i = 0; i < mpoint->
ngeoms; i ++ )
443 double ordinate_value;
448 if ( from <= ordinate_value && to >= ordinate_value )
456 if ( lwgeom_out->
bbox )
474 lwerror(
"Null input geometry.");
488 char homogeneous = 1;
489 size_t geoms_size = 0;
493 for ( i = 0; i < mline->
ngeoms; i ++ )
502 if ( lwgeom_out->
geoms )
511 for ( j = 0; j < col->
ngeoms; j++ )
526 if ( lwgeom_out->
bbox )
554 int added_last_point = 0;
555 POINT4D *p = NULL, *q = NULL, *
r = NULL;
556 double ordinate_value_p = 0.0, ordinate_value_q = 0.0;
559 #if POSTGIS_DEBUG_LEVEL >= 4
566 lwerror(
"Null input geometry.");
581 #if POSTGIS_DEBUG_LEVEL >= 4
582 LWDEBUGF(4,
"from = %g, to = %g, ordinate = %c", from, to, ordinate);
589 if ( (ordinate ==
'Z' && ! hasz) || (ordinate ==
'M' && ! hasm) )
591 lwerror(
"Cannot clip on ordinate %d in a %d-d geometry.", ordinate, dims);
606 for ( i = 0; i < pa_in->
npoints; i++ )
609 LWDEBUGF(4,
"added_last_point %d", added_last_point);
613 ordinate_value_q = ordinate_value_p;
617 LWDEBUGF(4,
" ordinate_value_p %g (current)", ordinate_value_p);
618 LWDEBUGF(4,
" ordinate_value_q %g (previous)", ordinate_value_q);
621 if ( ordinate_value_p >= from && ordinate_value_p <= to )
623 LWDEBUGF(4,
" inside ordinate range (%g, %g)", from, to);
625 if ( ! added_last_point )
627 LWDEBUG(4,
" new ptarray required");
637 ( ordinate_value_p > from && ordinate_value_p < to ) ||
638 ( ordinate_value_p == from && ordinate_value_q > to ) ||
639 ( ordinate_value_p == to && ordinate_value_q < from ) ) )
641 double interpolation_value;
642 (ordinate_value_q > to) ? (interpolation_value = to) : (interpolation_value = from);
645 LWDEBUGF(4,
"[0] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
650 if ( ordinate_value_p == from || ordinate_value_p == to )
652 added_last_point = 2;
656 added_last_point = 1;
662 LWDEBUGF(4,
" added_last_point (%d)", added_last_point);
663 if ( added_last_point == 1 )
667 double interpolation_value;
668 (ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
671 LWDEBUGF(4,
" [1] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
673 else if ( added_last_point == 2 )
679 (ordinate_value_q == from && ordinate_value_p > from) ||
680 (ordinate_value_q == to && ordinate_value_p < to) ) )
682 double interpolation_value;
683 (ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
686 LWDEBUGF(4,
" [2] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
689 else if ( i && ordinate_value_q < from && ordinate_value_p > to )
701 else if ( i && ordinate_value_q > to && ordinate_value_p < from )
716 LWDEBUG(4,
"saving pointarray to multi-line (1)");
736 added_last_point = 0;
744 LWDEBUG(4,
"saving pointarray to multi-line (2)");
768 if ( lwgeom_out->
bbox && lwgeom_out->
ngeoms > 0 )
785 lwerror(
"lwgeom_clip_to_ordinate_range: null input geometry!");
787 switch ( lwin->
type )
807 if ( out_col == NULL )
808 lwerror(
"lwgeom_clip_to_ordinate_range clipping routine returned NULL");
820 for ( i = 0; i < out_col->
ngeoms; i++ )
825 lwnotice(
"lwgeom_clip_to_ordinate_range cannot offset a clipped point");
834 lwerror(
"lwgeom_offsetcurve returned null");
840 lwerror(
"lwgeom_clip_to_ordinate_range found an unexpected type (%s) in the offset routine",
lwtype_name(
type));
851 lwerror(
"Input geometry does not have a measure dimension");
863 lwerror(
"lwgeom_interpolate_point: null input geometry!");
866 lwerror(
"Input geometry does not have a measure dimension");
869 lwerror(
"Input geometry is empty");
871 switch ( lwin->
type )
914 double t0,
double t1)
931 pv.
x = ( p1->
x - p0->
x );
932 pv.
y = ( p1->
y - p0->
y );
933 pv.
z = ( p1->
z - p0->
z );
937 qv.
x = ( q1->
x - q0->
x );
938 qv.
y = ( q1->
y - q0->
y );
939 qv.
z = ( q1->
z - q0->
z );
947 double dv2 =
DOT(dv,dv);
957 w0.
x = ( p0->
x - q0->
x );
958 w0.
y = ( p0->
y - q0->
y );
959 w0.
z = ( p0->
z - q0->
z );
966 double t = -
DOT(w0,dv) / dv2;
991 t = t0 + (t1 - t0) * t;
1005 if ( pbuf.
m >= tmin && pbuf.
m <= tmax )
1006 mvals[n++] = pbuf.
m;
1014 double a = *((
double *)pa);
1015 double b = *((
double *)pb);
1029 for (i=1; i<nvals; ++i)
1032 if ( vals[i] != vals[last] )
1034 vals[++last] = vals[i];
1063 for ( i = from+1; i < pa->
npoints; i++ )
1086 double mindist2 = FLT_MAX;
1090 lwerror(
"Both input geometries must have a measure dimension");
1099 lwerror(
"Both input geometries must be linestrings");
1105 lwerror(
"Both input lines must have at least 2 points");
1125 LWDEBUG(1,
"Inputs never exist at the same time");
1135 mvals =
lwalloc(
sizeof(
double) *
1146 nmvals =
uniq(mvals, nmvals);
1152 double t0 = mvals[0];
1154 LWDEBUGF(1,
"Inputs only exist both at a single time (%g)", t0);
1160 lwerror(
"Could not find point with M=%g on first geom", t0);
1166 lwerror(
"Could not find point with M=%g on second geom", t0);
1181 for (i=1; i<nmvals; ++i)
1183 double t0 = mvals[i-1];
1184 double t1 = mvals[i];
1193 if ( -1 == seg )
continue;
1197 if ( -1 == seg )
continue;
1201 if ( -1 == seg )
continue;
1205 if ( -1 == seg )
continue;
1216 dist2 = ( q0.
x - p0.
x ) * ( q0.
x - p0.
x ) +
1217 ( q0.
y - p0.
y ) * ( q0.
y - p0.
y ) +
1218 ( q0.
z - p0.
z ) * ( q0.
z - p0.
z );
1219 if ( dist2 < mindist2 )
1235 *mindist = sqrt(mindist2);
1251 double maxdist2 = maxdist * maxdist;
1256 lwerror(
"Both input geometries must have a measure dimension");
1265 lwerror(
"Both input geometries must be linestrings");
1272 lwerror(
"Both input lines must have at least 2 points");
1292 LWDEBUG(1,
"Inputs never exist at the same time");
1300 mvals =
lwalloc(
sizeof(
double) *
1311 nmvals =
uniq(mvals, nmvals);
1316 double t0 = mvals[0];
1318 LWDEBUGF(1,
"Inputs only exist both at a single time (%g)", t0);
1321 lwnotice(
"Could not find point with M=%g on first geom", t0);
1326 lwnotice(
"Could not find point with M=%g on second geom", t0);
1339 for (i=1; i<nmvals; ++i)
1341 double t0 = mvals[i-1];
1342 double t1 = mvals[i];
1343 #if POSTGIS_DEBUG_LEVEL >= 1
1353 if ( -1 == seg )
continue;
1357 if ( -1 == seg )
continue;
1361 if ( -1 == seg )
continue;
1365 if ( -1 == seg )
continue;
1368 #if POSTGIS_DEBUG_LEVEL >= 1
1379 dist2 = ( q0.
x - p0.
x ) * ( q0.
x - p0.
x ) +
1380 ( q0.
y - p0.
y ) * ( q0.
y - p0.
y ) +
1381 ( q0.
z - p0.
z ) * ( q0.
z - p0.
z );
1382 if ( dist2 <= maxdist2 )
1384 LWDEBUGF(1,
"Within distance %g at time %g, breaking", sqrt(dist2), t);
void lwgeom_refresh_bbox(LWGEOM *lwgeom)
Drop current bbox and calculate a fresh one.
int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
void lwmpoint_free(LWMPOINT *mpt)
double lwpoint_get_m(const LWPOINT *point)
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
LWGEOM * lwmline_as_lwgeom(const LWMLINE *obj)
LWGEOM * lwgeom_offsetcurve(const LWGEOM *geom, double size, int quadsegs, int joinStyle, double mitreLimit)
LWGEOM * lwmpoint_as_lwgeom(const LWMPOINT *obj)
double ptarray_locate_point(const POINTARRAY *pa, const POINT4D *pt, double *dist, POINT4D *p_located)
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...
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
LWMPOINT * lwmpoint_add_lwpoint(LWMPOINT *mobj, const LWPOINT *obj)
double distance3d_pt_pt(const POINT3D *p1, const POINT3D *p2)
void * lwrealloc(void *mem, size_t size)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
#define FLAGS_NDIMS(flags)
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
void ptarray_free(POINTARRAY *pa)
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...
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,...
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
LWMPOINT * lwmpoint_construct_empty(int srid, char hasz, char hasm)
void * lwalloc(size_t size)
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.
LWMPOINT * lwmpoint_construct(int srid, const POINTARRAY *pa)
#define LW_TRUE
Return types for functions with status returns.
#define FLAGS_SET_M(flags, value)
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
#define FLAGS_SET_Z(flags, value)
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
void lwline_free(LWLINE *line)
LWPOINT * lwpoint_clone(const LWPOINT *lwgeom)
int p4d_same(const POINT4D *p1, const POINT4D *p2)
int lwpoint_is_empty(const LWPOINT *point)
int ptarray_has_z(const POINTARRAY *pa)
int ptarray_has_m(const POINTARRAY *pa)
#define LWDEBUG(level, msg)
#define LWDEBUGF(level, msg,...)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
void lwpoint_set_ordinate(POINT4D *p, char ordinate, double value)
Given a point, ordinate number and value, set that ordinate on the point.
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.
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.
static LWMPOINT * lwmline_locate_along(const LWMLINE *lwmline, double m, double offset)
double lwpoint_get_ordinate(const POINT4D *p, char ordinate)
Given a POINT4D and an ordinate number, return the value of the ordinate.
static int segment_locate_along(const POINT4D *p1, const POINT4D *p2, double m, double offset, POINT4D *pn)
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...
static LWMPOINT * lwpoint_locate_along(const LWPOINT *lwpoint, double m, __attribute__((__unused__)) double offset)
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 int ptarray_collect_mvals(const POINTARRAY *pa, double tmin, double tmax, double *mvals)
double lwgeom_tcpa(const LWGEOM *g1, const LWGEOM *g2, double *mindist)
Find the time of closest point of approach.
static int compare_double(const void *pa, const void *pb)
static double segments_tcpa(POINT4D *p0, const POINT4D *p1, POINT4D *q0, const POINT4D *q1, double t0, double t1)
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,...
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.
static int ptarray_locate_along_linear(const POINTARRAY *pa, double m, POINT4D *p, uint32_t from)
static int uniq(double *vals, int nvals)
static POINTARRAY * ptarray_locate_along(const POINTARRAY *pa, double m, double offset)
static LWMPOINT * lwmpoint_locate_along(const LWMPOINT *lwin, double m, __attribute__((__unused__)) double offset)
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 * 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.
static LWMPOINT * lwline_locate_along(const LWLINE *lwline, double m, double offset)
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.
int lwgeom_cpa_within(const LWGEOM *g1, const LWGEOM *g2, double maxdist)
Is the closest point of approach within a distance ?