PostGIS  2.5.1dev-r@@SVN_REVISION@@
lwcollection.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * PostGIS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * PostGIS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright (C) 2001-2006 Refractions Research Inc.
22  *
23  **********************************************************************/
24 
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include "liblwgeom_internal.h"
30 #include "lwgeom_log.h"
31 
32 
33 #define CHECK_LWGEOM_ZM 1
34 
35 void
37 {
39 }
40 
41 
44  uint32_t ngeoms, LWGEOM **geoms)
45 {
46  LWCOLLECTION *ret;
47  int hasz, hasm;
48 #ifdef CHECK_LWGEOM_ZM
49  char zm;
50  uint32_t i;
51 #endif
52 
53  LWDEBUGF(2, "lwcollection_construct called with %d, %d, %p, %d, %p.", type, srid, bbox, ngeoms, geoms);
54 
55  if( ! lwtype_is_collection(type) )
56  lwerror("Non-collection type specified in collection constructor!");
57 
58  hasz = 0;
59  hasm = 0;
60  if ( ngeoms > 0 )
61  {
62  hasz = FLAGS_GET_Z(geoms[0]->flags);
63  hasm = FLAGS_GET_M(geoms[0]->flags);
64 #ifdef CHECK_LWGEOM_ZM
65  zm = FLAGS_GET_ZM(geoms[0]->flags);
66 
67  LWDEBUGF(3, "lwcollection_construct type[0]=%d", geoms[0]->type);
68 
69  for (i=1; i<ngeoms; i++)
70  {
71  LWDEBUGF(3, "lwcollection_construct type=[%d]=%d", i, geoms[i]->type);
72 
73  if ( zm != FLAGS_GET_ZM(geoms[i]->flags) )
74  lwerror("lwcollection_construct: mixed dimension geometries: %d/%d", zm, FLAGS_GET_ZM(geoms[i]->flags));
75  }
76 #endif
77  }
78 
79 
80  ret = lwalloc(sizeof(LWCOLLECTION));
81  ret->type = type;
82  ret->flags = gflags(hasz,hasm,0);
83  FLAGS_SET_BBOX(ret->flags, bbox?1:0);
84  ret->srid = srid;
85  ret->ngeoms = ngeoms;
86  ret->maxgeoms = ngeoms;
87  ret->geoms = geoms;
88  ret->bbox = bbox;
89 
90  return ret;
91 }
92 
94 lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
95 {
96  LWCOLLECTION *ret;
97  if( ! lwtype_is_collection(type) )
98  lwerror("Non-collection type specified in collection constructor!");
99 
100  ret = lwalloc(sizeof(LWCOLLECTION));
101  ret->type = type;
102  ret->flags = gflags(hasz,hasm,0);
103  ret->srid = srid;
104  ret->ngeoms = 0;
105  ret->maxgeoms = 1; /* Allocate room for sub-members, just in case. */
106  ret->geoms = lwalloc(ret->maxgeoms * sizeof(LWGEOM*));
107  ret->bbox = NULL;
108 
109  return ret;
110 }
111 
112 LWGEOM *
114 {
115  return (LWGEOM *)col->geoms[gnum];
116 }
117 
122 LWCOLLECTION *
124 {
125  uint32_t i;
126  LWCOLLECTION *ret = lwalloc(sizeof(LWCOLLECTION));
127  memcpy(ret, g, sizeof(LWCOLLECTION));
128  if ( g->ngeoms > 0 )
129  {
130  ret->geoms = lwalloc(sizeof(LWGEOM *)*g->ngeoms);
131  for (i=0; i<g->ngeoms; i++)
132  {
133  ret->geoms[i] = lwgeom_clone(g->geoms[i]);
134  }
135  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
136  }
137  else
138  {
139  ret->bbox = NULL; /* empty collection */
140  ret->geoms = NULL;
141  }
142  return ret;
143 }
144 
148 LWCOLLECTION *
150 {
151  uint32_t i;
152  LWCOLLECTION *ret = lwalloc(sizeof(LWCOLLECTION));
153  memcpy(ret, g, sizeof(LWCOLLECTION));
154  if ( g->ngeoms > 0 )
155  {
156  ret->geoms = lwalloc(sizeof(LWGEOM *)*g->ngeoms);
157  for (i=0; i<g->ngeoms; i++)
158  {
159  ret->geoms[i] = lwgeom_clone_deep(g->geoms[i]);
160  }
161  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
162  }
163  else
164  {
165  ret->bbox = NULL; /* empty collection */
166  ret->geoms = NULL;
167  }
168  return ret;
169 }
170 
175 {
176  if ( ngeoms <= col->maxgeoms ) return;
177 
178  /* Allocate more space if we need it */
179  do { col->maxgeoms *= 2; } while ( col->maxgeoms < ngeoms );
180  col->geoms = lwrealloc(col->geoms, sizeof(LWGEOM*) * col->maxgeoms);
181 }
182 
188 {
189  if (!col || !geom) return NULL;
190 
191  if (!col->geoms && (col->ngeoms || col->maxgeoms))
192  {
193  lwerror("Collection is in inconsistent state. Null memory but non-zero collection counts.");
194  return NULL;
195  }
196 
197  /* Check type compatibility */
198  if ( ! lwcollection_allows_subtype(col->type, geom->type) ) {
199  lwerror("%s cannot contain %s element", lwtype_name(col->type), lwtype_name(geom->type));
200  return NULL;
201  }
202 
203  /* In case this is a truly empty, make some initial space */
204  if (!col->geoms)
205  {
206  col->maxgeoms = 2;
207  col->ngeoms = 0;
208  col->geoms = lwalloc(col->maxgeoms * sizeof(LWGEOM*));
209  }
210 
211  /* Allocate more space if we need it */
212  lwcollection_reserve(col, col->ngeoms + 1);
213 
214 #if PARANOIA_LEVEL > 1
215  /* See http://trac.osgeo.org/postgis/ticket/2933 */
216  /* Make sure we don't already have a reference to this geom */
217  {
218  uint32_t i = 0;
219  for (i = 0; i < col->ngeoms; i++)
220  {
221  if (col->geoms[i] == geom)
222  {
223  lwerror("%s [%d] found duplicate geometry in collection %p == %p", __FILE__, __LINE__, col->geoms[i], geom);
224  return col;
225  }
226  }
227  }
228 #endif
229 
230  col->geoms[col->ngeoms] = (LWGEOM*)geom;
231  col->ngeoms++;
232  return col;
233 }
234 
239 LWCOLLECTION *
241 {
242  uint32_t i;
243  if (!col1 || !col2) return NULL;
244  for (i = 0; i < col2->ngeoms; i++)
245  col1 = lwcollection_add_lwgeom(col1, col2->geoms[i]);
246  return col1;
247 }
248 
250 lwcollection_segmentize2d(const LWCOLLECTION* col, double dist)
251 {
252  uint32_t i, j;
253  LWGEOM** newgeoms;
254 
255  if (!col->ngeoms) return lwcollection_clone(col);
256 
257  newgeoms = lwalloc(sizeof(LWGEOM*) * col->ngeoms);
258  for (i = 0; i < col->ngeoms; i++)
259  {
260  newgeoms[i] = lwgeom_segmentize2d(col->geoms[i], dist);
261  if (!newgeoms[i])
262  {
263  for (j = 0; j < i; j++)
264  lwgeom_free(newgeoms[j]);
265  lwfree(newgeoms);
266  return NULL;
267  }
268  }
269 
270  return lwcollection_construct(
271  col->type, col->srid, NULL, col->ngeoms, newgeoms);
272 }
273 
277 char
279 {
280  uint32_t i;
281 
282  LWDEBUG(2, "lwcollection_same called");
283 
284  if ( c1->type != c2->type ) return LW_FALSE;
285  if ( c1->ngeoms != c2->ngeoms ) return LW_FALSE;
286 
287  for ( i = 0; i < c1->ngeoms; i++ )
288  {
289  if ( ! lwgeom_same(c1->geoms[i], c2->geoms[i]) )
290  return LW_FALSE;
291  }
292 
293  /* Former method allowed out-of-order equality between collections
294 
295  hit = lwalloc(sizeof(uint32_t)*c1->ngeoms);
296  memset(hit, 0, sizeof(uint32_t)*c1->ngeoms);
297 
298  for (i=0; i<c1->ngeoms; i++)
299  {
300  char found=0;
301  for (j=0; j<c2->ngeoms; j++)
302  {
303  if ( hit[j] ) continue;
304  if ( lwgeom_same(c1->geoms[i], c2->geoms[j]) )
305  {
306  hit[j] = 1;
307  found=1;
308  break;
309  }
310  }
311  if ( ! found ) return LW_FALSE;
312  }
313  */
314 
315  return LW_TRUE;
316 }
317 
319 {
320  uint32_t i;
321  int ngeoms = 0;
322 
323  if ( ! col )
324  {
325  lwerror("Null input geometry.");
326  return 0;
327  }
328 
329  for ( i = 0; i < col->ngeoms; i++ )
330  {
331  if ( col->geoms[i])
332  {
333  switch (col->geoms[i]->type)
334  {
335  case POINTTYPE:
336  case LINETYPE:
337  case CIRCSTRINGTYPE:
338  case POLYGONTYPE:
339  ngeoms += 1;
340  break;
341  case MULTIPOINTTYPE:
342  case MULTILINETYPE:
343  case MULTICURVETYPE:
344  case MULTIPOLYGONTYPE:
345  ngeoms += col->ngeoms;
346  break;
347  case COLLECTIONTYPE:
348  ngeoms += lwcollection_ngeoms((LWCOLLECTION*)col->geoms[i]);
349  break;
350  }
351  }
352  }
353  return ngeoms;
354 }
355 
357 {
358  uint32_t i;
359  if ( ! col ) return;
360 
361  if ( col->bbox )
362  {
363  lwfree(col->bbox);
364  }
365  for ( i = 0; i < col->ngeoms; i++ )
366  {
367  LWDEBUGF(4,"freeing geom[%d]", i);
368  if ( col->geoms && col->geoms[i] )
369  lwgeom_free(col->geoms[i]);
370  }
371  if ( col->geoms )
372  {
373  lwfree(col->geoms);
374  }
375  lwfree(col);
376 }
377 
378 
387 {
388  uint32_t i = 0;
389  LWGEOM** geomlist;
390  LWCOLLECTION* outcol;
391  int geomlistsize = 16;
392  int geomlistlen = 0;
393  uint8_t outtype;
394 
395  if (!col) return NULL;
396 
397  switch (type)
398  {
399  case POINTTYPE:
400  outtype = MULTIPOINTTYPE;
401  break;
402  case LINETYPE:
403  outtype = MULTILINETYPE;
404  break;
405  case POLYGONTYPE:
406  outtype = MULTIPOLYGONTYPE;
407  break;
408  default:
409  lwerror(
410  "Only POLYGON, LINESTRING and POINT are supported by "
411  "lwcollection_extract. %s requested.",
412  lwtype_name(type));
413  return NULL;
414  }
415 
416  geomlist = lwalloc(sizeof(LWGEOM*) * geomlistsize);
417 
418  /* Process each sub-geometry */
419  for (i = 0; i < col->ngeoms; i++)
420  {
421  int subtype = col->geoms[i]->type;
422  /* Don't bother adding empty sub-geometries */
423  if (lwgeom_is_empty(col->geoms[i])) continue;
424  /* Copy our sub-types into the output list */
425  if (subtype == type)
426  {
427  /* We've over-run our buffer, double the memory segment
428  */
429  if (geomlistlen == geomlistsize)
430  {
431  geomlistsize *= 2;
432  geomlist = lwrealloc(
433  geomlist, sizeof(LWGEOM*) * geomlistsize);
434  }
435  geomlist[geomlistlen] = lwgeom_clone(col->geoms[i]);
436  geomlistlen++;
437  }
438  /* Recurse into sub-collections */
439  if (lwtype_is_collection(subtype))
440  {
441  uint32_t j = 0;
443  (LWCOLLECTION*)col->geoms[i], type);
444  for (j = 0; j < tmpcol->ngeoms; j++)
445  {
446  /* We've over-run our buffer, double the memory
447  * segment */
448  if (geomlistlen == geomlistsize)
449  {
450  geomlistsize *= 2;
451  geomlist = lwrealloc(geomlist,
452  sizeof(LWGEOM*) *
453  geomlistsize);
454  }
455  geomlist[geomlistlen] = tmpcol->geoms[j];
456  geomlistlen++;
457  }
458  if (tmpcol->ngeoms) lwfree(tmpcol->geoms);
459  if (tmpcol->bbox) lwfree(tmpcol->bbox);
460  lwfree(tmpcol);
461  }
462  }
463 
464  if (geomlistlen > 0)
465  {
466  GBOX gbox;
467  outcol = lwcollection_construct(
468  outtype, col->srid, NULL, geomlistlen, geomlist);
469  lwgeom_calculate_gbox((LWGEOM*)outcol, &gbox);
470  outcol->bbox = gbox_copy(&gbox);
471  }
472  else
473  {
474  lwfree(geomlist);
475  outcol = lwcollection_construct_empty(outtype,
476  col->srid,
477  FLAGS_GET_Z(col->flags),
478  FLAGS_GET_M(col->flags));
479  }
480 
481  return outcol;
482 }
483 
485 lwcollection_force_dims(const LWCOLLECTION *col, int hasz, int hasm)
486 {
487  LWCOLLECTION *colout;
488 
489  /* Return 2D empty */
490  if( lwcollection_is_empty(col) )
491  {
492  colout = lwcollection_construct_empty(col->type, col->srid, hasz, hasm);
493  }
494  else
495  {
496  uint32_t i;
497  LWGEOM **geoms = NULL;
498  geoms = lwalloc(sizeof(LWGEOM*) * col->ngeoms);
499  for( i = 0; i < col->ngeoms; i++ )
500  {
501  geoms[i] = lwgeom_force_dims(col->geoms[i], hasz, hasm);
502  }
503  colout = lwcollection_construct(col->type, col->srid, NULL, col->ngeoms, geoms);
504  }
505  return colout;
506 }
507 
509 {
510  uint32_t i;
511  if ( (col->ngeoms == 0) || (!col->geoms) )
512  return LW_TRUE;
513  for( i = 0; i < col->ngeoms; i++ )
514  {
515  if ( ! lwgeom_is_empty(col->geoms[i]) ) return LW_FALSE;
516  }
517  return LW_TRUE;
518 }
519 
520 
522 {
523  uint32_t i = 0;
524  uint32_t v = 0; /* vertices */
525  assert(col);
526  for ( i = 0; i < col->ngeoms; i++ )
527  {
528  v += lwgeom_count_vertices(col->geoms[i]);
529  }
530  return v;
531 }
532 
533 
534 int lwcollection_allows_subtype(int collectiontype, int subtype)
535 {
536  if ( collectiontype == COLLECTIONTYPE )
537  return LW_TRUE;
538  if ( collectiontype == MULTIPOINTTYPE &&
539  subtype == POINTTYPE )
540  return LW_TRUE;
541  if ( collectiontype == MULTILINETYPE &&
542  subtype == LINETYPE )
543  return LW_TRUE;
544  if ( collectiontype == MULTIPOLYGONTYPE &&
545  subtype == POLYGONTYPE )
546  return LW_TRUE;
547  if ( collectiontype == COMPOUNDTYPE &&
548  (subtype == LINETYPE || subtype == CIRCSTRINGTYPE) )
549  return LW_TRUE;
550  if ( collectiontype == CURVEPOLYTYPE &&
551  (subtype == CIRCSTRINGTYPE || subtype == LINETYPE || subtype == COMPOUNDTYPE) )
552  return LW_TRUE;
553  if ( collectiontype == MULTICURVETYPE &&
554  (subtype == CIRCSTRINGTYPE || subtype == LINETYPE || subtype == COMPOUNDTYPE) )
555  return LW_TRUE;
556  if ( collectiontype == MULTISURFACETYPE &&
557  (subtype == POLYGONTYPE || subtype == CURVEPOLYTYPE) )
558  return LW_TRUE;
559  if ( collectiontype == POLYHEDRALSURFACETYPE &&
560  subtype == POLYGONTYPE )
561  return LW_TRUE;
562  if ( collectiontype == TINTYPE &&
563  subtype == TRIANGLETYPE )
564  return LW_TRUE;
565 
566  /* Must be a bad combination! */
567  return LW_FALSE;
568 }
569 
570 int
572 {
573  if ( col->ngeoms < 1 )
574  return LW_FAILURE;
575 
576  return lwgeom_startpoint(col->geoms[0], pt);
577 }
578 
579 
#define LINETYPE
Definition: liblwgeom.h:85
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition: g_box.c:433
void lwcollection_release(LWCOLLECTION *lwcollection)
Definition: lwcollection.c:36
GBOX * bbox
Definition: liblwgeom.h:400
#define MULTICURVETYPE
Definition: liblwgeom.h:94
void lwfree(void *mem)
Definition: lwutil.c:244
uint8_t type
Definition: liblwgeom.h:505
int lwgeom_startpoint(const LWGEOM *lwgeom, POINT4D *pt)
Definition: lwgeom.c:2115
#define POLYGONTYPE
Definition: liblwgeom.h:86
LWCOLLECTION * lwcollection_clone(const LWCOLLECTION *g)
Clone LWCOLLECTION object.
Definition: lwcollection.c:123
#define CURVEPOLYTYPE
Definition: liblwgeom.h:93
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
#define COMPOUNDTYPE
Definition: liblwgeom.h:92
#define MULTIPOINTTYPE
Definition: liblwgeom.h:87
GBOX * bbox
Definition: liblwgeom.h:507
#define FLAGS_GET_ZM(flags)
Definition: liblwgeom.h:152
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:356
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
#define TRIANGLETYPE
Definition: liblwgeom.h:97
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:96
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition: lwgeom.c:520
void lwcollection_reserve(LWCOLLECTION *col, uint32_t ngeoms)
Ensure the collection can hold up at least ngeoms.
Definition: lwcollection.c:174
uint32_t maxgeoms
Definition: liblwgeom.h:510
uint32_t ngeoms
Definition: liblwgeom.h:509
LWGEOM * lwgeom_segmentize2d(const LWGEOM *line, double dist)
Definition: lwgeom.c:762
int lwcollection_is_empty(const LWCOLLECTION *col)
Definition: lwcollection.c:508
#define LW_FAILURE
Definition: liblwgeom.h:78
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
unsigned int uint32_t
Definition: uthash.h:78
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
Calculate bounding box of a geometry, automatically taking into account whether it is cartesian or ge...
Definition: lwgeom.c:746
uint8_t flags
Definition: liblwgeom.h:506
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
Definition: lwcollection.c:43
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
LWCOLLECTION * lwcollection_segmentize2d(const LWCOLLECTION *col, double dist)
Definition: lwcollection.c:250
#define LW_FALSE
Definition: liblwgeom.h:76
LWCOLLECTION * lwcollection_extract(LWCOLLECTION *col, int type)
Takes a potentially heterogeneous collection and returns a homogeneous collection consisting only of ...
Definition: lwcollection.c:386
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:187
int lwcollection_ngeoms(const LWCOLLECTION *col)
Definition: lwcollection.c:318
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:75
LWCOLLECTION * lwcollection_concat_in_place(LWCOLLECTION *col1, const LWCOLLECTION *col2)
Appends all geometries from col2 to col1 in place.
Definition: lwcollection.c:240
LWGEOM ** geoms
Definition: liblwgeom.h:511
#define TINTYPE
Definition: liblwgeom.h:98
int lwtype_is_collection(uint8_t type)
Determine whether a type number is a collection or not.
Definition: lwgeom.c:1093
char lwcollection_same(const LWCOLLECTION *c1, const LWCOLLECTION *c2)
check for same geometry composition
Definition: lwcollection.c:278
int lwcollection_allows_subtype(int collectiontype, int subtype)
Check if subtype is allowed in collectiontype.
Definition: lwcollection.c:534
int32_t srid
Definition: liblwgeom.h:508
LWCOLLECTION * lwcollection_clone_deep(const LWCOLLECTION *g)
Deep clone LWCOLLECTION object.
Definition: lwcollection.c:149
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:139
LWGEOM * lwgeom_force_dims(const LWGEOM *lwgeom, int hasz, int hasm)
Definition: lwgeom.c:808
LWGEOM * lwgeom_clone(const LWGEOM *lwgeom)
Clone LWGEOM object.
Definition: lwgeom.c:482
char lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
geom1 same as geom2 iff
Definition: lwgeom.c:582
uint8_t gflags(int hasz, int hasm, int geodetic)
Construct a new flags char.
Definition: g_util.c:145
uint32_t lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1235
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:89
#define FLAGS_SET_BBOX(flags, value)
Definition: liblwgeom.h:147
LWCOLLECTION * lwcollection_force_dims(const LWCOLLECTION *col, int hasz, int hasm)
Definition: lwcollection.c:485
int lwcollection_startpoint(const LWCOLLECTION *col, POINT4D *pt)
Definition: lwcollection.c:571
#define MULTISURFACETYPE
Definition: liblwgeom.h:95
LWGEOM * lwcollection_getsubgeom(LWCOLLECTION *col, int gnum)
Definition: lwcollection.c:113
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:237
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:84
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:140
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
Definition: lwgeom.c:459
uint8_t type
Definition: liblwgeom.h:398
type
Definition: ovdump.py:41
uint32_t lwcollection_count_vertices(LWCOLLECTION *col)
Definition: lwcollection.c:521
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:91
void * lwalloc(size_t size)
Definition: lwutil.c:229
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:1393
#define MULTILINETYPE
Definition: liblwgeom.h:88
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
unsigned char uint8_t
Definition: uthash.h:79
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
#define COLLECTIONTYPE
Definition: liblwgeom.h:90
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:300