PostGIS  2.1.10dev-r@@SVN_REVISION@@
lwline.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * Copyright (C) 2012 Sandro Santilli <strk@keybit.net>
7  * Copyright (C) 2001-2006 Refractions Research Inc.
8  *
9  * This is free software; you can redistribute and/or modify it under
10  * the terms of the GNU General Public Licence. See the COPYING file.
11  *
12  **********************************************************************/
13 
14 /* basic LWLINE functions */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include "liblwgeom_internal.h"
20 #include "lwgeom_log.h"
21 
22 
23 
24 /*
25  * Construct a new LWLINE. points will *NOT* be copied
26  * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0)
27  */
28 LWLINE *
29 lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
30 {
31  LWLINE *result;
32  result = (LWLINE*) lwalloc(sizeof(LWLINE));
33 
34  LWDEBUG(2, "lwline_construct called.");
35 
36  result->type = LINETYPE;
37 
38  result->flags = points->flags;
39  FLAGS_SET_BBOX(result->flags, bbox?1:0);
40 
41  LWDEBUGF(3, "lwline_construct type=%d", result->type);
42 
43  result->srid = srid;
44  result->points = points;
45  result->bbox = bbox;
46 
47  return result;
48 }
49 
50 LWLINE *
51 lwline_construct_empty(int srid, char hasz, char hasm)
52 {
53  LWLINE *result = lwalloc(sizeof(LWLINE));
54  result->type = LINETYPE;
55  result->flags = gflags(hasz,hasm,0);
56  result->srid = srid;
57  result->points = ptarray_construct_empty(hasz, hasm, 1);
58  result->bbox = NULL;
59  return result;
60 }
61 
62 
63 void lwline_free (LWLINE *line)
64 {
65  if ( ! line ) return;
66 
67  if ( line->bbox )
68  lwfree(line->bbox);
69  if ( line->points )
70  ptarray_free(line->points);
71  lwfree(line);
72 }
73 
74 
75 void printLWLINE(LWLINE *line)
76 {
77  lwnotice("LWLINE {");
78  lwnotice(" ndims = %i", (int)FLAGS_NDIMS(line->flags));
79  lwnotice(" srid = %i", (int)line->srid);
80  printPA(line->points);
81  lwnotice("}");
82 }
83 
84 /* @brief Clone LWLINE object. Serialized point lists are not copied.
85  *
86  * @see ptarray_clone
87  */
88 LWLINE *
90 {
91  LWLINE *ret = lwalloc(sizeof(LWLINE));
92 
93  LWDEBUGF(2, "lwline_clone called with %p", g);
94 
95  memcpy(ret, g, sizeof(LWLINE));
96 
97  ret->points = ptarray_clone(g->points);
98 
99  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
100  return ret;
101 }
102 
103 /* Deep clone LWLINE object. POINTARRAY *is* copied. */
104 LWLINE *
106 {
107  LWLINE *ret = lwalloc(sizeof(LWLINE));
108 
109  LWDEBUGF(2, "lwline_clone_deep called with %p", g);
110  memcpy(ret, g, sizeof(LWLINE));
111 
112  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
113  if ( g->points ) ret->points = ptarray_clone_deep(g->points);
114  FLAGS_SET_READONLY(ret->flags,0);
115 
116  return ret;
117 }
118 
119 
120 void
122 {
124 }
125 
126 void
128 {
129  if ( lwline_is_empty(line) ) return;
130  ptarray_reverse(line->points);
131 }
132 
133 LWLINE *
134 lwline_segmentize2d(LWLINE *line, double dist)
135 {
136  return lwline_construct(line->srid, NULL,
137  ptarray_segmentize2d(line->points, dist));
138 }
139 
140 /* check coordinate equality */
141 char
142 lwline_same(const LWLINE *l1, const LWLINE *l2)
143 {
144  return ptarray_same(l1->points, l2->points);
145 }
146 
147 /*
148  * Construct a LWLINE from an array of point and line geometries
149  * LWLINE dimensions are large enough to host all input dimensions.
150  */
151 LWLINE *
152 lwline_from_lwgeom_array(int srid, uint32_t ngeoms, LWGEOM **geoms)
153 {
154  int i;
155  int hasz = LW_FALSE;
156  int hasm = LW_FALSE;
157  POINTARRAY *pa;
158  LWLINE *line;
159  POINT4D pt;
160 
161  /*
162  * Find output dimensions, check integrity
163  */
164  for (i=0; i<ngeoms; i++)
165  {
166  if ( FLAGS_GET_Z(geoms[i]->flags) ) hasz = LW_TRUE;
167  if ( FLAGS_GET_M(geoms[i]->flags) ) hasm = LW_TRUE;
168  if ( hasz && hasm ) break; /* Nothing more to learn! */
169  }
170 
171  /* ngeoms should be a guess about how many points we have in input */
172  pa = ptarray_construct_empty(hasz, hasm, ngeoms);
173 
174  for ( i=0; i < ngeoms; i++ )
175  {
176  LWGEOM *g = geoms[i];
177 
178  if ( lwgeom_is_empty(g) ) continue;
179 
180  if ( g->type == POINTTYPE )
181  {
182  lwpoint_getPoint4d_p((LWPOINT*)g, &pt);
183  ptarray_append_point(pa, &pt, LW_TRUE);
184  }
185  else if ( g->type == LINETYPE )
186  {
187  ptarray_append_ptarray(pa, ((LWLINE*)g)->points, -1);
188  }
189  else
190  {
191  ptarray_free(pa);
192  lwerror("lwline_from_ptarray: invalid input type: %s", lwtype_name(g->type));
193  return NULL;
194  }
195  }
196 
197  if ( pa->npoints > 0 )
198  line = lwline_construct(srid, NULL, pa);
199  else {
200  /* Is this really any different from the above ? */
201  ptarray_free(pa);
202  line = lwline_construct_empty(srid, hasz, hasm);
203  }
204 
205  return line;
206 }
207 
208 /*
209  * Construct a LWLINE from an array of LWPOINTs
210  * LWLINE dimensions are large enough to host all input dimensions.
211  */
212 LWLINE *
213 lwline_from_ptarray(int srid, uint32_t npoints, LWPOINT **points)
214 {
215  int i;
216  int hasz = LW_FALSE;
217  int hasm = LW_FALSE;
218  POINTARRAY *pa;
219  LWLINE *line;
220  POINT4D pt;
221 
222  /*
223  * Find output dimensions, check integrity
224  */
225  for (i=0; i<npoints; i++)
226  {
227  if ( points[i]->type != POINTTYPE )
228  {
229  lwerror("lwline_from_ptarray: invalid input type: %s", lwtype_name(points[i]->type));
230  return NULL;
231  }
232  if ( FLAGS_GET_Z(points[i]->flags) ) hasz = LW_TRUE;
233  if ( FLAGS_GET_M(points[i]->flags) ) hasm = LW_TRUE;
234  if ( hasz && hasm ) break; /* Nothing more to learn! */
235  }
236 
237  pa = ptarray_construct_empty(hasz, hasm, npoints);
238 
239  for ( i=0; i < npoints; i++ )
240  {
241  if ( ! lwpoint_is_empty(points[i]) )
242  {
243  lwpoint_getPoint4d_p(points[i], &pt);
244  ptarray_append_point(pa, &pt, LW_TRUE);
245  }
246  }
247 
248  if ( pa->npoints > 0 )
249  line = lwline_construct(srid, NULL, pa);
250  else
251  line = lwline_construct_empty(srid, hasz, hasm);
252 
253  return line;
254 }
255 
256 /*
257  * Construct a LWLINE from a LWMPOINT
258  */
259 LWLINE *
260 lwline_from_lwmpoint(int srid, LWMPOINT *mpoint)
261 {
262  uint32_t i;
263  POINTARRAY *pa = NULL;
264  LWGEOM *lwgeom = (LWGEOM*)mpoint;
265  POINT4D pt;
266 
267  char hasz = lwgeom_has_z(lwgeom);
268  char hasm = lwgeom_has_m(lwgeom);
269  uint32_t npoints = mpoint->ngeoms;
270 
271  if ( lwgeom_is_empty(lwgeom) )
272  {
273  return lwline_construct_empty(srid, hasz, hasm);
274  }
275 
276  pa = ptarray_construct(hasz, hasm, npoints);
277 
278  for (i=0; i < npoints; i++)
279  {
280  getPoint4d_p(mpoint->geoms[i]->point, 0, &pt);
281  ptarray_set_point4d(pa, i, &pt);
282  }
283 
284  LWDEBUGF(3, "lwline_from_lwmpoint: constructed pointarray for %d points", mpoint->ngeoms);
285 
286  return lwline_construct(srid, NULL, pa);
287 }
288 
293 LWPOINT*
294 lwline_get_lwpoint(LWLINE *line, int where)
295 {
296  POINT4D pt;
297  LWPOINT *lwpoint;
298  POINTARRAY *pa;
299 
300  if ( lwline_is_empty(line) || where < 0 || where >= line->points->npoints )
301  return NULL;
302 
304  pt = getPoint4d(line->points, where);
305  ptarray_append_point(pa, &pt, LW_TRUE);
306  lwpoint = lwpoint_construct(line->srid, NULL, pa);
307  return lwpoint;
308 }
309 
310 
311 int
312 lwline_add_lwpoint(LWLINE *line, LWPOINT *point, int where)
313 {
314  POINT4D pt;
315  getPoint4d_p(point->point, 0, &pt);
316 
317  if ( ptarray_insert_point(line->points, &pt, where) != LW_SUCCESS )
318  return LW_FAILURE;
319 
320  /* Update the bounding box */
321  if ( line->bbox )
322  {
325  }
326 
327  return LW_SUCCESS;
328 }
329 
330 
331 
332 LWLINE *
333 lwline_removepoint(LWLINE *line, uint32_t index)
334 {
335  POINTARRAY *newpa;
336  LWLINE *ret;
337 
338  newpa = ptarray_removePoint(line->points, index);
339 
340  ret = lwline_construct(line->srid, NULL, newpa);
341  lwgeom_add_bbox((LWGEOM *) ret);
342 
343  return ret;
344 }
345 
346 /*
347  * Note: input will be changed, make sure you have permissions for this.
348  */
349 void
350 lwline_setPoint4d(LWLINE *line, uint32_t index, POINT4D *newpoint)
351 {
352  ptarray_set_point4d(line->points, index, newpoint);
353  /* Update the box, if there is one to update */
354  if ( line->bbox )
355  {
356  lwgeom_drop_bbox((LWGEOM*)line);
357  lwgeom_add_bbox((LWGEOM*)line);
358  }
359 }
360 
365 LWLINE*
366 lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end)
367 {
368  int i = 0;
369  int hasm = 0, hasz = 0;
370  int npoints = 0;
371  double length = 0.0;
372  double length_so_far = 0.0;
373  double m_range = m_end - m_start;
374  double m;
375  POINTARRAY *pa = NULL;
376  POINT3DZ p1, p2;
377 
378  if ( lwline->type != LINETYPE )
379  {
380  lwerror("lwline_construct_from_lwline: only line types supported");
381  return NULL;
382  }
383 
384  hasz = FLAGS_GET_Z(lwline->flags);
385  hasm = 1;
386 
387  /* Null points or npoints == 0 will result in empty return geometry */
388  if ( lwline->points )
389  {
390  npoints = lwline->points->npoints;
391  length = ptarray_length_2d(lwline->points);
392  getPoint3dz_p(lwline->points, 0, &p1);
393  }
394 
395  pa = ptarray_construct(hasz, hasm, npoints);
396 
397  for ( i = 0; i < npoints; i++ )
398  {
399  POINT4D q;
400  POINT2D a, b;
401  getPoint3dz_p(lwline->points, i, &p2);
402  a.x = p1.x;
403  a.y = p1.y;
404  b.x = p2.x;
405  b.y = p2.y;
406  length_so_far += distance2d_pt_pt(&a, &b);
407  if ( length > 0.0 )
408  m = m_start + m_range * length_so_far / length;
409  else
410  m = 0.0;
411  q.x = p2.x;
412  q.y = p2.y;
413  q.z = p2.z;
414  q.m = m;
415  ptarray_set_point4d(pa, i, &q);
416  p1 = p2;
417  }
418 
419  return lwline_construct(lwline->srid, NULL, pa);
420 }
421 
422 LWGEOM*
424 {
426 
427  LWDEBUGF(3, "lwline_remove_repeated_points: npts %p", npts);
428 
429  return (LWGEOM*)lwline_construct(lwline->srid,
430  lwline->bbox ? gbox_copy(lwline->bbox) : 0,
431  npts);
432 }
433 
434 int
436 {
437  if (FLAGS_GET_Z(line->flags))
438  return ptarray_is_closed_3d(line->points);
439 
440  return ptarray_is_closed_2d(line->points);
441 }
442 
443 
444 LWLINE*
445 lwline_force_dims(const LWLINE *line, int hasz, int hasm)
446 {
447  POINTARRAY *pdims = NULL;
448  LWLINE *lineout;
449 
450  /* Return 2D empty */
451  if( lwline_is_empty(line) )
452  {
453  lineout = lwline_construct_empty(line->srid, hasz, hasm);
454  }
455  else
456  {
457  pdims = ptarray_force_dims(line->points, hasz, hasm);
458  lineout = lwline_construct(line->srid, NULL, pdims);
459  }
460  lineout->type = line->type;
461  return lineout;
462 }
463 
464 int lwline_is_empty(const LWLINE *line)
465 {
466  if ( !line->points || line->points->npoints < 1 )
467  return LW_TRUE;
468  return LW_FALSE;
469 }
470 
471 
473 {
474  assert(line);
475  if ( ! line->points )
476  return 0;
477  return line->points->npoints;
478 }
479 
480 LWLINE* lwline_simplify(const LWLINE *iline, double dist)
481 {
482  LWLINE *oline;
483 
484  LWDEBUG(2, "function called");
485 
486  /* Skip empty case */
487  if( lwline_is_empty(iline) )
488  return lwline_clone(iline);
489 
490  static const int minvertices = 0; /* TODO: allow setting this */
491  oline = lwline_construct(iline->srid, NULL, ptarray_simplify(iline->points, dist, minvertices));
492  oline->type = iline->type;
493  return oline;
494 }
495 
496 double lwline_length(const LWLINE *line)
497 {
498  if ( lwline_is_empty(line) )
499  return 0.0;
500  return ptarray_length(line->points);
501 }
502 
503 double lwline_length_2d(const LWLINE *line)
504 {
505  if ( lwline_is_empty(line) )
506  return 0.0;
507  return ptarray_length_2d(line->points);
508 }
void ptarray_set_point4d(POINTARRAY *pa, int n, const POINT4D *p4d)
Definition: lwgeom_api.c:501
double x
Definition: liblwgeom.h:308
#define LINETYPE
Definition: liblwgeom.h:61
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition: g_box.c:362
uint8_t type
Definition: liblwgeom.h:374
double z
Definition: liblwgeom.h:290
double y
Definition: liblwgeom.h:290
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
double m
Definition: liblwgeom.h:308
LWLINE * lwline_from_lwgeom_array(int srid, uint32_t ngeoms, LWGEOM **geoms)
Definition: lwline.c:152
GBOX * bbox
Definition: liblwgeom.h:376
POINTARRAY * ptarray_clone(const POINTARRAY *ptarray)
Clone a POINTARRAY object.
Definition: ptarray.c:643
double x
Definition: liblwgeom.h:290
int lwline_is_closed(const LWLINE *line)
Definition: lwline.c:435
void printLWLINE(LWLINE *line)
Definition: lwline.c:75
LWLINE * lwline_from_lwmpoint(int srid, LWMPOINT *mpoint)
Definition: lwline.c:260
void lwfree(void *mem)
Definition: lwutil.c:190
int npoints
Definition: liblwgeom.h:327
int ptarray_is_closed_3d(const POINTARRAY *pa)
Definition: ptarray.c:678
LWLINE * lwline_simplify(const LWLINE *iline, double dist)
Definition: lwline.c:480
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:57
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:315
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition: ptarray.c:1586
#define LW_SUCCESS
Definition: liblwgeom.h:55
POINTARRAY * ptarray_segmentize2d(const POINTARRAY *ipa, double dist)
Returns a modified POINTARRAY so that no segment is longer than the given distance (computed using 2d...
Definition: ptarray.c:381
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:50
LWLINE * lwline_construct_empty(int srid, char hasz, char hasm)
Definition: lwline.c:51
LWLINE * lwline_from_ptarray(int srid, uint32_t npoints, LWPOINT **points)
Definition: lwline.c:213
int lwline_is_empty(const LWLINE *line)
Definition: lwline.c:464
void lwline_setPoint4d(LWLINE *line, uint32_t index, POINT4D *newpoint)
Definition: lwline.c:350
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
The old function nessecary for ptarray_segmentize2d in ptarray.c.
Definition: measures.c:2123
int32_t srid
Definition: liblwgeom.h:377
LWLINE * lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end)
Re-write the measure ordinate (or add one, if it isn't already there) interpolating the measure betwe...
Definition: lwline.c:366
POINTARRAY * point
Definition: liblwgeom.h:367
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:672
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 lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
Definition: lwgeom.c:542
#define LW_FAILURE
Definition: liblwgeom.h:54
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
double x
Definition: liblwgeom.h:284
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:54
void lwline_release(LWLINE *lwline)
Definition: lwline.c:121
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:164
POINT4D getPoint4d(const POINTARRAY *pa, int n)
Definition: lwgeom_api.c:202
double lwline_length(const LWLINE *line)
Definition: lwline.c:496
int getPoint3dz_p(const POINTARRAY *pa, int n, POINT3DZ *point)
Definition: lwgeom_api.c:305
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:249
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_TRUE, then a duplicate point will not be added.
Definition: ptarray.c:141
#define LW_FALSE
Definition: liblwgeom.h:52
uint8_t flags
Definition: liblwgeom.h:325
char lwline_same(const LWLINE *l1, const LWLINE *l2)
Definition: lwline.c:142
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:51
LWLINE * lwline_clone(const LWLINE *g)
Definition: lwline.c:89
void lwline_reverse(LWLINE *line)
Definition: lwline.c:127
int ptarray_append_ptarray(POINTARRAY *pa1, POINTARRAY *pa2, double gap_tolerance)
Append a POINTARRAY, pa2 to the end of an existing POINTARRAY, pa1.
Definition: ptarray.c:172
int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
Definition: lwpoint.c:42
LWPOINT ** geoms
Definition: liblwgeom.h:426
POINTARRAY * ptarray_clone_deep(const POINTARRAY *ptarray)
Deep clone a pointarray (also clones serialized pointlist)
Definition: ptarray.c:619
POINTARRAY * ptarray_force_dims(const POINTARRAY *pa, int hasz, int hasm)
Definition: ptarray.c:999
LWLINE * lwline_clone_deep(const LWLINE *g)
Definition: lwline.c:105
double y
Definition: liblwgeom.h:284
int ptarray_insert_point(POINTARRAY *pa, const POINT4D *p, int where)
Insert a point into an existing POINTARRAY.
Definition: ptarray.c:84
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:106
int lwline_add_lwpoint(LWLINE *line, LWPOINT *point, int where)
Add a LWPOINT to an LWLINE.
Definition: lwline.c:312
double z
Definition: liblwgeom.h:308
uint8_t gflags(int hasz, int hasm, int geodetic)
Construct a new flags char.
Definition: g_util.c:131
double ptarray_length(const POINTARRAY *pts)
Find the 3d/2d length of the given POINTARRAY (depending on its dimensionality)
Definition: ptarray.c:1614
POINTARRAY * ptarray_simplify(POINTARRAY *inpts, double epsilon, unsigned int minpts)
Definition: ptarray.c:1495
#define FLAGS_SET_BBOX(flags, value)
Definition: liblwgeom.h:114
LWLINE * lwline_removepoint(LWLINE *line, uint32_t index)
Definition: lwline.c:333
LWGEOM * lwline_remove_repeated_points(LWLINE *lwline)
Definition: lwline.c:423
void printPA(POINTARRAY *pa)
Definition: lwgeom_api.c:563
char ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2)
Definition: ptarray.c:443
int lwline_count_vertices(LWLINE *line)
Definition: lwline.c:472
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
int lwpoint_is_empty(const LWPOINT *point)
Definition: lwpoint.c:258
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:555
void ptarray_reverse(POINTARRAY *pa)
Definition: ptarray.c:328
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:107
LWLINE * lwline_segmentize2d(LWLINE *line, double dist)
Definition: lwline.c:134
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
Definition: lwgeom.c:328
LWLINE * lwline_force_dims(const LWLINE *line, int hasz, int hasm)
Definition: lwline.c:445
uint8_t type
Definition: liblwgeom.h:352
void lwline_free(LWLINE *line)
Definition: lwline.c:63
double lwline_length_2d(const LWLINE *line)
Definition: lwline.c:503
POINTARRAY * ptarray_removePoint(POINTARRAY *pa, uint32_t where)
Remove a point from a pointarray.
Definition: ptarray.c:540
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:96
void * lwalloc(size_t size)
Definition: lwutil.c:175
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1229
double y
Definition: liblwgeom.h:308
POINTARRAY * ptarray_remove_repeated_points(POINTARRAY *in)
Definition: ptarray.c:1401
int ngeoms
Definition: liblwgeom.h:424
uint8_t flags
Definition: liblwgeom.h:375
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:118
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:799
LWPOINT * lwline_get_lwpoint(LWLINE *line, int where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition: lwline.c:294
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:217
#define FLAGS_SET_READONLY(flags, value)
Definition: liblwgeom.h:116
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:29
POINTARRAY * points
Definition: liblwgeom.h:378