PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ lwline_split_by_point_to()

int lwline_split_by_point_to ( const LWLINE ln,
const LWPOINT pt,
LWMLINE to 
)

Split a line by a point and push components to the provided multiline.

If the point doesn't split the line, push nothing to the container. Returns 0 if the point is off the line. Returns 1 if the point is on the line boundary (endpoints). Return 2 if the point is on the interior of the line (only case in which a split happens).

NOTE: the components pushed to the output vector have their SRID stripped

Definition at line 209 of file lwgeom_geos_split.c.

211{
212 double mindist_sqr = -1;
213 POINT4D pt, pt_projected;
214 POINT4D p1, p2;
215 POINTARRAY *ipa = lwline_in->points;
216 POINTARRAY* pa1;
217 POINTARRAY* pa2;
218 uint32_t i, nsegs, seg = UINT32_MAX;
219
220 /* Possible outcomes:
221 *
222 * 1. The point is not on the line or on the boundary
223 * -> Leave collection untouched, return 0
224 * 2. The point is on the boundary
225 * -> Leave collection untouched, return 1
226 * 3. The point is in the line
227 * -> Push 2 elements on the collection:
228 * o start_point - cut_point
229 * o cut_point - last_point
230 * -> Return 2
231 */
232
233 getPoint4d_p(blade_in->point, 0, &pt);
234
235 /* Find closest segment */
236 if ( ipa->npoints < 1 ) return 0; /* empty input line */
237 getPoint4d_p(ipa, 0, &p1);
238 nsegs = ipa->npoints - 1;
239 for ( i = 0; i < nsegs; i++ )
240 {
241 getPoint4d_p(ipa, i+1, &p2);
242 double dist_sqr = distance2d_sqr_pt_seg((POINT2D *)&pt, (POINT2D *)&p1, (POINT2D *)&p2);
243 LWDEBUGF(4, "Distance (squared) of point %.15g %.15g to segment %.15g %.15g, %.15g %.15g: %.15g",
244 pt.x, pt.y,
245 p1.x, p1.y,
246 p2.x, p2.y,
247 dist_sqr);
248 if (i == 0 || dist_sqr < mindist_sqr)
249 {
250 mindist_sqr = dist_sqr;
251 seg=i;
252 if (mindist_sqr == 0.0)
253 break; /* can't be closer than ON line */
254 }
255 p1 = p2;
256 }
257
258 LWDEBUGF(3, "Closest segment: %d", seg);
259 LWDEBUGF(3, "mindist: %.15g", mindist_sqr);
260
261 /* No intersection */
262 if (mindist_sqr > 0)
263 return 0;
264
265 /* empty or single-point line, intersection on boundary */
266 if ( seg == UINT32_MAX ) return 1;
267
268 /*
269 * We need to project the
270 * point on the closest segment,
271 * to interpolate Z and M if needed
272 */
273 getPoint4d_p(ipa, seg, &p1);
274 getPoint4d_p(ipa, seg+1, &p2);
275 closest_point_on_segment(&pt, &p1, &p2, &pt_projected);
276 /* But X and Y we want the ones of the input point,
277 * as on some architectures the interpolation math moves the
278 * coordinates (see #3422)
279 */
280 pt_projected.x = pt.x;
281 pt_projected.y = pt.y;
282
283 LWDEBUGF(3, "Projected point:(%.15g %.15g), seg:%d, p1:(%.15g %.15g), p2:(%.15g %.15g)", pt_projected.x, pt_projected.y, seg, p1.x, p1.y, p2.x, p2.y);
284
285 /* When closest point == an endpoint, this is a boundary intersection */
286 if ( ( (seg == nsegs-1) && P4D_SAME_STRICT(&pt_projected, &p2) ) ||
287 ( (seg == 0) && P4D_SAME_STRICT(&pt_projected, &p1) ) )
288 {
289 return 1;
290 }
291
292 /* This is an internal intersection, let's build the two new pointarrays */
293
294 pa1 = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), seg+2);
295 /* TODO: replace with a memcpy ? */
296 for (i=0; i<=seg; ++i)
297 {
298 getPoint4d_p(ipa, i, &p1);
300 }
301 ptarray_append_point(pa1, &pt_projected, LW_FALSE);
302
304 ptarray_append_point(pa2, &pt_projected, LW_FALSE);
305 /* TODO: replace with a memcpy (if so need to check for duplicated point) ? */
306 for (i=seg+1; i<ipa->npoints; ++i)
307 {
308 getPoint4d_p(ipa, i, &p1);
310 }
311
312 /* NOTE: I've seen empty pointarrays with loc != 0 and loc != 1 */
313 if ( pa1->npoints == 0 || pa2->npoints == 0 ) {
314 ptarray_free(pa1);
315 ptarray_free(pa2);
316 /* Intersection is on the boundary */
317 return 1;
318 }
319
322 return 2;
323}
#define LW_FALSE
Definition liblwgeom.h:94
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition ptarray.c:59
#define FLAGS_GET_Z(flags)
Definition liblwgeom.h:165
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
LWMLINE * lwmline_add_lwline(LWMLINE *mobj, const LWLINE *obj)
Definition lwmline.c:46
#define FLAGS_GET_M(flags)
Definition liblwgeom.h:166
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition lwgeom_api.c:125
double distance2d_sqr_pt_seg(const POINT2D *p, const POINT2D *A, const POINT2D *B)
Definition measures.c:2354
void ptarray_free(POINTARRAY *pa)
Definition ptarray.c:327
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,...
Definition ptarray.c:147
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:215
#define P4D_SAME_STRICT(a, b)
void closest_point_on_segment(const POINT4D *R, const POINT4D *A, const POINT4D *B, POINT4D *ret)
Definition ptarray.c:1408
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
#define UINT32_MAX
double y
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:414
double y
Definition liblwgeom.h:414
lwflags_t flags
Definition liblwgeom.h:431
uint32_t npoints
Definition liblwgeom.h:427

References closest_point_on_segment(), distance2d_sqr_pt_seg(), POINTARRAY::flags, FLAGS_GET_M, FLAGS_GET_Z, getPoint4d_p(), LW_FALSE, LWDEBUGF, lwline_construct(), lwmline_add_lwline(), POINTARRAY::npoints, P4D_SAME_STRICT, LWPOINT::point, LWLINE::points, ptarray_append_point(), ptarray_construct_empty(), ptarray_free(), SRID_UNKNOWN, UINT32_MAX, POINT2D::x, POINT4D::x, POINT2D::y, and POINT4D::y.

Referenced by lwgeom_node(), lwline_split_by_mpoint(), lwline_split_by_point(), and test_lwline_split_by_point_to().

Here is the call graph for this function:
Here is the caller graph for this function: