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 assert(ordinate ==
'X' || ordinate ==
'Y' ||
331 ordinate ==
'Z' || ordinate ==
'M');
332 assert(
FP_MIN(p1_value, p2_value) <= interpolation_value &&
333 FP_MAX(p1_value, p2_value) >= interpolation_value);
335 proportion = (interpolation_value - p1_value) / (p2_value - p1_value);
337 for (i = 0; i < 4; i++)
339 if (dims[i] ==
'Z' && !hasz)
341 if (dims[i] ==
'M' && !hasm)
343 if (dims[i] == ordinate)
347 double newordinate = 0.0;
350 newordinate = p1_value + proportion * (p2_value - p1_value);
367 double ordinate_value;
379 if (from <= ordinate_value && to >= ordinate_value)
406 for (i = 0; i < mpoint->
ngeoms; i++)
409 double ordinate_value;
414 if (from <= ordinate_value && to >= ordinate_value)
451 p1out = (ovp1 < from) ? -1 : ((ovp1 > to) ? 1 : 0);
453 if (from <= ovp1 && ovp1 <= to)
457 for (i = 1; i < ipa->
npoints; i++)
461 p2out = (ovp2 < from) ? -1 : ((ovp2 > to) ? 1 : 0);
463 if (p1out == 0 && p2out == 0)
467 else if (p1out == p2out && p1out != 0)
471 else if (p1out == -1 && p2out == 0)
477 else if (p1out == -1 && p2out == 1)
484 else if (p1out == 0 && p2out == -1)
489 else if (p1out == 0 && p2out == 1)
494 else if (p1out == 1 && p2out == -1)
501 else if (p1out == 1 && p2out == 0)
513 if (is_closed && opa->
npoints > 2)
534 int added_last_point = 0;
535 POINT4D *p = NULL, *q = NULL, *
r = NULL;
536 double ordinate_value_p = 0.0, ordinate_value_q = 0.0;
547 if ((ordinate ==
'Z' && !hasz) || (ordinate ==
'M' && !hasm))
549 lwerror(
"Cannot clip on ordinate %d in a %d-d geometry.", ordinate, dims);
564 for (i = 0; i < pa_in->
npoints; i++)
569 ordinate_value_q = ordinate_value_p;
575 if (ordinate_value_p >= from && ordinate_value_p <= to)
578 if (!added_last_point)
590 (ordinate_value_p > from && ordinate_value_p < to) ||
591 (ordinate_value_p == from && ordinate_value_q > to) ||
592 (ordinate_value_p == to && ordinate_value_q < from)))
594 double interpolation_value;
595 (ordinate_value_q > to) ? (interpolation_value = to)
596 : (interpolation_value = from);
603 if (ordinate_value_p == from || ordinate_value_p == to)
604 added_last_point = 2;
606 added_last_point = 1;
611 if (added_last_point == 1)
615 double interpolation_value;
616 (ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
620 else if (added_last_point == 2)
625 if (from != to && ((ordinate_value_q == from && ordinate_value_p > from) ||
626 (ordinate_value_q == to && ordinate_value_p < to)))
628 double interpolation_value;
629 (ordinate_value_p > to) ? (interpolation_value = to)
630 : (interpolation_value = from);
635 else if (i && ordinate_value_q < from && ordinate_value_p > to)
647 else if (i && ordinate_value_q > to && ordinate_value_p < from)
679 added_last_point = 0;
722 for (uint32_t i = 0; i < poly->
nrings; i++)
764 for (uint32_t i = 1; i < pa->
npoints - 2; i++)
802 for (i = 0; i < icol->
ngeoms; i++)
838 lwerror(
"lwgeom_clip_to_ordinate_range: null input geometry!");
871 lwerror(
"lwgeom_clip_to_ordinate_range clipping routine returned NULL");
882 for (i = 0; i < out_col->
ngeoms; i++)
887 lwnotice(
"lwgeom_clip_to_ordinate_range cannot offset a clipped point");
896 lwerror(
"lwgeom_offsetcurve returned null");
902 lwerror(
"lwgeom_clip_to_ordinate_range found an unexpected type (%s) in the offset routine",
914 lwerror(
"Input geometry does not have a measure dimension");
926 lwerror(
"lwgeom_interpolate_point: null input geometry!");
929 lwerror(
"Input geometry does not have a measure dimension");
932 lwerror(
"Input geometry is empty");
992 pv.
x = (p1->
x - p0->
x);
993 pv.
y = (p1->
y - p0->
y);
994 pv.
z = (p1->
z - p0->
z);
998 qv.
x = (q1->
x - q0->
x);
999 qv.
y = (q1->
y - q0->
y);
1000 qv.
z = (q1->
z - q0->
z);
1008 double dv2 =
DOT(dv, dv);
1018 w0.
x = (p0->
x - q0->
x);
1019 w0.
y = (p0->
y - q0->
y);
1020 w0.
z = (p0->
z - q0->
z);
1027 double t = -
DOT(w0, dv) / dv2;
1052 t = t0 + (t1 - t0) * t;
1063 for (i = 0; i < pa->
npoints; ++i)
1066 if (pbuf.
m >= tmin && pbuf.
m <= tmax)
1067 mvals[n++] = pbuf.
m;
1075 double a = *((
double *)pa);
1076 double b = *((
double *)pb);
1090 for (i = 1; i < nvals; ++i)
1093 if (vals[i] != vals[last])
1095 vals[++last] = vals[i];
1124 for (i = from + 1; i < pa->
npoints; i++)
1147 double mindist2 = FLT_MAX;
1151 lwerror(
"Both input geometries must have a measure dimension");
1160 lwerror(
"Both input geometries must be linestrings");
1166 lwerror(
"Both input lines must have at least 2 points");
1186 LWDEBUG(1,
"Inputs never exist at the same time");
1206 nmvals =
uniq(mvals, nmvals);
1212 double t0 = mvals[0];
1214 LWDEBUGF(1,
"Inputs only exist both at a single time (%g)", t0);
1220 lwerror(
"Could not find point with M=%g on first geom", t0);
1226 lwerror(
"Could not find point with M=%g on second geom", t0);
1241 for (i = 1; i < nmvals; ++i)
1243 double t0 = mvals[i - 1];
1244 double t1 = mvals[i];
1280 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);
1281 if (dist2 < mindist2)
1297 *mindist = sqrt(mindist2);
1313 double maxdist2 = maxdist * maxdist;
1318 lwerror(
"Both input geometries must have a measure dimension");
1327 lwerror(
"Both input geometries must be linestrings");
1334 lwerror(
"Both input lines must have at least 2 points");
1354 LWDEBUG(1,
"Inputs never exist at the same time");
1372 nmvals =
uniq(mvals, nmvals);
1377 double t0 = mvals[0];
1379 LWDEBUGF(1,
"Inputs only exist both at a single time (%g)", t0);
1382 lwnotice(
"Could not find point with M=%g on first geom", t0);
1387 lwnotice(
"Could not find point with M=%g on second geom", t0);
1400 for (i = 1; i < nmvals; ++i)
1402 double t0 = mvals[i - 1];
1403 double t1 = mvals[i];
1404 #if POSTGIS_DEBUG_LEVEL >= 1
1433 #if POSTGIS_DEBUG_LEVEL >= 1
1444 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);
1445 if (dist2 <= maxdist2)
1447 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)
Datum within(PG_FUNCTION_ARGS)
#define LWDEBUG(level, msg)
#define LWDEBUGF(level, msg,...)
void lwnotice(const char *fmt,...) __attribute__((format(printf
Write a notice out to the notice handler.
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error 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 ?