PostGIS  2.1.10dev-r@@SVN_REVISION@@
Datum LWGEOM_line_interpolate_point ( PG_FUNCTION_ARGS  )

Definition at line 87 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(), result, and LWLINE::srid.

88 {
89  GSERIALIZED *gser = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
91  double distance = PG_GETARG_FLOAT8(1);
92  LWLINE *line;
93  LWGEOM *geom;
94  LWPOINT *point;
95  POINTARRAY *ipa, *opa;
96  POINT4D pt;
97  int nsegs, i;
98  double length, slength, tlength;
99 
100  if ( distance < 0 || distance > 1 )
101  {
102  elog(ERROR,"line_interpolate_point: 2nd arg isnt within [0,1]");
103  PG_RETURN_NULL();
104  }
105 
106  if ( gserialized_get_type(gser) != LINETYPE )
107  {
108  elog(ERROR,"line_interpolate_point: 1st arg isnt a line");
109  PG_RETURN_NULL();
110  }
111 
112  /* Empty.InterpolatePoint == Point Empty */
113  if ( gserialized_is_empty(gser) )
114  {
116  result = geometry_serialize(lwpoint_as_lwgeom(point));
117  lwpoint_free(point);
118  PG_RETURN_POINTER(result);
119  }
120 
121  geom = lwgeom_from_gserialized(gser);
122  line = lwgeom_as_lwline(geom);
123  ipa = line->points;
124 
125  /* If distance is one of the two extremes, return the point on that
126  * end rather than doing any expensive computations
127  */
128  if ( distance == 0.0 || distance == 1.0 )
129  {
130  if ( distance == 0.0 )
131  getPoint4d_p(ipa, 0, &pt);
132  else
133  getPoint4d_p(ipa, ipa->npoints-1, &pt);
134 
135  opa = ptarray_construct(lwgeom_has_z(geom), lwgeom_has_m(geom), 1);
136  ptarray_set_point4d(opa, 0, &pt);
137 
138  point = lwpoint_construct(line->srid, NULL, opa);
139  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(point)));
140  }
141 
142  /* Interpolate a point on the line */
143  nsegs = ipa->npoints - 1;
144  length = ptarray_length_2d(ipa);
145  tlength = 0;
146  for ( i = 0; i < nsegs; i++ )
147  {
148  POINT4D p1, p2;
149  POINT4D *p1ptr=&p1, *p2ptr=&p2; /* don't break
150  * strict-aliasing rules
151  */
152 
153  getPoint4d_p(ipa, i, &p1);
154  getPoint4d_p(ipa, i+1, &p2);
155 
156  /* Find the relative length of this segment */
157  slength = distance2d_pt_pt((POINT2D*)p1ptr, (POINT2D*)p2ptr)/length;
158 
159  /* If our target distance is before the total length we've seen
160  * so far. create a new point some distance down the current
161  * segment.
162  */
163  if ( distance < tlength + slength )
164  {
165  double dseg = (distance - tlength) / slength;
166  interpolate_point4d(&p1, &p2, &pt, dseg);
167  opa = ptarray_construct(lwgeom_has_z(geom), lwgeom_has_m(geom), 1);
168  ptarray_set_point4d(opa, 0, &pt);
169  point = lwpoint_construct(line->srid, NULL, opa);
170  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(point)));
171  }
172  tlength += slength;
173  }
174 
175  /* Return the last point on the line. This shouldn't happen, but
176  * could if there's some floating point rounding errors. */
177  getPoint4d_p(ipa, ipa->npoints-1, &pt);
178  opa = ptarray_construct(lwgeom_has_z(geom), lwgeom_has_m(geom), 1);
179  ptarray_set_point4d(opa, 0, &pt);
180  point = lwpoint_construct(line->srid, NULL, opa);
181  PG_FREE_IF_COPY(gser, 0);
182  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(point)));
183 }
void ptarray_set_point4d(POINTARRAY *pa, int n, const POINT4D *p4d)
Definition: lwgeom_api.c:501
#define LINETYPE
Definition: liblwgeom.h:61
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:56
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:49
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int npoints
Definition: liblwgeom.h:327
int gserialized_has_m(const GSERIALIZED *gser)
Check if a GSERIALIZED has an M ordinate.
Definition: g_serialized.c:30
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:180
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition: ptarray.c:1586
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
The old function nessecary for ptarray_segmentize2d in ptarray.c.
Definition: measures.c:2123
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:118
int32_t srid
Definition: liblwgeom.h:377
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
Definition: g_serialized.c:25
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:792
char ** result
Definition: liblwgeom.h:218
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:771
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:140
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:96
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:799
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:70
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:217
POINTARRAY * points
Definition: liblwgeom.h:378

Here is the call graph for this function: