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;
89 for (i = 1; i < pa->
npoints; i++)
115 int hasz, hasm, srid;
156 if ((!lwmline) || (lwmline->
ngeoms < 1))
163 for (i = 0; i < lwmline->
ngeoms; i++)
170 for (j = 0; j < along->ngeoms; j++)
206 for (i = 0; i < lwin->
ngeoms; i++)
225 lwerror(
"Input geometry does not have a measure dimension");
259 lwerror(
"Null input geometry.");
274 lwerror(
"Cannot extract %c ordinate.", ordinate);
287 lwerror(
"Null input geometry.");
306 lwerror(
"Cannot set %c ordinate.", ordinate);
322 double interpolation_value)
324 static char *dims =
"XYZM";
330 #if PARANOIA_LEVEL > 0
331 if (!(ordinate ==
'X' || ordinate ==
'Y' || ordinate ==
'Z' || ordinate ==
'M'))
333 lwerror(
"Cannot interpolate over %c ordinate.", ordinate);
337 if (
FP_MIN(p1_value, p2_value) > interpolation_value ||
FP_MAX(p1_value, p2_value) < interpolation_value)
339 lwerror(
"Cannot interpolate to a value (%g) not between the input points (%g, %g).",
347 proportion = (interpolation_value - p1_value) / (p2_value - p1_value);
349 for (i = 0; i < 4; i++)
351 if (dims[i] ==
'Z' && !hasz)
353 if (dims[i] ==
'M' && !hasm)
355 if (dims[i] == ordinate)
359 double newordinate = 0.0;
362 newordinate = p1_value + proportion * (p2_value - p1_value);
379 double ordinate_value;
391 if (from <= ordinate_value && to >= ordinate_value)
418 for (i = 0; i < mpoint->
ngeoms; i++)
421 double ordinate_value;
426 if (from <= ordinate_value && to >= ordinate_value)
463 p1out = (ovp1 < from) ? -1 : ((ovp1 > to) ? 1 : 0);
465 if (from <= ovp1 && ovp1 <= to)
469 for (i = 1; i < ipa->
npoints; i++)
473 p2out = (ovp2 < from) ? -1 : ((ovp2 > to) ? 1 : 0);
475 if (p1out == 0 && p2out == 0)
479 else if (p1out == p2out && p1out != 0)
483 else if (p1out == -1 && p2out == 0)
489 else if (p1out == -1 && p2out == 1)
496 else if (p1out == 0 && p2out == -1)
501 else if (p1out == 0 && p2out == 1)
506 else if (p1out == 1 && p2out == -1)
513 else if (p1out == 1 && p2out == 0)
525 if (is_closed && opa->
npoints > 2)
546 int added_last_point = 0;
547 POINT4D *p = NULL, *q = NULL, *
r = NULL;
548 double ordinate_value_p = 0.0, ordinate_value_q = 0.0;
559 if ((ordinate ==
'Z' && !hasz) || (ordinate ==
'M' && !hasm))
561 lwerror(
"Cannot clip on ordinate %d in a %d-d geometry.", ordinate, dims);
576 for (i = 0; i < pa_in->
npoints; i++)
581 ordinate_value_q = ordinate_value_p;
587 if (ordinate_value_p >= from && ordinate_value_p <= to)
590 if (!added_last_point)
602 (ordinate_value_p > from && ordinate_value_p < to) ||
603 (ordinate_value_p == from && ordinate_value_q > to) ||
604 (ordinate_value_p == to && ordinate_value_q < from)))
606 double interpolation_value;
607 (ordinate_value_q > to) ? (interpolation_value = to)
608 : (interpolation_value = from);
615 if (ordinate_value_p == from || ordinate_value_p == to)
616 added_last_point = 2;
618 added_last_point = 1;
623 if (added_last_point == 1)
627 double interpolation_value;
628 (ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
632 else if (added_last_point == 2)
637 if (from != to && ((ordinate_value_q == from && ordinate_value_p > from) ||
638 (ordinate_value_q == to && ordinate_value_p < to)))
640 double interpolation_value;
641 (ordinate_value_p > to) ? (interpolation_value = to)
642 : (interpolation_value = from);
647 else if (i && ordinate_value_q < from && ordinate_value_p > to)
659 else if (i && ordinate_value_q > to && ordinate_value_p < from)
691 added_last_point = 0;
734 for (uint32_t i = 0; i < poly->
nrings; i++)
770 for (uint32_t i = 1; i < pa->
npoints - 2; i++)
808 for (i = 0; i < icol->
ngeoms; i++)
844 lwerror(
"lwgeom_clip_to_ordinate_range: null input geometry!");
877 lwerror(
"lwgeom_clip_to_ordinate_range clipping routine returned NULL");
888 for (i = 0; i < out_col->
ngeoms; i++)
893 lwnotice(
"lwgeom_clip_to_ordinate_range cannot offset a clipped point");
902 lwerror(
"lwgeom_offsetcurve returned null");
908 lwerror(
"lwgeom_clip_to_ordinate_range found an unexpected type (%s) in the offset routine",
920 lwerror(
"Input geometry does not have a measure dimension");
932 lwerror(
"lwgeom_interpolate_point: null input geometry!");
935 lwerror(
"Input geometry does not have a measure dimension");
938 lwerror(
"Input geometry is empty");
998 pv.
x = (p1->
x - p0->
x);
999 pv.
y = (p1->
y - p0->
y);
1000 pv.
z = (p1->
z - p0->
z);
1004 qv.
x = (q1->
x - q0->
x);
1005 qv.
y = (q1->
y - q0->
y);
1006 qv.
z = (q1->
z - q0->
z);
1014 double dv2 =
DOT(dv, dv);
1024 w0.
x = (p0->
x - q0->
x);
1025 w0.
y = (p0->
y - q0->
y);
1026 w0.
z = (p0->
z - q0->
z);
1033 double t = -
DOT(w0, dv) / dv2;
1058 t = t0 + (t1 - t0) * t;
1069 for (i = 0; i < pa->
npoints; ++i)
1072 if (pbuf.
m >= tmin && pbuf.
m <= tmax)
1073 mvals[n++] = pbuf.
m;
1081 double a = *((
double *)pa);
1082 double b = *((
double *)pb);
1096 for (i = 1; i < nvals; ++i)
1099 if (vals[i] != vals[last])
1101 vals[++last] = vals[i];
1130 for (i = from + 1; i < pa->
npoints; i++)
1153 double mindist2 = FLT_MAX;
1157 lwerror(
"Both input geometries must have a measure dimension");
1166 lwerror(
"Both input geometries must be linestrings");
1172 lwerror(
"Both input lines must have at least 2 points");
1192 LWDEBUG(1,
"Inputs never exist at the same time");
1212 nmvals =
uniq(mvals, nmvals);
1218 double t0 = mvals[0];
1220 LWDEBUGF(1,
"Inputs only exist both at a single time (%g)", t0);
1226 lwerror(
"Could not find point with M=%g on first geom", t0);
1232 lwerror(
"Could not find point with M=%g on second geom", t0);
1247 for (i = 1; i < nmvals; ++i)
1249 double t0 = mvals[i - 1];
1250 double t1 = mvals[i];
1286 dist2 = (q0.
x - p0.
x) * (q0.
x - p0.
x) + (q0.
y - p0.
y) * (q0.
y - p0.
y) + (q0.
z - p0.
z) * (q0.
z - p0.
z);
1287 if (dist2 < mindist2)
1303 *mindist = sqrt(mindist2);
1319 double maxdist2 = maxdist * maxdist;
1324 lwerror(
"Both input geometries must have a measure dimension");
1333 lwerror(
"Both input geometries must be linestrings");
1340 lwerror(
"Both input lines must have at least 2 points");
1360 LWDEBUG(1,
"Inputs never exist at the same time");
1378 nmvals =
uniq(mvals, nmvals);
1383 double t0 = mvals[0];
1385 LWDEBUGF(1,
"Inputs only exist both at a single time (%g)", t0);
1388 lwnotice(
"Could not find point with M=%g on first geom", t0);
1393 lwnotice(
"Could not find point with M=%g on second geom", t0);
1406 for (i = 1; i < nmvals; ++i)
1408 double t0 = mvals[i - 1];
1409 double t1 = mvals[i];
1410 #if POSTGIS_DEBUG_LEVEL >= 1
1439 #if POSTGIS_DEBUG_LEVEL >= 1
1450 dist2 = (q0.
x - p0.
x) * (q0.
x - p0.
x) + (q0.
y - p0.
y) * (q0.
y - p0.
y) + (q0.
z - p0.
z) * (q0.
z - p0.
z);
1451 if (dist2 <= maxdist2)
1453 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)
POINT4D getPoint4d(const POINTARRAY *pa, uint32_t n)
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)
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)
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
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.
#define FLAGS_GET_Z(flags)
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
LWMPOINT * lwmpoint_add_lwpoint(LWMPOINT *mobj, const LWPOINT *obj)
double distance3d_pt_pt(const POINT3D *p1, const POINT3D *p2)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
#define FLAGS_NDIMS(flags)
LWMPOINT * lwmpoint_construct_empty(int32_t srid, char hasz, char hasm)
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
#define POLYHEDRALSURFACETYPE
void lwcollection_release(LWCOLLECTION *lwcollection)
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
#define FLAGS_GET_M(flags)
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...
LWCOLLECTION * lwcollection_concat_in_place(LWCOLLECTION *col1, const LWCOLLECTION *col2)
Appends all geometries from col2 to col1 in place.
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.
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.
void lwpoly_free(LWPOLY *poly)
#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)
LWPOLY * lwpoly_construct_empty(int32_t srid, char hasz, char hasm)
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
LWMPOINT * lwmpoint_construct(int32_t srid, const POINTARRAY *pa)
void lwline_free(LWLINE *line)
LWTRIANGLE * lwtriangle_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
LWPOINT * lwpoint_clone(const LWPOINT *lwgeom)
int p4d_same(const POINT4D *p1, const POINT4D *p2)
#define LW_ON_INTERRUPT(x)
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.
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
void lwpoint_set_ordinate(POINT4D *p, char ordinate, double value)
Given a point, ordinate number and value, set that ordinate on the point.
static 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.
static LWCOLLECTION * lwpoly_clip_to_ordinate_range(const LWPOLY *poly, char ordinate, double from, double to)
Clip an input LWPOLY 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)
static LWCOLLECTION * lwtriangle_clip_to_ordinate_range(const LWTRIANGLE *tri, char ordinate, double from, double to)
Clip an input LWTRIANGLE between two values, on any ordinate input.
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)
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)
static POINTARRAY * ptarray_clamp_to_ordinate_range(const POINTARRAY *ipa, char ordinate, double from, double to, uint8_t is_closed)
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,...
static 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...
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 LWCOLLECTION * lwcollection_clip_to_ordinate_range(const LWCOLLECTION *icol, char ordinate, double from, double to)
Clip an input COLLECTION between two values, on any ordinate input.
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...
static 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)
int lwgeom_cpa_within(const LWGEOM *g1, const LWGEOM *g2, double maxdist)
Is the closest point of approach within a distance ?
Datum within(PG_FUNCTION_ARGS)