PostGIS  3.0.6dev-r@@SVN_REVISION@@

◆ ptarray_segmentize2d()

POINTARRAY* ptarray_segmentize2d ( const POINTARRAY ipa,
double  dist 
)

Returns a modified POINTARRAY so that no segment is longer than the given distance (computed using 2d).

Every input point is kept. Z and M values for added points (if needed) are set proportionally.

Definition at line 405 of file ptarray.c.

406 {
407  double segdist;
408  POINT4D p1, p2;
409  POINT4D pbuf;
410  POINTARRAY *opa;
411  uint32_t i, j, nseg;
412  int hasz = FLAGS_GET_Z(ipa->flags);
413  int hasm = FLAGS_GET_M(ipa->flags);
414 
415  pbuf.x = pbuf.y = pbuf.z = pbuf.m = 0;
416 
417  /* Initial storage */
418  opa = ptarray_construct_empty(hasz, hasm, ipa->npoints);
419 
420  /* Add first point */
421  getPoint4d_p(ipa, 0, &p1);
422  ptarray_append_point(opa, &p1, LW_FALSE);
423 
424  /* Loop on all other input points */
425  for (i = 1; i < ipa->npoints; i++)
426  {
427  /*
428  * We use these pointers to avoid
429  * "strict-aliasing rules break" warning raised
430  * by gcc (3.3 and up).
431  *
432  * It looks that casting a variable address (also
433  * referred to as "type-punned pointer")
434  * breaks those "strict" rules.
435  */
436  POINT4D *p1ptr=&p1, *p2ptr=&p2;
437  double segments;
438 
439  getPoint4d_p(ipa, i, &p2);
440 
441  segdist = distance2d_pt_pt((POINT2D *)p1ptr, (POINT2D *)p2ptr);
442  /* Split input segment into shorter even chunks */
443  segments = ceil(segdist / dist);
444 
445  /* Uses INT32_MAX instead of UINT32_MAX to be safe that it fits */
446  if (segments >= INT32_MAX)
447  {
448  lwnotice("%s:%d - %s: Too many segments required (%e)",
449  __FILE__, __LINE__,__func__, segments);
450  ptarray_free(opa);
451  return NULL;
452  }
453  nseg = segments;
454 
455  for (j = 1; j < nseg; j++)
456  {
457  pbuf.x = p1.x + (p2.x - p1.x) * j / nseg;
458  pbuf.y = p1.y + (p2.y - p1.y) * j / nseg;
459  if (hasz)
460  pbuf.z = p1.z + (p2.z - p1.z) * j / nseg;
461  if (hasm)
462  pbuf.m = p1.m + (p2.m - p1.m) * j / nseg;
463  ptarray_append_point(opa, &pbuf, LW_FALSE);
464  LW_ON_INTERRUPT(ptarray_free(opa); return NULL);
465  }
466 
467  ptarray_append_point(opa, &p2, (ipa->npoints == 2) ? LW_TRUE : LW_FALSE);
468  p1 = p2;
469  LW_ON_INTERRUPT(ptarray_free(opa); return NULL);
470  }
471 
472  return opa;
473 }
#define LW_FALSE
Definition: liblwgeom.h:108
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:2397
#define FLAGS_GET_Z(flags)
Definition: liblwgeom.h:179
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:180
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:125
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:107
#define LW_ON_INTERRUPT(x)
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
#define INT32_MAX
Definition: lwin_wkt_lex.c:334
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:59
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:319
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int repeated_points)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
Definition: ptarray.c:147
double m
Definition: liblwgeom.h:400
double x
Definition: liblwgeom.h:400
double z
Definition: liblwgeom.h:400
double y
Definition: liblwgeom.h:400
lwflags_t flags
Definition: liblwgeom.h:417
uint32_t npoints
Definition: liblwgeom.h:413

References distance2d_pt_pt(), POINTARRAY::flags, FLAGS_GET_M, FLAGS_GET_Z, getPoint4d_p(), INT32_MAX, LW_FALSE, LW_ON_INTERRUPT, LW_TRUE, lwnotice(), POINT4D::m, POINTARRAY::npoints, ptarray_append_point(), ptarray_construct_empty(), ptarray_free(), POINT4D::x, POINT4D::y, and POINT4D::z.

Referenced by lwline_segmentize2d(), and lwpoly_segmentize2d().

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