PostGIS  2.2.8dev-r@@SVN_REVISION@@

◆ LWGEOM_line_interpolate_point()

Datum LWGEOM_line_interpolate_point ( PG_FUNCTION_ARGS  )

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

129 {
130  GSERIALIZED *gser = PG_GETARG_GSERIALIZED_P(0);
131  GSERIALIZED *result;
132  double distance = PG_GETARG_FLOAT8(1);
133  LWLINE *line;
134  LWGEOM *geom;
135  LWPOINT *point;
136  POINTARRAY *ipa, *opa;
137  POINT4D pt;
138  int nsegs, i;
139  double length, slength, tlength;
140 
141  if ( distance < 0 || distance > 1 )
142  {
143  elog(ERROR,"line_interpolate_point: 2nd arg isn't within [0,1]");
144  PG_RETURN_NULL();
145  }
146 
147  if ( gserialized_get_type(gser) != LINETYPE )
148  {
149  elog(ERROR,"line_interpolate_point: 1st arg isn't a line");
150  PG_RETURN_NULL();
151  }
152 
153  /* Empty.InterpolatePoint == Point Empty */
154  if ( gserialized_is_empty(gser) )
155  {
157  result = geometry_serialize(lwpoint_as_lwgeom(point));
158  lwpoint_free(point);
159  PG_RETURN_POINTER(result);
160  }
161 
162  geom = lwgeom_from_gserialized(gser);
163  line = lwgeom_as_lwline(geom);
164  ipa = line->points;
165 
166  /* If distance is one of the two extremes, return the point on that
167  * end rather than doing any expensive computations
168  */
169  if ( distance == 0.0 || distance == 1.0 )
170  {
171  if ( distance == 0.0 )
172  getPoint4d_p(ipa, 0, &pt);
173  else
174  getPoint4d_p(ipa, ipa->npoints-1, &pt);
175 
176  opa = ptarray_construct(lwgeom_has_z(geom), lwgeom_has_m(geom), 1);
177  ptarray_set_point4d(opa, 0, &pt);
178 
179  point = lwpoint_construct(line->srid, NULL, opa);
180  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(point)));
181  }
182 
183  /* Interpolate a point on the line */
184  nsegs = ipa->npoints - 1;
185  length = ptarray_length_2d(ipa);
186  tlength = 0;
187  for ( i = 0; i < nsegs; i++ )
188  {
189  POINT4D p1, p2;
190  POINT4D *p1ptr=&p1, *p2ptr=&p2; /* don't break
191  * strict-aliasing rules
192  */
193 
194  getPoint4d_p(ipa, i, &p1);
195  getPoint4d_p(ipa, i+1, &p2);
196 
197  /* Find the relative length of this segment */
198  slength = distance2d_pt_pt((POINT2D*)p1ptr, (POINT2D*)p2ptr)/length;
199 
200  /* If our target distance is before the total length we've seen
201  * so far. create a new point some distance down the current
202  * segment.
203  */
204  if ( distance < tlength + slength )
205  {
206  double dseg = (distance - tlength) / slength;
207  interpolate_point4d(&p1, &p2, &pt, dseg);
208  opa = ptarray_construct(lwgeom_has_z(geom), lwgeom_has_m(geom), 1);
209  ptarray_set_point4d(opa, 0, &pt);
210  point = lwpoint_construct(line->srid, NULL, opa);
211  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(point)));
212  }
213  tlength += slength;
214  }
215 
216  /* Return the last point on the line. This shouldn't happen, but
217  * could if there's some floating point rounding errors. */
218  getPoint4d_p(ipa, ipa->npoints-1, &pt);
219  opa = ptarray_construct(lwgeom_has_z(geom), lwgeom_has_m(geom), 1);
220  ptarray_set_point4d(opa, 0, &pt);
221  point = lwpoint_construct(line->srid, NULL, opa);
222  PG_FREE_IF_COPY(gser, 0);
223  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(point)));
224 }
void ptarray_set_point4d(POINTARRAY *pa, int n, const POINT4D *p4d)
Definition: lwgeom_api.c:536
#define LINETYPE
Definition: liblwgeom.h:71
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:55
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:355
int gserialized_has_m(const GSERIALIZED *gser)
Check if a GSERIALIZED has an M ordinate.
Definition: g_serialized.c:29
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:182
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:2302
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:120
int32_t srid
Definition: liblwgeom.h:405
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
Definition: g_serialized.c:24
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:836
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:806
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:139
LWGEOM * geom
Datum distance(PG_FUNCTION_ARGS)
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:89
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:254
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:98
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:843
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:69
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:231
POINTARRAY * points
Definition: liblwgeom.h:406
Here is the call graph for this function:
Here is the caller graph for this function: