PostGIS  2.2.8dev-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 222 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().

224 {
225  double mindist = -1;
226  POINT4D pt, pt_projected;
227  POINT4D p1, p2;
228  POINTARRAY *ipa = lwline_in->points;
229  POINTARRAY* pa1;
230  POINTARRAY* pa2;
231  int i, nsegs, seg = -1;
232 
233  /* Possible outcomes:
234  *
235  * 1. The point is not on the line or on the boundary
236  * -> Leave collection untouched, return 0
237  * 2. The point is on the boundary
238  * -> Leave collection untouched, return 1
239  * 3. The point is in the line
240  * -> Push 2 elements on the collection:
241  * o start_point - cut_point
242  * o cut_point - last_point
243  * -> Return 2
244  */
245 
246  getPoint4d_p(blade_in->point, 0, &pt);
247 
248  /* Find closest segment */
249  getPoint4d_p(ipa, 0, &p1);
250  nsegs = ipa->npoints - 1;
251  for ( i = 0; i < nsegs; i++ )
252  {
253  getPoint4d_p(ipa, i+1, &p2);
254  double dist;
255  dist = distance2d_pt_seg((POINT2D*)&pt, (POINT2D*)&p1, (POINT2D*)&p2);
256  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);
257  if (i==0 || dist < mindist )
258  {
259  mindist = dist;
260  seg=i;
261  if ( mindist == 0.0 ) break; /* can't be closer than ON line */
262  }
263  p1 = p2;
264  }
265 
266  LWDEBUGF(3, "Closest segment: %d", seg);
267  LWDEBUGF(3, "mindist: %g", mindist);
268 
269  /* No intersection */
270  if ( mindist > 0 ) return 0;
271 
272  /* empty or single-point line, intersection on boundary */
273  if ( seg < 0 ) return 1;
274 
275  /*
276  * We need to project the
277  * point on the closest segment,
278  * to interpolate Z and M if needed
279  */
280  getPoint4d_p(ipa, seg, &p1);
281  getPoint4d_p(ipa, seg+1, &p2);
282  closest_point_on_segment(&pt, &p1, &p2, &pt_projected);
283  /* But X and Y we want the ones of the input point,
284  * as on some architectures the interpolation math moves the
285  * coordinates (see #3422)
286  */
287  pt_projected.x = pt.x;
288  pt_projected.y = pt.y;
289 
290  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);
291 
292  /* When closest point == an endpoint, this is a boundary intersection */
293  if ( ( (seg == nsegs-1) && p4d_same(&pt_projected, &p2) ) ||
294  ( (seg == 0) && p4d_same(&pt_projected, &p1) ) )
295  {
296  return 1;
297  }
298 
299  /* This is an internal intersection, let's build the two new pointarrays */
300 
301  pa1 = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), seg+2);
302  /* TODO: replace with a memcpy ? */
303  for (i=0; i<=seg; ++i)
304  {
305  getPoint4d_p(ipa, i, &p1);
306  ptarray_append_point(pa1, &p1, LW_FALSE);
307  }
308  ptarray_append_point(pa1, &pt_projected, LW_FALSE);
309 
310  pa2 = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), ipa->npoints-seg);
311  ptarray_append_point(pa2, &pt_projected, LW_FALSE);
312  /* TODO: replace with a memcpy (if so need to check for duplicated point) ? */
313  for (i=seg+1; i<ipa->npoints; ++i)
314  {
315  getPoint4d_p(ipa, i, &p1);
316  ptarray_append_point(pa2, &p1, LW_FALSE);
317  }
318 
319  /* NOTE: I've seen empty pointarrays with loc != 0 and loc != 1 */
320  if ( pa1->npoints == 0 || pa2->npoints == 0 ) {
321  ptarray_free(pa1);
322  ptarray_free(pa2);
323  /* Intersection is on the boundary */
324  return 1;
325  }
326 
329  return 2;
330 }
double x
Definition: liblwgeom.h:336
int npoints
Definition: liblwgeom.h:355
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:32
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:2327
POINTARRAY * point
Definition: liblwgeom.h:395
double x
Definition: liblwgeom.h:312
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_TRUE, then a duplicate point will not be added.
Definition: ptarray.c:156
#define LW_FALSE
Definition: liblwgeom.h:62
uint8_t flags
Definition: liblwgeom.h:353
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:29
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:172
double y
Definition: liblwgeom.h:312
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:124
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:125
void closest_point_on_segment(const POINT4D *R, const POINT4D *A, const POINT4D *B, POINT4D *ret)
Definition: ptarray.c:1255
double y
Definition: liblwgeom.h:336
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:231
int p4d_same(const POINT4D *p1, const POINT4D *p2)
Definition: lwalgorithm.c:17
POINTARRAY * points
Definition: liblwgeom.h:406
Here is the call graph for this function:
Here is the caller graph for this function: