PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ LWGEOM_line_interpolate_point()

Datum LWGEOM_line_interpolate_point ( PG_FUNCTION_ARGS  )

Definition at line 153 of file lwgeom_functions_analytic.c.

References distance(), distance2d_pt_pt(), dumpnode::geom, geometry_serialize(), getPoint4d_p(), gserialized_get_srid(), gserialized_get_type(), gserialized_has_m(), gserialized_has_z(), gserialized_is_empty(), interpolate_point4d(), LINETYPE, lwgeom_as_lwline(), lwgeom_from_gserialized(), lwgeom_has_m(), lwgeom_has_z(), lwpoint_as_lwgeom(), lwpoint_construct(), lwpoint_construct_empty(), lwpoint_free(), POINTARRAY::npoints, LWLINE::points, ptarray_construct(), ptarray_length_2d(), ptarray_set_point4d(), and LWLINE::srid.

Referenced by LWGEOM_SetEffectiveArea().

154 {
155  GSERIALIZED *gser = PG_GETARG_GSERIALIZED_P(0);
156  GSERIALIZED *result;
157  double distance = PG_GETARG_FLOAT8(1);
158  LWLINE *line;
159  LWGEOM *geom;
160  LWPOINT *point;
161  POINTARRAY *ipa, *opa;
162  POINT4D pt;
163  int nsegs, i;
164  double length, slength, tlength;
165 
166  if ( distance < 0 || distance > 1 )
167  {
168  elog(ERROR,"line_interpolate_point: 2nd arg isn't within [0,1]");
169  PG_RETURN_NULL();
170  }
171 
172  if ( gserialized_get_type(gser) != LINETYPE )
173  {
174  elog(ERROR,"line_interpolate_point: 1st arg isn't a line");
175  PG_RETURN_NULL();
176  }
177 
178  /* Empty.InterpolatePoint == Point Empty */
179  if ( gserialized_is_empty(gser) )
180  {
182  result = geometry_serialize(lwpoint_as_lwgeom(point));
183  lwpoint_free(point);
184  PG_RETURN_POINTER(result);
185  }
186 
187  geom = lwgeom_from_gserialized(gser);
188  line = lwgeom_as_lwline(geom);
189  ipa = line->points;
190 
191  /* If distance is one of the two extremes, return the point on that
192  * end rather than doing any expensive computations
193  */
194  if ( distance == 0.0 || distance == 1.0 )
195  {
196  if ( distance == 0.0 )
197  getPoint4d_p(ipa, 0, &pt);
198  else
199  getPoint4d_p(ipa, ipa->npoints-1, &pt);
200 
201  opa = ptarray_construct(lwgeom_has_z(geom), lwgeom_has_m(geom), 1);
202  ptarray_set_point4d(opa, 0, &pt);
203 
204  point = lwpoint_construct(line->srid, NULL, opa);
205  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(point)));
206  }
207 
208  /* Interpolate a point on the line */
209  nsegs = ipa->npoints - 1;
210  length = ptarray_length_2d(ipa);
211  tlength = 0;
212  for ( i = 0; i < nsegs; i++ )
213  {
214  POINT4D p1, p2;
215  POINT4D *p1ptr=&p1, *p2ptr=&p2; /* don't break
216  * strict-aliasing rules
217  */
218 
219  getPoint4d_p(ipa, i, &p1);
220  getPoint4d_p(ipa, i+1, &p2);
221 
222  /* Find the relative length of this segment */
223  slength = distance2d_pt_pt((POINT2D*)p1ptr, (POINT2D*)p2ptr)/length;
224 
225  /* If our target distance is before the total length we've seen
226  * so far. create a new point some distance down the current
227  * segment.
228  */
229  if ( distance < tlength + slength )
230  {
231  double dseg = (distance - tlength) / slength;
232  interpolate_point4d(&p1, &p2, &pt, dseg);
233  opa = ptarray_construct(lwgeom_has_z(geom), lwgeom_has_m(geom), 1);
234  ptarray_set_point4d(opa, 0, &pt);
235  point = lwpoint_construct(line->srid, NULL, opa);
236  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(point)));
237  }
238  tlength += slength;
239  }
240 
241  /* Return the last point on the line. This shouldn't happen, but
242  * could if there's some floating point rounding errors. */
243  getPoint4d_p(ipa, ipa->npoints-1, &pt);
244  opa = ptarray_construct(lwgeom_has_z(geom), lwgeom_has_m(geom), 1);
245  ptarray_set_point4d(opa, 0, &pt);
246  point = lwpoint_construct(line->srid, NULL, opa);
247  PG_FREE_IF_COPY(gser, 0);
248  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(point)));
249 }
void ptarray_set_point4d(POINTARRAY *pa, int n, const POINT4D *p4d)
Definition: lwgeom_api.c:437
#define LINETYPE
Definition: liblwgeom.h:86
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area...
Definition: g_serialized.c:86
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:62
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int npoints
Definition: liblwgeom.h:371
int gserialized_has_m(const GSERIALIZED *gser)
Check if a GSERIALIZED has an M ordinate.
Definition: g_serialized.c:50
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:213
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it&#39;s 3d)
Definition: ptarray.c:1692
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
The old function nessecary for ptarray_segmentize2d in ptarray.c.
Definition: measures.c:2317
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:151
int32_t srid
Definition: liblwgeom.h:421
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
Definition: g_serialized.c:45
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:885
void interpolate_point4d(POINT4D *A, 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:680
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:179
LWGEOM * geom
Datum distance(PG_FUNCTION_ARGS)
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:138
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:303
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:892
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:100
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:122
POINTARRAY * points
Definition: liblwgeom.h:422
Here is the call graph for this function:
Here is the caller graph for this function: