PostGIS  2.4.9dev-r@@SVN_REVISION@@
lwin_geojson.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 2013 Sandro Santilli <strk@kbt.io>
22  * Copyright 2011 Kashif Rasul <kashif.rasul@gmail.com>
23  *
24  **********************************************************************/
25 
26 
27 #include <assert.h>
28 #include "liblwgeom.h"
29 #include "lwgeom_log.h"
30 #include "../postgis_config.h"
31 
32 #if defined(HAVE_LIBJSON) || defined(HAVE_LIBJSON_C) /* --{ */
33 
34 #define JSON_C_VERSION_013 (13 << 8)
35 
36 #ifdef HAVE_LIBJSON_C
37 #include <json-c/json.h>
38 #if !defined(JSON_C_VERSION_NUM) || JSON_C_VERSION_NUM < JSON_C_VERSION_013
39 #include <json-c/json_object_private.h>
40 #endif
41 #else
42 #include <json/json.h>
43 #if !defined(JSON_C_VERSION_NUM) || JSON_C_VERSION_NUM < JSON_C_VERSION_013
44 #include <json/json_object_private.h>
45 #endif
46 #endif
47 
48 #ifndef JSON_C_VERSION
49 /* Adds support for libjson < 0.10 */
50 # define json_tokener_error_desc(x) json_tokener_errors[(x)]
51 #endif
52 
53 #include <string.h>
54 
55 static void geojson_lwerror(char *msg, __attribute__((__unused__)) int error_code)
56 {
57  LWDEBUGF(3, "lwgeom_from_geojson ERROR %i", error_code);
58  lwerror("%s", msg);
59 }
60 
61 /* Prototype */
62 static LWGEOM* parse_geojson(json_object *geojson, int *hasz, int root_srid);
63 
64 static json_object*
65 findMemberByName(json_object* poObj, const char* pszName )
66 {
67  json_object* poTmp;
68  json_object_iter it;
69 
70  poTmp = poObj;
71 
72  if( NULL == pszName || NULL == poObj)
73  return NULL;
74 
75  it.key = NULL;
76  it.val = NULL;
77  it.entry = NULL;
78 
79  if( NULL != json_object_get_object(poTmp) )
80  {
81  if( NULL == json_object_get_object(poTmp)->head )
82  {
83  geojson_lwerror("invalid GeoJSON representation", 2);
84  return NULL;
85  }
86 
87  for( it.entry = json_object_get_object(poTmp)->head;
88  ( it.entry ?
89  ( it.key = (char*)it.entry->k,
90  it.val = (json_object*)it.entry->v, it.entry) : 0);
91  it.entry = it.entry->next)
92  {
93  if( strcasecmp((char *)it.key, pszName )==0 )
94  return it.val;
95  }
96  }
97 
98  return NULL;
99 }
100 
101 
102 static int
103 parse_geojson_coord(json_object *poObj, int *hasz, POINTARRAY *pa)
104 {
105  POINT4D pt;
106 
107  LWDEBUGF(3, "parse_geojson_coord called for object %s.", json_object_to_json_string( poObj ) );
108 
109  if( json_type_array == json_object_get_type( poObj ) )
110  {
111 
112  json_object* poObjCoord = NULL;
113  const int nSize = json_object_array_length( poObj );
114  LWDEBUGF(3, "parse_geojson_coord called for array size %d.", nSize );
115 
116  if ( nSize < 2 )
117  {
118  geojson_lwerror("Too few ordinates in GeoJSON", 4);
119  return LW_FAILURE;
120  }
121 
122  /* Read X coordinate */
123  poObjCoord = json_object_array_get_idx( poObj, 0 );
124  pt.x = json_object_get_double( poObjCoord );
125  LWDEBUGF(3, "parse_geojson_coord pt.x = %f.", pt.x );
126 
127  /* Read Y coordinate */
128  poObjCoord = json_object_array_get_idx( poObj, 1 );
129  pt.y = json_object_get_double( poObjCoord );
130  LWDEBUGF(3, "parse_geojson_coord pt.y = %f.", pt.y );
131 
132  if( nSize > 2 ) /* should this be >= 3 ? */
133  {
134  /* Read Z coordinate */
135  poObjCoord = json_object_array_get_idx( poObj, 2 );
136  pt.z = json_object_get_double( poObjCoord );
137  LWDEBUGF(3, "parse_geojson_coord pt.z = %f.", pt.z );
138  *hasz = LW_TRUE;
139  }
140  else if ( nSize == 2 )
141  {
142  *hasz = LW_FALSE;
143  /* Initialize Z coordinate, if required */
144  if ( FLAGS_GET_Z(pa->flags) ) pt.z = 0.0;
145  }
146  else
147  {
148  /* TODO: should we account for nSize > 3 ? */
149  /* more than 3 coordinates, we're just dropping dimensions here... */
150  }
151 
152  /* Initialize M coordinate, if required */
153  if ( FLAGS_GET_M(pa->flags) ) pt.m = 0.0;
154 
155  }
156  else
157  {
158  /* If it's not an array, just don't handle it */
159  return LW_FAILURE;
160  }
161 
162  return ptarray_append_point(pa, &pt, LW_TRUE);
163 }
164 
165 static LWGEOM*
166 parse_geojson_point(json_object *geojson, int *hasz, int root_srid)
167 {
168  LWGEOM *geom;
169  POINTARRAY *pa;
170  json_object* coords = NULL;
171 
172  LWDEBUGF(3, "parse_geojson_point called with root_srid = %d.", root_srid );
173 
174  coords = findMemberByName( geojson, "coordinates" );
175  if ( ! coords )
176  {
177  geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
178  return NULL;
179  }
180 
181  pa = ptarray_construct_empty(1, 0, 1);
182  parse_geojson_coord(coords, hasz, pa);
183 
184  geom = (LWGEOM *) lwpoint_construct(root_srid, NULL, pa);
185  LWDEBUG(2, "parse_geojson_point finished.");
186  return geom;
187 }
188 
189 static LWGEOM*
190 parse_geojson_linestring(json_object *geojson, int *hasz, int root_srid)
191 {
192  LWGEOM *geom;
193  POINTARRAY *pa;
194  json_object* points = NULL;
195  int i = 0;
196 
197  LWDEBUG(2, "parse_geojson_linestring called.");
198 
199  points = findMemberByName( geojson, "coordinates" );
200  if ( ! points )
201  {
202  geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
203  return NULL;
204  }
205 
206  pa = ptarray_construct_empty(1, 0, 1);
207 
208  if( json_type_array == json_object_get_type( points ) )
209  {
210  const int nPoints = json_object_array_length( points );
211  for(i = 0; i < nPoints; ++i)
212  {
213  json_object* coords = NULL;
214  coords = json_object_array_get_idx( points, i );
215  parse_geojson_coord(coords, hasz, pa);
216  }
217  }
218 
219  geom = (LWGEOM *) lwline_construct(root_srid, NULL, pa);
220 
221  LWDEBUG(2, "parse_geojson_linestring finished.");
222  return geom;
223 }
224 
225 static LWGEOM*
226 parse_geojson_polygon(json_object *geojson, int *hasz, int root_srid)
227 {
228  POINTARRAY **ppa = NULL;
229  json_object* rings = NULL;
230  json_object* points = NULL;
231  int i = 0, j = 0;
232  int nRings = 0, nPoints = 0;
233 
234  rings = findMemberByName( geojson, "coordinates" );
235  if ( ! rings )
236  {
237  geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
238  return NULL;
239  }
240 
241  if ( json_type_array != json_object_get_type(rings) )
242  {
243  geojson_lwerror("The 'coordinates' in GeoJSON are not an array", 4);
244  return NULL;
245  }
246 
247  nRings = json_object_array_length( rings );
248 
249  /* No rings => POLYGON EMPTY */
250  if ( ! nRings )
251  {
252  return (LWGEOM *)lwpoly_construct_empty(root_srid, 0, 0);
253  }
254 
255  for ( i = 0; i < nRings; i++ )
256  {
257  points = json_object_array_get_idx(rings, i);
258  if ( ! points || json_object_get_type(points) != json_type_array )
259  {
260  geojson_lwerror("The 'coordinates' in GeoJSON ring are not an array", 4);
261  return NULL;
262  }
263  nPoints = json_object_array_length(points);
264 
265  if ( ! ppa )
266  ppa = (POINTARRAY**)lwalloc(sizeof(POINTARRAY*) * nRings);
267 
268  ppa[i] = ptarray_construct_empty(1, 0, 1);
269  for ( j = 0; j < nPoints; j++ )
270  {
271  json_object* coords = NULL;
272  coords = json_object_array_get_idx( points, j );
273  if (LW_FAILURE == parse_geojson_coord(coords, hasz, ppa[i]))
274  {
275  int k;
276  for (k = 0; k <= i; k++)
277  {
278  ptarray_free(ppa[k]);
279  }
280  lwfree(ppa);
281  geojson_lwerror("The 'coordinates' in GeoJSON polygon are not sufficiently nested", 4);
282  return NULL;
283  }
284  }
285  }
286 
287  /* All the rings were empty! */
288  if ( ! ppa )
289  return (LWGEOM *)lwpoly_construct_empty(root_srid, 0, 0);
290 
291  return (LWGEOM *) lwpoly_construct(root_srid, NULL, nRings, ppa);
292 }
293 
294 static LWGEOM*
295 parse_geojson_multipoint(json_object *geojson, int *hasz, int root_srid)
296 {
297  LWGEOM *geom;
298  int i = 0;
299  json_object* poObjPoints = NULL;
300 
301  if (!root_srid)
302  {
303  geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, root_srid, 1, 0);
304  }
305  else
306  {
308  }
309 
310  poObjPoints = findMemberByName( geojson, "coordinates" );
311  if ( ! poObjPoints )
312  {
313  geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
314  return NULL;
315  }
316 
317  if( json_type_array == json_object_get_type( poObjPoints ) )
318  {
319  const int nPoints = json_object_array_length( poObjPoints );
320  for( i = 0; i < nPoints; ++i)
321  {
322  POINTARRAY *pa;
323  json_object* poObjCoords = NULL;
324  poObjCoords = json_object_array_get_idx( poObjPoints, i );
325 
326  pa = ptarray_construct_empty(1, 0, 1);
327  parse_geojson_coord(poObjCoords, hasz, pa);
328 
329  geom = (LWGEOM*)lwmpoint_add_lwpoint((LWMPOINT*)geom,
330  (LWPOINT*)lwpoint_construct(root_srid, NULL, pa));
331  }
332  }
333 
334  return geom;
335 }
336 
337 static LWGEOM*
338 parse_geojson_multilinestring(json_object *geojson, int *hasz, int root_srid)
339 {
340  LWGEOM *geom = NULL;
341  int i, j;
342  json_object* poObjLines = NULL;
343 
344  if (!root_srid)
345  {
346  geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, root_srid, 1, 0);
347  }
348  else
349  {
351  }
352 
353  poObjLines = findMemberByName( geojson, "coordinates" );
354  if ( ! poObjLines )
355  {
356  geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
357  return NULL;
358  }
359 
360  if( json_type_array == json_object_get_type( poObjLines ) )
361  {
362  const int nLines = json_object_array_length( poObjLines );
363  for( i = 0; i < nLines; ++i)
364  {
365  POINTARRAY *pa = NULL;
366  json_object* poObjLine = NULL;
367  poObjLine = json_object_array_get_idx( poObjLines, i );
368  pa = ptarray_construct_empty(1, 0, 1);
369 
370  if( json_type_array == json_object_get_type( poObjLine ) )
371  {
372  const int nPoints = json_object_array_length( poObjLine );
373  for(j = 0; j < nPoints; ++j)
374  {
375  json_object* coords = NULL;
376  coords = json_object_array_get_idx( poObjLine, j );
377  parse_geojson_coord(coords, hasz, pa);
378  }
379 
380  geom = (LWGEOM*)lwmline_add_lwline((LWMLINE*)geom,
381  (LWLINE*)lwline_construct(root_srid, NULL, pa));
382  }
383  }
384  }
385 
386  return geom;
387 }
388 
389 static LWGEOM*
390 parse_geojson_multipolygon(json_object *geojson, int *hasz, int root_srid)
391 {
392  LWGEOM *geom = NULL;
393  int i, j, k;
394  json_object* poObjPolys = NULL;
395 
396  if (!root_srid)
397  {
398  geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, root_srid, 1, 0);
399  }
400  else
401  {
403  }
404 
405  poObjPolys = findMemberByName( geojson, "coordinates" );
406  if ( ! poObjPolys )
407  {
408  geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
409  return NULL;
410  }
411 
412  if( json_type_array == json_object_get_type( poObjPolys ) )
413  {
414  const int nPolys = json_object_array_length( poObjPolys );
415 
416  for(i = 0; i < nPolys; ++i)
417  {
418  json_object* poObjPoly = json_object_array_get_idx( poObjPolys, i );
419 
420  if( json_type_array == json_object_get_type( poObjPoly ) )
421  {
422  LWPOLY *lwpoly = lwpoly_construct_empty(geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom));
423  int nRings = json_object_array_length( poObjPoly );
424 
425  for(j = 0; j < nRings; ++j)
426  {
427  json_object* points = json_object_array_get_idx( poObjPoly, j );
428 
429  if( json_type_array == json_object_get_type( points ) )
430  {
431 
432  POINTARRAY *pa = ptarray_construct_empty(1, 0, 1);
433 
434  int nPoints = json_object_array_length( points );
435  for ( k=0; k < nPoints; k++ )
436  {
437  json_object* coords = json_object_array_get_idx( points, k );
438  parse_geojson_coord(coords, hasz, pa);
439  }
440 
441  lwpoly_add_ring(lwpoly, pa);
442  }
443  }
444  geom = (LWGEOM*)lwmpoly_add_lwpoly((LWMPOLY*)geom, lwpoly);
445  }
446  }
447  }
448 
449  return geom;
450 }
451 
452 static LWGEOM*
453 parse_geojson_geometrycollection(json_object *geojson, int *hasz, int root_srid)
454 {
455  LWGEOM *geom = NULL;
456  int i;
457  json_object* poObjGeoms = NULL;
458 
459  if (!root_srid)
460  {
461  geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, root_srid, 1, 0);
462  }
463  else
464  {
466  }
467 
468  poObjGeoms = findMemberByName( geojson, "geometries" );
469  if ( ! poObjGeoms )
470  {
471  geojson_lwerror("Unable to find 'geometries' in GeoJSON string", 4);
472  return NULL;
473  }
474 
475  if( json_type_array == json_object_get_type( poObjGeoms ) )
476  {
477  const int nGeoms = json_object_array_length( poObjGeoms );
478  json_object* poObjGeom = NULL;
479  for(i = 0; i < nGeoms; ++i )
480  {
481  poObjGeom = json_object_array_get_idx( poObjGeoms, i );
483  parse_geojson(poObjGeom, hasz, root_srid));
484  }
485  }
486 
487  return geom;
488 }
489 
490 static LWGEOM*
491 parse_geojson(json_object *geojson, int *hasz, int root_srid)
492 {
493  json_object* type = NULL;
494  const char* name;
495 
496  if( NULL == geojson )
497  {
498  geojson_lwerror("invalid GeoJSON representation", 2);
499  return NULL;
500  }
501 
502  type = findMemberByName( geojson, "type" );
503  if( NULL == type )
504  {
505  geojson_lwerror("unknown GeoJSON type", 3);
506  return NULL;
507  }
508 
509  name = json_object_get_string( type );
510 
511  if( strcasecmp( name, "Point" )==0 )
512  return parse_geojson_point(geojson, hasz, root_srid);
513 
514  if( strcasecmp( name, "LineString" )==0 )
515  return parse_geojson_linestring(geojson, hasz, root_srid);
516 
517  if( strcasecmp( name, "Polygon" )==0 )
518  return parse_geojson_polygon(geojson, hasz, root_srid);
519 
520  if( strcasecmp( name, "MultiPoint" )==0 )
521  return parse_geojson_multipoint(geojson, hasz, root_srid);
522 
523  if( strcasecmp( name, "MultiLineString" )==0 )
524  return parse_geojson_multilinestring(geojson, hasz, root_srid);
525 
526  if( strcasecmp( name, "MultiPolygon" )==0 )
527  return parse_geojson_multipolygon(geojson, hasz, root_srid);
528 
529  if( strcasecmp( name, "GeometryCollection" )==0 )
530  return parse_geojson_geometrycollection(geojson, hasz, root_srid);
531 
532  lwerror("invalid GeoJson representation");
533  return NULL; /* Never reach */
534 }
535 
536 #endif /* HAVE_LIBJSON or HAVE_LIBJSON_C --} */
537 
538 LWGEOM*
539 lwgeom_from_geojson(const char *geojson, char **srs)
540 {
541 #ifndef HAVE_LIBJSON
542  *srs = NULL;
543  lwerror("You need JSON-C for lwgeom_from_geojson");
544  return NULL;
545 #else /* HAVE_LIBJSON */
546 
547  /* size_t geojson_size = strlen(geojson); */
548 
549  LWGEOM *lwgeom;
550  int hasz=LW_TRUE;
551  json_tokener* jstok = NULL;
552  json_object* poObj = NULL;
553  json_object* poObjSrs = NULL;
554  *srs = NULL;
555 
556  /* Begin to Parse json */
557  jstok = json_tokener_new();
558  poObj = json_tokener_parse_ex(jstok, geojson, -1);
559  if( jstok->err != json_tokener_success)
560  {
561  char err[256];
562  snprintf(err, 256, "%s (at offset %d)", json_tokener_error_desc(jstok->err), jstok->char_offset);
563  json_tokener_free(jstok);
564  json_object_put(poObj);
565  geojson_lwerror(err, 1);
566  return NULL;
567  }
568  json_tokener_free(jstok);
569 
570  poObjSrs = findMemberByName( poObj, "crs" );
571  if (poObjSrs != NULL)
572  {
573  json_object* poObjSrsType = findMemberByName( poObjSrs, "type" );
574  if (poObjSrsType != NULL)
575  {
576  json_object* poObjSrsProps = findMemberByName( poObjSrs, "properties" );
577  if ( poObjSrsProps )
578  {
579  json_object* poNameURL = findMemberByName( poObjSrsProps, "name" );
580  if ( poNameURL )
581  {
582  const char* pszName = json_object_get_string( poNameURL );
583  if ( pszName )
584  {
585  *srs = lwalloc(strlen(pszName) + 1);
586  strcpy(*srs, pszName);
587  }
588  }
589  }
590  }
591  }
592 
593  lwgeom = parse_geojson(poObj, &hasz, 0);
594  json_object_put(poObj);
595 
596  lwgeom_add_bbox(lwgeom);
597 
598  if (!hasz)
599  {
600  LWGEOM *tmp = lwgeom_force_2d(lwgeom);
601  lwgeom_free(lwgeom);
602  lwgeom = tmp;
603 
604  LWDEBUG(2, "geom_from_geojson called.");
605  }
606 
607  return lwgeom;
608 #endif /* HAVE_LIBJSON } */
609 }
610 
611 
double x
Definition: liblwgeom.h:352
double m
Definition: liblwgeom.h:352
static LWGEOM * parse_geojson(json_object *geojson, int *hasz, int root_srid)
Definition: lwin_geojson.c:491
static void geojson_lwerror(char *msg, __attribute__((__unused__)) int error_code)
Definition: lwin_geojson.c:55
void lwfree(void *mem)
Definition: lwutil.c:244
#define __attribute__(x)
Definition: liblwgeom.h:198
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1099
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:330
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
static LWGEOM * parse_geojson_multipolygon(json_object *geojson, int *hasz, int root_srid)
Definition: lwin_geojson.c:390
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
static int parse_geojson_coord(json_object *poObj, int *hasz, POINTARRAY *pa)
Definition: lwin_geojson.c:103
LWMLINE * lwmline_add_lwline(LWMLINE *mobj, const LWLINE *obj)
Definition: lwmline.c:46
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:885
int32_t srid
Definition: liblwgeom.h:399
#define LW_FAILURE
Definition: liblwgeom.h:79
static LWGEOM * parse_geojson_polygon(json_object *geojson, int *hasz, int root_srid)
Definition: lwin_geojson.c:226
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_FALSE, then a duplicate point will not be added.
Definition: ptarray.c:156
#define LW_FALSE
Definition: liblwgeom.h:77
uint8_t flags
Definition: liblwgeom.h:369
LWPOLY * lwpoly_construct(int srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
Definition: lwpoly.c:43
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:76
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
#define json_tokener_error_desc(x)
Definition: lwin_geojson.c:50
LWGEOM * lwgeom_force_2d(const LWGEOM *geom)
Strip out the Z/M components of an LWGEOM.
Definition: lwgeom.c:739
static LWGEOM * parse_geojson_multilinestring(json_object *geojson, int *hasz, int root_srid)
Definition: lwin_geojson.c:338
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:140
double z
Definition: liblwgeom.h:352
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
static LWGEOM * parse_geojson_linestring(json_object *geojson, int *hasz, int root_srid)
Definition: lwin_geojson.c:190
static LWGEOM * parse_geojson_point(json_object *geojson, int *hasz, int root_srid)
Definition: lwin_geojson.c:166
static LWGEOM * parse_geojson_geometrycollection(json_object *geojson, int *hasz, int root_srid)
Definition: lwin_geojson.c:453
static json_object * findMemberByName(json_object *poObj, const char *pszName)
Definition: lwin_geojson.c:65
LWMPOINT * lwmpoint_add_lwpoint(LWMPOINT *mobj, const LWPOINT *obj)
Definition: lwmpoint.c:45
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:161
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:648
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:141
type
Definition: ovdump.py:41
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition: lwpoly.c:249
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
void * lwalloc(size_t size)
Definition: lwutil.c:229
static LWGEOM * parse_geojson_multipoint(json_object *geojson, int *hasz, int root_srid)
Definition: lwin_geojson.c:295
double y
Definition: liblwgeom.h:352
#define MULTILINETYPE
Definition: liblwgeom.h:89
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:892
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:187
LWMPOLY * lwmpoly_add_lwpoly(LWMPOLY *mobj, const LWPOLY *obj)
Definition: lwmpoly.c:47
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
This library is the generic geometry handling section of PostGIS.
LWGEOM * lwgeom_from_geojson(const char *geojson, char **srs)
Create an LWGEOM object from a GeoJSON representation.
Definition: lwin_geojson.c:539