PostGIS  3.4.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 256 of file lwgeodetic_measures.c.

259 {
260  POINT4D pt;
261  uint32_t i;
262  uint32_t points_to_interpolate;
263  uint32_t points_found = 0;
264  double length;
265  double length_fraction_increment = length_fraction;
266  double length_fraction_consumed = 0;
267  char has_z = (char) lwgeom_has_z(lwline_as_lwgeom(line));
268  char has_m = (char) lwgeom_has_m(lwline_as_lwgeom(line));
269  const POINTARRAY* ipa = line->points;
270  POINTARRAY *opa;
271  POINT4D p1, p2;
272  POINT3D q1, q2;
273  LWGEOM *lwresult;
274  GEOGRAPHIC_POINT g1, g2;
275  uint32_t srid = line->srid;
276 
277  /* Empty.InterpolatePoint == Point Empty */
278  if ( lwline_is_empty(line) )
279  {
280  return lwgeom_clone_deep(lwline_as_lwgeom(line));
281  }
282 
283  /*
284  * If distance is one of the two extremes, return the point on that
285  * end rather than doing any computations
286  */
287  if ( length_fraction == 0.0 || length_fraction == 1.0 )
288  {
289  if ( length_fraction == 0.0 )
290  getPoint4d_p(ipa, 0, &pt);
291  else
292  getPoint4d_p(ipa, ipa->npoints-1, &pt);
293 
294  opa = ptarray_construct(has_z, has_m, 1);
295  ptarray_set_point4d(opa, 0, &pt);
296  return lwpoint_as_lwgeom(lwpoint_construct(srid, NULL, opa));
297  }
298 
299  /* Interpolate points along the line */
300  length = ptarray_length_spheroid(ipa, s);
301  points_to_interpolate = repeat ? (uint32_t) floor(1 / length_fraction) : 1;
302  opa = ptarray_construct(has_z, has_m, points_to_interpolate);
303 
304  getPoint4d_p(ipa, 0, &p1);
305  geographic_point_init(p1.x, p1.y, &g1);
306  for ( i = 0; i < ipa->npoints - 1 && points_found < points_to_interpolate; i++ )
307  {
308  double segment_length_frac;
309  getPoint4d_p(ipa, i+1, &p2);
310  geographic_point_init(p2.x, p2.y, &g2);
311 
312  /* Special sphere case */
313  if ( s->a == s->b )
314  segment_length_frac = s->radius * sphere_distance(&g1, &g2) / length;
315  /* Spheroid case */
316  else
317  segment_length_frac = spheroid_distance(&g1, &g2, s) / length;
318 
319  /* If our target distance is before the total length we've seen
320  * so far. create a new point some distance down the current
321  * segment.
322  */
323  while ( length_fraction < length_fraction_consumed + segment_length_frac && points_found < points_to_interpolate )
324  {
325  geog2cart(&g1, &q1);
326  geog2cart(&g2, &q2);
327  double segment_fraction = (length_fraction - length_fraction_consumed) / segment_length_frac;
328  interpolate_point4d_spheroid(&p1, &p2, &pt, s, segment_fraction);
329  ptarray_set_point4d(opa, points_found++, &pt);
330  length_fraction += length_fraction_increment;
331  }
332 
333  length_fraction_consumed += segment_length_frac;
334 
335  p1 = p2;
336  g1 = g2;
337  }
338 
339  /* Return the last point on the line. This shouldn't happen, but
340  * could if there's some floating point rounding errors. */
341  if (points_found < points_to_interpolate)
342  {
343  getPoint4d_p(ipa, ipa->npoints - 1, &pt);
344  ptarray_set_point4d(opa, points_found, &pt);
345  }
346 
347  if (opa->npoints <= 1)
348  {
349  lwresult = lwpoint_as_lwgeom(lwpoint_construct(srid, NULL, opa));
350  } else {
351  lwresult = lwmpoint_as_lwgeom(lwmpoint_construct(srid, opa));
352  }
353 
354  return lwresult;
355 }
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:3243
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:948
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: