PostGIS  2.4.9dev-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.

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, 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().

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