PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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 {
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 * lwmpoint_as_lwgeom(const LWMPOINT *obj)
Definition lwgeom.c:332
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:372
LWMPOINT * lwmpoint_construct(int32_t srid, const POINTARRAY *pa)
Definition lwmpoint.c:52
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition lwpoint.c:129
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition lwgeom.c:962
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
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:969
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
Definition lwgeom_api.c:369
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
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition lwgeom.c:557
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)
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: