PostGIS  2.3.8dev-r@@SVN_REVISION@@

◆ LWGEOM_line_interpolate_point()

Datum LWGEOM_line_interpolate_point ( PG_FUNCTION_ARGS  )

Definition at line 150 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().

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