PostGIS  2.5.7dev-r@@SVN_REVISION@@

◆ 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 = -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;
243  dist = distance2d_pt_seg((POINT2D*)&pt, (POINT2D*)&p1, (POINT2D*)&p2);
244  LWDEBUGF(4, " Distance of point %g %g to segment %g %g, %g %g: %g", pt.x, pt.y, p1.x, p1.y, p2.x, p2.y, dist);
245  if (i==0 || dist < mindist )
246  {
247  mindist = dist;
248  seg=i;
249  if ( mindist == 0.0 ) break; /* can't be closer than ON line */
250  }
251  p1 = p2;
252  }
253 
254  LWDEBUGF(3, "Closest segment: %d", seg);
255  LWDEBUGF(3, "mindist: %g", mindist);
256 
257  /* No intersection */
258  if ( mindist > 0 ) return 0;
259 
260  /* empty or single-point line, intersection on boundary */
261  if ( seg == UINT32_MAX ) return 1;
262 
263  /*
264  * We need to project the
265  * point on the closest segment,
266  * to interpolate Z and M if needed
267  */
268  getPoint4d_p(ipa, seg, &p1);
269  getPoint4d_p(ipa, seg+1, &p2);
270  closest_point_on_segment(&pt, &p1, &p2, &pt_projected);
271  /* But X and Y we want the ones of the input point,
272  * as on some architectures the interpolation math moves the
273  * coordinates (see #3422)
274  */
275  pt_projected.x = pt.x;
276  pt_projected.y = pt.y;
277 
278  LWDEBUGF(3, "Projected point:(%g %g), seg:%d, p1:(%g %g), p2:(%g %g)", pt_projected.x, pt_projected.y, seg, p1.x, p1.y, p2.x, p2.y);
279 
280  /* When closest point == an endpoint, this is a boundary intersection */
281  if ( ( (seg == nsegs-1) && p4d_same(&pt_projected, &p2) ) ||
282  ( (seg == 0) && p4d_same(&pt_projected, &p1) ) )
283  {
284  return 1;
285  }
286 
287  /* This is an internal intersection, let's build the two new pointarrays */
288 
289  pa1 = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), seg+2);
290  /* TODO: replace with a memcpy ? */
291  for (i=0; i<=seg; ++i)
292  {
293  getPoint4d_p(ipa, i, &p1);
294  ptarray_append_point(pa1, &p1, LW_FALSE);
295  }
296  ptarray_append_point(pa1, &pt_projected, LW_FALSE);
297 
298  pa2 = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), ipa->npoints-seg);
299  ptarray_append_point(pa2, &pt_projected, LW_FALSE);
300  /* TODO: replace with a memcpy (if so need to check for duplicated point) ? */
301  for (i=seg+1; i<ipa->npoints; ++i)
302  {
303  getPoint4d_p(ipa, i, &p1);
304  ptarray_append_point(pa2, &p1, LW_FALSE);
305  }
306 
307  /* NOTE: I've seen empty pointarrays with loc != 0 and loc != 1 */
308  if ( pa1->npoints == 0 || pa2->npoints == 0 ) {
309  ptarray_free(pa1);
310  ptarray_free(pa2);
311  /* Intersection is on the boundary */
312  return 1;
313  }
314 
317  return 2;
318 }
#define LW_FALSE
Definition: liblwgeom.h:77
LWMLINE * lwmline_add_lwline(LWMLINE *mobj, const LWLINE *obj)
Definition: lwmline.c:46
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:140
double distance2d_pt_seg(const POINT2D *p, const POINT2D *A, const POINT2D *B)
Definition: measures.c:2332
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:141
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:123
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:328
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:156
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:188
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
int p4d_same(const POINT4D *p1, const POINT4D *p2)
Definition: lwalgorithm.c:31
void closest_point_on_segment(const POINT4D *R, const POINT4D *A, const POINT4D *B, POINT4D *ret)
Definition: ptarray.c:1257
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
#define UINT32_MAX
Definition: lwin_wkt_lex.c:343
POINTARRAY * points
Definition: liblwgeom.h:425
POINTARRAY * point
Definition: liblwgeom.h:414
double y
Definition: liblwgeom.h:331
double x
Definition: liblwgeom.h:331
double x
Definition: liblwgeom.h:355
double y
Definition: liblwgeom.h:355
uint32_t npoints
Definition: liblwgeom.h:374
uint8_t flags
Definition: liblwgeom.h:372
unsigned int uint32_t
Definition: uthash.h:78

References closest_point_on_segment(), distance2d_pt_seg(), POINTARRAY::flags, FLAGS_GET_M, FLAGS_GET_Z, getPoint4d_p(), LW_FALSE, LWDEBUGF, lwline_construct(), lwmline_add_lwline(), POINTARRAY::npoints, p4d_same(), 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: