PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ geography_interpolate_points()

LWGEOM* geography_interpolate_points ( const LWLINE line,
double  length_fraction,
const SPHEROID s,
char  repeat 
)

Interpolate a point along a geographic line.

Definition at line 257 of file lwgeodetic_measures.c.

260 {
261  POINT4D pt;
262  uint32_t i;
263  uint32_t points_to_interpolate;
264  uint32_t points_found = 0;
265  double length;
266  double length_fraction_increment = length_fraction;
267  double length_fraction_consumed = 0;
268  char has_z = (char) lwgeom_has_z(lwline_as_lwgeom(line));
269  char has_m = (char) lwgeom_has_m(lwline_as_lwgeom(line));
270  const POINTARRAY* ipa = line->points;
271  POINTARRAY *opa;
272  POINT4D p1, p2;
273  POINT3D q1, q2;
274  LWGEOM *lwresult;
275  GEOGRAPHIC_POINT g1, g2;
276  uint32_t srid = line->srid;
277 
278  /* Empty.InterpolatePoint == Point Empty */
279  if ( lwline_is_empty(line) )
280  {
281  return lwgeom_clone_deep(lwline_as_lwgeom(line));
282  }
283 
284  /*
285  * If distance is one of the two extremes, return the point on that
286  * end rather than doing any computations
287  */
288  if ( length_fraction == 0.0 || length_fraction == 1.0 )
289  {
290  if ( length_fraction == 0.0 )
291  getPoint4d_p(ipa, 0, &pt);
292  else
293  getPoint4d_p(ipa, ipa->npoints-1, &pt);
294 
295  opa = ptarray_construct(has_z, has_m, 1);
296  ptarray_set_point4d(opa, 0, &pt);
297  return lwpoint_as_lwgeom(lwpoint_construct(srid, NULL, opa));
298  }
299 
300  /* Interpolate points along the line */
301  length = ptarray_length_spheroid(ipa, s);
302  points_to_interpolate = repeat ? (uint32_t) floor(1 / length_fraction) : 1;
303  opa = ptarray_construct(has_z, has_m, points_to_interpolate);
304 
305  getPoint4d_p(ipa, 0, &p1);
306  geographic_point_init(p1.x, p1.y, &g1);
307  for ( i = 0; i < ipa->npoints - 1 && points_found < points_to_interpolate; i++ )
308  {
309  double segment_length_frac;
310  getPoint4d_p(ipa, i+1, &p2);
311  geographic_point_init(p2.x, p2.y, &g2);
312 
313  /* Special sphere case */
314  if ( s->a == s->b )
315  segment_length_frac = s->radius * sphere_distance(&g1, &g2) / length;
316  /* Spheroid case */
317  else
318  segment_length_frac = spheroid_distance(&g1, &g2, s) / length;
319 
320  /* If our target distance is before the total length we've seen
321  * so far. create a new point some distance down the current
322  * segment.
323  */
324  while ( length_fraction < length_fraction_consumed + segment_length_frac && points_found < points_to_interpolate )
325  {
326  geog2cart(&g1, &q1);
327  geog2cart(&g2, &q2);
328  double segment_fraction = (length_fraction - length_fraction_consumed) / segment_length_frac;
329  interpolate_point4d_spheroid(&p1, &p2, &pt, s, segment_fraction);
330  ptarray_set_point4d(opa, points_found++, &pt);
331  length_fraction += length_fraction_increment;
332  }
333 
334  length_fraction_consumed += segment_length_frac;
335 
336  p1 = p2;
337  g1 = g2;
338  }
339 
340  /* Return the last point on the line. This shouldn't happen, but
341  * could if there's some floating point rounding errors. */
342  if (points_found < points_to_interpolate)
343  {
344  getPoint4d_p(ipa, ipa->npoints - 1, &pt);
345  ptarray_set_point4d(opa, points_found, &pt);
346  }
347 
348  if (opa->npoints <= 1)
349  {
350  lwresult = lwpoint_as_lwgeom(lwpoint_construct(srid, NULL, opa));
351  } else {
352  lwresult = lwmpoint_as_lwgeom(lwmpoint_construct(srid, opa));
353  }
354 
355  return lwresult;
356 }
char * s
Definition: cu_in_wkt.c:23
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:339
LWGEOM * lwmpoint_as_lwgeom(const LWMPOINT *obj)
Definition: lwgeom.c:304
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition: lwgeom.c:529
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition: ptarray.c:51
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:934
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:344
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
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:941
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
Definition: lwgeom_api.c:369
LWMPOINT * lwmpoint_construct(int32_t srid, const POINTARRAY *pa)
Definition: lwmpoint.c:52
int lwline_is_empty(const LWLINE *line)
void geographic_point_init(double lon, double lat, GEOGRAPHIC_POINT *g)
Initialize a geographic point.
Definition: lwgeodetic.c:180
double ptarray_length_spheroid(const POINTARRAY *pa, const SPHEROID *s)
Definition: lwgeodetic.c:3092
double sphere_distance(const GEOGRAPHIC_POINT *s, const GEOGRAPHIC_POINT *e)
Given two points on a unit sphere, calculate their distance apart in radians.
Definition: lwgeodetic.c:896
void geog2cart(const GEOGRAPHIC_POINT *g, POINT3D *p)
Convert spherical coordinates to cartesian coordinates on unit sphere.
Definition: lwgeodetic.c:404
double spheroid_distance(const GEOGRAPHIC_POINT *a, const GEOGRAPHIC_POINT *b, const SPHEROID *spheroid)
Computes the shortest distance along the surface of the spheroid between two points,...
Definition: lwspheroid.c:79
static void interpolate_point4d_spheroid(const POINT4D *p1, const POINT4D *p2, POINT4D *p, const SPHEROID *s, double f)
Find interpolation point p between geography points p1 and p2 so that the len(p1,p) == len(p1,...
Point in spherical coordinates on the world.
Definition: lwgeodetic.h:54
POINTARRAY * points
Definition: liblwgeom.h:483
int32_t srid
Definition: liblwgeom.h:484
double x
Definition: liblwgeom.h:414
double y
Definition: liblwgeom.h:414
uint32_t npoints
Definition: liblwgeom.h:427

References geog2cart(), geographic_point_init(), getPoint4d_p(), interpolate_point4d_spheroid(), lwgeom_clone_deep(), lwgeom_has_m(), lwgeom_has_z(), lwline_as_lwgeom(), lwline_is_empty(), lwmpoint_as_lwgeom(), lwmpoint_construct(), lwpoint_as_lwgeom(), lwpoint_construct(), POINTARRAY::npoints, LWLINE::points, ptarray_construct(), ptarray_length_spheroid(), ptarray_set_point4d(), s, sphere_distance(), spheroid_distance(), LWLINE::srid, POINT4D::x, and POINT4D::y.

Referenced by geography_line_interpolate_point().

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