PostGIS  3.0.6dev-r@@SVN_REVISION@@

◆ lwline_interpolate_point_3d()

LWPOINT* lwline_interpolate_point_3d ( const LWLINE line,
double  distance 
)

Interpolate one point along a line in 3D.

Definition at line 602 of file lwline.c.

603 {
604  double length, slength, tlength;
605  POINTARRAY *ipa;
606  POINT4D pt;
607  int nsegs, i;
608  LWGEOM *geom = lwline_as_lwgeom(line);
609  int has_z = lwgeom_has_z(geom);
610  int has_m = lwgeom_has_m(geom);
611  ipa = line->points;
612 
613  /* Empty.InterpolatePoint == Point Empty */
614  if (lwline_is_empty(line))
615  {
616  return lwpoint_construct_empty(line->srid, has_z, has_m);
617  }
618 
619  /* If distance is one of the two extremes, return the point on that
620  * end rather than doing any expensive computations
621  */
622  if (distance == 0.0 || distance == 1.0)
623  {
624  if (distance == 0.0)
625  getPoint4d_p(ipa, 0, &pt);
626  else
627  getPoint4d_p(ipa, ipa->npoints - 1, &pt);
628 
629  return lwpoint_make(line->srid, has_z, has_m, &pt);
630  }
631 
632  /* Interpolate a point on the line */
633  nsegs = ipa->npoints - 1;
634  length = ptarray_length(ipa);
635  tlength = 0;
636  for (i = 0; i < nsegs; i++)
637  {
638  POINT4D p1, p2;
639  POINT4D *p1ptr = &p1, *p2ptr = &p2; /* don't break
640  * strict-aliasing rules
641  */
642 
643  getPoint4d_p(ipa, i, &p1);
644  getPoint4d_p(ipa, i + 1, &p2);
645 
646  /* Find the relative length of this segment */
647  slength = distance3d_pt_pt((POINT3D *)p1ptr, (POINT3D *)p2ptr) / length;
648 
649  /* If our target distance is before the total length we've seen
650  * so far. create a new point some distance down the current
651  * segment.
652  */
653  if (distance < tlength + slength)
654  {
655  double dseg = (distance - tlength) / slength;
656  interpolate_point4d(&p1, &p2, &pt, dseg);
657  return lwpoint_make(line->srid, has_z, has_m, &pt);
658  }
659  tlength += slength;
660  }
661 
662  /* Return the last point on the line. This shouldn't happen, but
663  * could if there's some floating point rounding errors. */
664  getPoint4d_p(ipa, ipa->npoints - 1, &pt);
665  return lwpoint_make(line->srid, has_z, has_m, &pt);
666 }
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwpoint.c:151
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:321
void interpolate_point4d(const POINT4D *A, const POINT4D *B, POINT4D *I, double F)
Find interpolation point I between point A and point B so that the len(AI) == len(AB)*F and I falls o...
Definition: lwgeom_api.c:656
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:916
double distance3d_pt_pt(const POINT3D *p1, const POINT3D *p2)
Definition: measures3d.c:1032
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:125
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:923
LWPOINT * lwpoint_make(int32_t srid, int hasz, int hasm, const POINT4D *p)
Definition: lwpoint.c:206
int lwline_is_empty(const LWLINE *line)
double ptarray_length(const POINTARRAY *pts)
Find the 3d/2d length of the given POINTARRAY (depending on its dimensionality)
Definition: ptarray.c:1728
static double distance(double x1, double y1, double x2, double y2)
Definition: lwtree.c:1032
POINTARRAY * points
Definition: liblwgeom.h:469
int32_t srid
Definition: liblwgeom.h:470
uint32_t npoints
Definition: liblwgeom.h:413

References distance(), distance3d_pt_pt(), getPoint4d_p(), interpolate_point4d(), lwgeom_has_m(), lwgeom_has_z(), lwline_as_lwgeom(), lwline_is_empty(), lwpoint_construct_empty(), lwpoint_make(), POINTARRAY::npoints, LWLINE::points, ptarray_length(), and LWLINE::srid.

Referenced by ST_3DLineInterpolatePoint(), and test_lwline_interpolate_point_3d().

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