- #945, improved join selectivity, N-D selectivity calculations, user
accessible selectivity and stats reader functions for testing
- #2210, ST_MinConvexHull(raster)
+ - lwgeom_from_geojson in liblwgeom (Sandro Santilli / Vizzuality)
* Enhancements *
- #823, tiger geocoder: Make loader_generate_script download portion
AC_DEFINE_UNQUOTED([POSTGIS_USE_STATS], [1], [Enable use of ANALYZE statistics])
-CPPFLAGS="$PGSQL_CPPFLAGS $GEOS_CPPFLAGS $PROJ_CPPFLAGS $JSON_CPPFLAGS $XML2_CPPFLAGS"
+CPPFLAGS="$PGSQL_CPPFLAGS $GEOS_CPPFLAGS $PROJ_CPPFLAGS $XML2_CPPFLAGS"
dnl AC_MSG_RESULT([CPPFLAGS: $CPPFLAGS])
SHLIB_LINK="$PGSQL_LDFLAGS $GEOS_LDFLAGS $PROJ_LDFLAGS -lgeos_c -lproj $JSON_LDFLAGS $XML2_LDFLAGS"
# **********************************************************************
CC = @CC@
-CFLAGS = @CFLAGS@ @PICFLAGS@ @WARNFLAGS@ @GEOS_CPPFLAGS@ @PROJ_CPPFLAGS@
-LDFLAGS = @LDFLAGS@ @GEOS_LDFLAGS@ -lgeos_c @PROJ_LDFLAGS@ -lproj
+CFLAGS = @CFLAGS@ @PICFLAGS@ @WARNFLAGS@ @GEOS_CPPFLAGS@ @PROJ_CPPFLAGS@ @JSON_CPPFLAGS@
+LDFLAGS = @LDFLAGS@ @GEOS_LDFLAGS@ -lgeos_c @PROJ_LDFLAGS@ -lproj @JSON_LDFLAGS@
NUMERICFLAGS = @NUMERICFLAGS@
top_builddir = @top_builddir@
prefix = @prefix@
lwpsurface.o \
lwtin.o \
lwout_wkb.o \
+ lwin_geojson.o \
lwin_wkb.o \
lwout_wkt.o \
lwin_wkt_parse.o \
cu_out_svg.o \
cu_surface.o \
cu_out_x3d.o \
+ cu_in_geojson.o \
cu_in_wkb.o \
cu_in_wkt.o \
cu_tester.o
--- /dev/null
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ *
+ * Copyright 2013 Sandro Santilli <strk@keybit.net>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "CUnit/Basic.h"
+
+#include "liblwgeom_internal.h"
+#include "cu_tester.h"
+
+static void do_geojson_test(const char * exp, char * in, char * exp_srs, int precision, int has_bbox)
+{
+ LWGEOM *g;
+ char * h = NULL;
+ char * srs = NULL;
+ size_t size;
+
+ has_bbox = has_bbox; /* unused */
+
+ g = lwgeom_from_geojson(in, &srs);
+ h = lwgeom_to_wkt(g, WKT_EXTENDED, 15, &size);
+
+ if (strcmp(h, exp)) {
+ fprintf(stderr, "\nIn: %s\nExp: %s\nObt: %s\n", in, exp, h);
+ CU_ASSERT_STRING_EQUAL(h, exp);
+ }
+
+ if ( exp_srs ) {
+ if ( ! srs ) {
+ fprintf(stderr, "\nIn: %s\nExp: %s\nObt: (null)\n", in, exp_srs);
+ CU_ASSERT_EQUAL(srs, exp_srs);
+ }
+ else if (strcmp(srs, exp_srs)) {
+ fprintf(stderr, "\nIn: %s\nExp: %s\nObt: %s\n", in, exp_srs, srs);
+ CU_ASSERT_STRING_EQUAL(srs, exp_srs);
+ }
+ } else if ( srs ) {
+ fprintf(stderr, "\nIn: %s\nExp: (null)\nObt: %s\n", in, srs);
+ CU_ASSERT_EQUAL(srs, exp_srs);
+ }
+
+ lwgeom_free(g);
+ if ( h ) lwfree(h);
+ if ( srs ) lwfree(srs);
+}
+
+
+static void do_geojson_unsupported(char * in, char * exp)
+{
+ LWGEOM *g;
+ char * h = NULL;
+ char * srs = NULL;
+ size_t size;
+
+ g = lwgeom_from_geojson(in, &srs);
+
+ if ( g ) {
+ h = lwgeom_to_wkt(g, WKT_ISO, 1, &size);
+ fprintf(stderr, "\nIn: %s\nExp: %s\nObt: %s\n",
+ in, exp, h);
+ CU_ASSERT(!g);
+ } else {
+
+ if (strcmp(cu_error_msg, exp))
+ fprintf(stderr, "\nIn: %s\nExp: %s\nObt: %s\n",
+ in, exp, cu_error_msg);
+ CU_ASSERT_STRING_EQUAL(in, cu_error_msg);
+ }
+
+ cu_error_msg_reset();
+
+ if ( srs ) lwfree(srs);
+ if ( h ) lwfree(h);
+ lwgeom_free(g);
+}
+
+static void in_geojson_test_srid(void)
+{
+ /* Linestring */
+ do_geojson_test(
+ "LINESTRING(0 1,2 3,4 5)",
+ "{\"type\":\"LineString\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"coordinates\":[[0,1],[2,3],[4,5]]}",
+ "EPSG:4326", 0, 0);
+
+ /* Polygon */
+ do_geojson_test(
+ "POLYGON((0 1,2 3,4 5,0 1))",
+ "{\"type\":\"Polygon\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]]]}",
+ "EPSG:4326", 0, 0);
+
+ /* Polygon - with internal ring */
+ do_geojson_test(
+ "POLYGON((0 1,2 3,4 5,0 1),(6 7,8 9,10 11,6 7))",
+ "{\"type\":\"Polygon\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]],[[6,7],[8,9],[10,11],[6,7]]]}",
+ "EPSG:4326", 0, 0);
+
+ /* Multiline */
+ do_geojson_test(
+ "MULTILINESTRING((0 1,2 3,4 5),(6 7,8 9,10 11))",
+ "{\"type\":\"MultiLineString\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"coordinates\":[[[0,1],[2,3],[4,5]],[[6,7],[8,9],[10,11]]]}",
+ "EPSG:4326", 0, 0);
+
+ /* MultiPolygon */
+ do_geojson_test(
+ "MULTIPOLYGON(((0 1,2 3,4 5,0 1)),((6 7,8 9,10 11,6 7)))",
+ "{\"type\":\"MultiPolygon\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"coordinates\":[[[[0,1],[2,3],[4,5],[0,1]]],[[[6,7],[8,9],[10,11],[6,7]]]]}",
+ "EPSG:4326", 0, 0);
+
+ /* Empty GeometryCollection */
+ do_geojson_test(
+ "GEOMETRYCOLLECTION EMPTY",
+ "{\"type\":\"GeometryCollection\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"geometries\":[]}",
+ "EPSG:4326", 0, 0);
+}
+
+static void in_geojson_test_bbox(void)
+{
+ /* Linestring */
+ do_geojson_test(
+ "LINESTRING(0 1,2 3,4 5)",
+ "{\"type\":\"LineString\",\"bbox\":[0,1,4,5],\"coordinates\":[[0,1],[2,3],[4,5]]}",
+ NULL, 0, 1);
+
+ /* Polygon */
+ do_geojson_test(
+ "POLYGON((0 1,2 3,4 5,0 1))",
+ "{\"type\":\"Polygon\",\"bbox\":[0,1,4,5],\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]]]}",
+ NULL, 0, 1);
+
+ /* Polygon - with internal ring */
+ do_geojson_test(
+ "POLYGON((0 1,2 3,4 5,0 1),(6 7,8 9,10 11,6 7))",
+ "{\"type\":\"Polygon\",\"bbox\":[0,1,4,5],\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]],[[6,7],[8,9],[10,11],[6,7]]]}",
+ NULL, 0, 1);
+
+ /* Multiline */
+ do_geojson_test(
+ "MULTILINESTRING((0 1,2 3,4 5),(6 7,8 9,10 11))",
+ "{\"type\":\"MultiLineString\",\"bbox\":[0,1,10,11],\"coordinates\":[[[0,1],[2,3],[4,5]],[[6,7],[8,9],[10,11]]]}",
+ NULL, 0, 1);
+
+ /* MultiPolygon */
+ do_geojson_test(
+ "MULTIPOLYGON(((0 1,2 3,4 5,0 1)),((6 7,8 9,10 11,6 7)))",
+ "{\"type\":\"MultiPolygon\",\"bbox\":[0,1,10,11],\"coordinates\":[[[[0,1],[2,3],[4,5],[0,1]]],[[[6,7],[8,9],[10,11],[6,7]]]]}",
+ NULL, 0, 1);
+
+ /* GeometryCollection */
+ do_geojson_test(
+ "GEOMETRYCOLLECTION(LINESTRING(0 1,-1 3),LINESTRING(2 3,4 5))",
+ "{\"type\":\"GeometryCollection\",\"bbox\":[-1,1,4,5],\"geometries\":[{\"type\":\"LineString\",\"coordinates\":[[0,1],[-1,3]]},{\"type\":\"LineString\",\"coordinates\":[[2,3],[4,5]]}]}",
+ NULL, 0, 1);
+
+ /* Empty GeometryCollection */
+ do_geojson_test(
+ "GEOMETRYCOLLECTION EMPTY",
+ "{\"type\":\"GeometryCollection\",\"geometries\":[]}",
+ NULL, 0, 1);
+}
+
+static void in_geojson_test_geoms(void)
+{
+ /* Linestring */
+ do_geojson_test(
+ "LINESTRING(0 1,2 3,4 5)",
+ "{\"type\":\"LineString\",\"coordinates\":[[0,1],[2,3],[4,5]]}",
+ NULL, 0, 0);
+
+ /* Polygon */
+ do_geojson_test(
+ "POLYGON((0 1,2 3,4 5,0 1))",
+ "{\"type\":\"Polygon\",\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]]]}",
+ NULL, 0, 0);
+
+ /* Polygon - with internal ring */
+ do_geojson_test(
+ "POLYGON((0 1,2 3,4 5,0 1),(6 7,8 9,10 11,6 7))",
+ "{\"type\":\"Polygon\",\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]],[[6,7],[8,9],[10,11],[6,7]]]}",
+ NULL, 0, 0);
+
+ /* Multiline */
+ do_geojson_test(
+ "MULTILINESTRING((0 1,2 3,4 5),(6 7,8 9,10 11))",
+ "{\"type\":\"MultiLineString\",\"coordinates\":[[[0,1],[2,3],[4,5]],[[6,7],[8,9],[10,11]]]}",
+ NULL, 0, 0);
+
+ /* MultiPolygon */
+ do_geojson_test(
+ "MULTIPOLYGON(((0 1,2 3,4 5,0 1)),((6 7,8 9,10 11,6 7)))",
+ "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[0,1],[2,3],[4,5],[0,1]]],[[[6,7],[8,9],[10,11],[6,7]]]]}",
+ NULL, 0, 0);
+
+ /* GeometryCollection */
+ do_geojson_test(
+ "GEOMETRYCOLLECTION(POINT(0 1),LINESTRING(2 3,4 5))",
+ "{\"type\":\"GeometryCollection\",\"geometries\":[{\"type\":\"Point\",\"coordinates\":[0,1]},{\"type\":\"LineString\",\"coordinates\":[[2,3],[4,5]]}]}",
+ NULL, 0, 0);
+
+ /* Empty GeometryCollection */
+ do_geojson_test(
+ "GEOMETRYCOLLECTION EMPTY",
+ "{\"type\":\"GeometryCollection\",\"geometries\":[]}",
+ NULL, 0, 0);
+
+}
+
+/*
+** Used by test harness to register the tests in this file.
+*/
+CU_TestInfo in_geojson_tests[] =
+{
+ PG_TEST(in_geojson_test_srid),
+ PG_TEST(in_geojson_test_bbox),
+ PG_TEST(in_geojson_test_geoms),
+ CU_TEST_INFO_NULL
+};
+CU_SuiteInfo in_geojson_suite = {"in_geojson", NULL, NULL, in_geojson_tests};
extern CU_SuiteInfo tree_suite;
extern CU_SuiteInfo triangulate_suite;
extern CU_SuiteInfo homogenize_suite;
+extern CU_SuiteInfo in_geojson_suite;
extern CU_SuiteInfo stringbuffer_suite;
extern CU_SuiteInfo surface_suite;
extern CU_SuiteInfo out_gml_suite;
stringbuffer_suite,
surface_suite,
homogenize_suite,
+ in_geojson_suite,
out_gml_suite,
out_kml_suite,
out_geojson_suite,
extern char* lwgeom_to_svg(const LWGEOM *geom, int precision, int relative);
extern char* lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid);
+/**
+ * Create an LWGEOM object from a GeoJSON representation
+ *
+ * @param geojson the GeoJSON input
+ * @param srs output parameter. Will be set to a newly allocated
+ * string holding the spatial reference string, or NULL
+ * if no such parameter is found in input.
+ * If not null, the pointer must be freed with lwfree.
+ */
+extern LWGEOM* lwgeom_from_geojson(const char *geojson, char **srs);
+
/**
* Initialize a spheroid object for use in geodetic functions.
*/
--- /dev/null
+/**********************************************************************
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ *
+ * Copyright 2013 Sandro Santilli <strk@keybit.net>
+ * Copyright 2011 Kashif Rasul <kashif.rasul@gmail.com>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include <assert.h>
+#include "liblwgeom.h"
+#include "lwgeom_log.h"
+#include "../postgis_config.h"
+
+#ifdef HAVE_LIBJSON
+
+#include <json/json.h>
+#include <json/json_object_private.h>
+#include <string.h>
+
+static void geojson_lwerror(char *msg, int error_code)
+{
+ LWDEBUGF(3, "lwgeom_from_geojson ERROR %i", error_code);
+ lwerror("%s", msg);
+}
+
+/* Prototype */
+static LWGEOM* parse_geojson(json_object *geojson, int *hasz, int root_srid);
+
+static json_object*
+findMemberByName(json_object* poObj, const char* pszName )
+{
+ json_object* poTmp;
+ json_object_iter it;
+
+ poTmp = poObj;
+
+ if( NULL == pszName || NULL == poObj)
+ return NULL;
+
+ it.key = NULL;
+ it.val = NULL;
+ it.entry = NULL;
+
+ if( NULL != json_object_get_object(poTmp) )
+ {
+ assert( NULL != json_object_get_object(poTmp)->head );
+
+ for( it.entry = json_object_get_object(poTmp)->head;
+ ( it.entry ?
+ ( it.key = (char*)it.entry->k,
+ it.val = (json_object*)it.entry->v, it.entry) : 0);
+ it.entry = it.entry->next)
+ {
+ if( strcasecmp((char *)it.key, pszName )==0 )
+ return it.val;
+ }
+ }
+
+ return NULL;
+}
+
+
+static int
+parse_geojson_coord(json_object *poObj, int *hasz, POINTARRAY *pa)
+{
+ POINT4D pt;
+ int iType = 0;
+
+ LWDEBUGF(3, "parse_geojson_coord called for object %s.", json_object_to_json_string( poObj ) );
+
+ if( json_type_array == json_object_get_type( poObj ) )
+ {
+
+ json_object* poObjCoord = NULL;
+ const int nSize = json_object_array_length( poObj );
+ LWDEBUGF(3, "parse_geojson_coord called for array size %d.", nSize );
+
+
+ // Read X coordinate
+ poObjCoord = json_object_array_get_idx( poObj, 0 );
+ iType = json_object_get_type(poObjCoord);
+ if (iType == json_type_double)
+ pt.x = json_object_get_double( poObjCoord );
+ else
+ pt.x = json_object_get_int( poObjCoord );
+ LWDEBUGF(3, "parse_geojson_coord pt.x = %f.", pt.x );
+
+ // Read Y coordiante
+ poObjCoord = json_object_array_get_idx( poObj, 1 );
+ if (iType == json_type_double)
+ pt.y = json_object_get_double( poObjCoord );
+ else
+ pt.y = json_object_get_int( poObjCoord );
+ LWDEBUGF(3, "parse_geojson_coord pt.y = %f.", pt.y );
+
+ if( nSize == 3 ) /* should this be >= 3 ? */
+ {
+ // Read Z coordiante
+ poObjCoord = json_object_array_get_idx( poObj, 2 );
+ if (iType == 3)
+ pt.z = json_object_get_double( poObjCoord );
+ else
+ pt.z = json_object_get_int( poObjCoord );
+ LWDEBUGF(3, "parse_geojson_coord pt.z = %f.", pt.z );
+ *hasz = LW_TRUE;
+ }
+ else
+ {
+ *hasz = LW_FALSE;
+ /* Initialize Z coordinate, if required */
+ if ( FLAGS_GET_Z(pa->flags) ) pt.z = 0.0;
+ }
+
+ /* TODO: should we account for nSize > 3 ? */
+
+ /* Initialize M coordinate, if required */
+ if ( FLAGS_GET_M(pa->flags) ) pt.m = 0.0;
+
+ }
+
+ return ptarray_append_point(pa, &pt, LW_FALSE);
+}
+
+static LWGEOM*
+parse_geojson_point(json_object *geojson, int *hasz, int root_srid)
+{
+ LWGEOM *geom;
+ POINTARRAY *pa;
+ json_object* coords = NULL;
+
+ LWDEBUGF(3, "parse_geojson_point called with root_srid = %d.", root_srid );
+
+ coords = findMemberByName( geojson, "coordinates" );
+ if ( ! coords ) {
+ geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+ return NULL;
+ }
+
+ pa = ptarray_construct_empty(1, 0, 1);
+ parse_geojson_coord(coords, hasz, pa);
+
+ geom = (LWGEOM *) lwpoint_construct(root_srid, NULL, pa);
+ LWDEBUG(2, "parse_geojson_point finished.");
+ return geom;
+}
+
+static LWGEOM*
+parse_geojson_linestring(json_object *geojson, int *hasz, int root_srid)
+{
+ LWGEOM *geom;
+ POINTARRAY *pa;
+ json_object* points = NULL;
+ int i = 0;
+
+ LWDEBUG(2, "parse_geojson_linestring called.");
+
+ points = findMemberByName( geojson, "coordinates" );
+ if ( ! points ) {
+ geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+ return NULL;
+ }
+
+ pa = ptarray_construct_empty(1, 0, 1);
+
+ if( json_type_array == json_object_get_type( points ) )
+ {
+ const int nPoints = json_object_array_length( points );
+ for(i = 0; i < nPoints; ++i)
+ {
+ json_object* coords = NULL;
+ coords = json_object_array_get_idx( points, i );
+ parse_geojson_coord(coords, hasz, pa);
+ }
+ }
+
+ geom = (LWGEOM *) lwline_construct(root_srid, NULL, pa);
+
+ LWDEBUG(2, "parse_geojson_linestring finished.");
+ return geom;
+}
+
+static LWGEOM*
+parse_geojson_polygon(json_object *geojson, int *hasz, int root_srid)
+{
+ LWGEOM *geom;
+ POINTARRAY **ppa;
+ json_object* rings = NULL;
+ int i = 0, j = 0;
+ int ring = 0;
+
+ rings = findMemberByName( geojson, "coordinates" );
+ if ( ! rings ) {
+ geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+ return NULL;
+ }
+
+ ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));
+
+ if( json_type_array == json_object_get_type( rings ) )
+ {
+ int nPoints;
+ json_object* points = NULL;
+ ppa[0] = ptarray_construct_empty(1, 0, 1);
+ ring = json_object_array_length( rings );
+ points = json_object_array_get_idx( rings, 0 );
+ nPoints = json_object_array_length( points );
+
+ for (i=0; i < nPoints; i++ )
+ {
+ json_object* coords = NULL;
+ coords = json_object_array_get_idx( points, i );
+ parse_geojson_coord(coords, hasz, ppa[0]);
+ }
+
+ for(i = 1; i < ring; ++i)
+ {
+ int nPoints;
+ ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, sizeof(POINTARRAY*) * (i + 1));
+ ppa[i] = ptarray_construct_empty(1, 0, 1);
+ points = json_object_array_get_idx( rings, i );
+ nPoints = json_object_array_length( points );
+ for (j=0; j < nPoints; j++ )
+ {
+ json_object* coords = NULL;
+ coords = json_object_array_get_idx( points, j );
+ parse_geojson_coord(coords, hasz, ppa[i]);
+ }
+ }
+ }
+
+ geom = (LWGEOM *) lwpoly_construct(root_srid, NULL, ring, ppa);
+ return geom;
+}
+
+static LWGEOM*
+parse_geojson_multipoint(json_object *geojson, int *hasz, int root_srid)
+{
+ LWGEOM *geom;
+ int i = 0;
+ json_object* poObjPoints = NULL;
+
+ if (!root_srid)
+ {
+ geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, root_srid, 1, 0);
+ }
+ else
+ {
+ geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, -1, 1, 0);
+ }
+
+ poObjPoints = findMemberByName( geojson, "coordinates" );
+ if ( ! poObjPoints ) {
+ geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+ return NULL;
+ }
+
+ if( json_type_array == json_object_get_type( poObjPoints ) )
+ {
+ const int nPoints = json_object_array_length( poObjPoints );
+ for( i = 0; i < nPoints; ++i)
+ {
+ POINTARRAY *pa;
+ json_object* poObjCoords = NULL;
+ poObjCoords = json_object_array_get_idx( poObjPoints, i );
+
+ pa = ptarray_construct_empty(1, 0, 1);
+ parse_geojson_coord(poObjCoords, hasz, pa);
+
+ geom = (LWGEOM*)lwmpoint_add_lwpoint((LWMPOINT*)geom,
+ (LWPOINT*)lwpoint_construct(root_srid, NULL, pa));
+ }
+ }
+
+ return geom;
+}
+
+static LWGEOM*
+parse_geojson_multilinestring(json_object *geojson, int *hasz, int root_srid)
+{
+ LWGEOM *geom = NULL;
+ int i, j;
+ json_object* poObjLines = NULL;
+
+ if (!root_srid)
+ {
+ geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, root_srid, 1, 0);
+ }
+ else
+ {
+ geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, -1, 1, 0);
+ }
+
+ poObjLines = findMemberByName( geojson, "coordinates" );
+ if ( ! poObjLines ) {
+ geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+ return NULL;
+ }
+
+ if( json_type_array == json_object_get_type( poObjLines ) )
+ {
+ const int nLines = json_object_array_length( poObjLines );
+ for( i = 0; i < nLines; ++i)
+ {
+ POINTARRAY *pa = NULL;
+ json_object* poObjLine = NULL;
+ poObjLine = json_object_array_get_idx( poObjLines, i );
+ pa = ptarray_construct_empty(1, 0, 1);
+
+ if( json_type_array == json_object_get_type( poObjLine ) )
+ {
+ const int nPoints = json_object_array_length( poObjLine );
+ for(j = 0; j < nPoints; ++j)
+ {
+ json_object* coords = NULL;
+ coords = json_object_array_get_idx( poObjLine, j );
+ parse_geojson_coord(coords, hasz, pa);
+ }
+
+ geom = (LWGEOM*)lwmline_add_lwline((LWMLINE*)geom,
+ (LWLINE*)lwline_construct(root_srid, NULL, pa));
+ }
+ }
+ }
+
+ return geom;
+}
+
+static LWGEOM*
+parse_geojson_multipolygon(json_object *geojson, int *hasz, int root_srid)
+{
+ LWGEOM *geom = NULL;
+ int i, j, k;
+ json_object* poObjPolys = NULL;
+
+ if (!root_srid)
+ {
+ geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, root_srid, 1, 0);
+ }
+ else
+ {
+ geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, -1, 1, 0);
+ }
+
+ poObjPolys = findMemberByName( geojson, "coordinates" );
+ if ( ! poObjPolys ) {
+ geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+ return NULL;
+ }
+
+ if( json_type_array == json_object_get_type( poObjPolys ) )
+ {
+ const int nPolys = json_object_array_length( poObjPolys );
+
+ for(i = 0; i < nPolys; ++i)
+ {
+ POINTARRAY **ppa;
+ json_object* poObjPoly = NULL;
+ poObjPoly = json_object_array_get_idx( poObjPolys, i );
+
+ ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));
+
+ if( json_type_array == json_object_get_type( poObjPoly ) )
+ {
+ int nPoints;
+ json_object* points = NULL;
+ int ring = json_object_array_length( poObjPoly );
+ ppa[0] = ptarray_construct_empty(1, 0, 1);
+
+ points = json_object_array_get_idx( poObjPoly, 0 );
+ nPoints = json_object_array_length( points );
+
+ for (j=0; j < nPoints; j++ )
+ {
+ json_object* coords = NULL;
+ coords = json_object_array_get_idx( points, j );
+ parse_geojson_coord(coords, hasz, ppa[0]);
+ }
+
+ for(j = 1; j < ring; ++j)
+ {
+ int nPoints;
+ ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, sizeof(POINTARRAY*) * (j + 1));
+ ppa[j] = ptarray_construct_empty(1, 0, 1);
+ points = json_object_array_get_idx( poObjPoly, j );
+
+ nPoints = json_object_array_length( points );
+ for (k=0; k < nPoints; k++ )
+ {
+ json_object* coords = NULL;
+ coords = json_object_array_get_idx( points, k );
+ parse_geojson_coord(coords, hasz, ppa[i]);
+ }
+ }
+
+ geom = (LWGEOM*)lwmpoly_add_lwpoly((LWMPOLY*)geom,
+ (LWPOLY*)lwpoly_construct(root_srid, NULL, ring, ppa));
+ }
+ }
+ }
+
+ return geom;
+}
+
+static LWGEOM*
+parse_geojson_geometrycollection(json_object *geojson, int *hasz, int root_srid)
+{
+ LWGEOM *geom = NULL;
+ int i;
+ json_object* poObjGeoms = NULL;
+
+ if (!root_srid)
+ {
+ geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, root_srid, 1, 0);
+ }
+ else
+ {
+ geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, -1, 1, 0);
+ }
+
+ poObjGeoms = findMemberByName( geojson, "geometries" );
+ if ( ! poObjGeoms ) {
+ geojson_lwerror("Unable to find 'geometries' in GeoJSON string", 4);
+ return NULL;
+ }
+
+ if( json_type_array == json_object_get_type( poObjGeoms ) )
+ {
+ const int nGeoms = json_object_array_length( poObjGeoms );
+ json_object* poObjGeom = NULL;
+ for(i = 0; i < nGeoms; ++i )
+ {
+ poObjGeom = json_object_array_get_idx( poObjGeoms, i );
+ geom = (LWGEOM*)lwcollection_add_lwgeom((LWCOLLECTION *)geom,
+ parse_geojson(poObjGeom, hasz, root_srid));
+ }
+ }
+
+ return geom;
+}
+
+static LWGEOM*
+parse_geojson(json_object *geojson, int *hasz, int root_srid)
+{
+ json_object* type = NULL;
+ const char* name;
+
+ if( NULL == geojson ) {
+ geojson_lwerror("invalid GeoJSON representation", 2);
+ return NULL;
+ }
+
+ type = findMemberByName( geojson, "type" );
+ if( NULL == type ) {
+ geojson_lwerror("unknown GeoJSON type", 3);
+ return NULL;
+ }
+
+ name = json_object_get_string( type );
+
+ if( strcasecmp( name, "Point" )==0 )
+ return parse_geojson_point(geojson, hasz, root_srid);
+
+ if( strcasecmp( name, "LineString" )==0 )
+ return parse_geojson_linestring(geojson, hasz, root_srid);
+
+ if( strcasecmp( name, "Polygon" )==0 )
+ return parse_geojson_polygon(geojson, hasz, root_srid);
+
+ if( strcasecmp( name, "MultiPoint" )==0 )
+ return parse_geojson_multipoint(geojson, hasz, root_srid);
+
+ if( strcasecmp( name, "MultiLineString" )==0 )
+ return parse_geojson_multilinestring(geojson, hasz, root_srid);
+
+ if( strcasecmp( name, "MultiPolygon" )==0 )
+ return parse_geojson_multipolygon(geojson, hasz, root_srid);
+
+ if( strcasecmp( name, "GeometryCollection" )==0 )
+ return parse_geojson_geometrycollection(geojson, hasz, root_srid);
+
+ lwerror("invalid GeoJson representation");
+ return NULL; /* Never reach */
+}
+
+#endif /* HAVE_LIBJSON */
+
+LWGEOM*
+lwgeom_from_geojson(const char *geojson, char **srs)
+{
+#ifndef HAVE_LIBJSON
+ *srs = NULL;
+ lwerror("You need JSON-C for lwgeom_from_geojson");
+ return NULL;
+#else /* HAVE_LIBJSON */
+
+ /* size_t geojson_size = strlen(geojson); */
+
+ LWGEOM *lwgeom;
+ int hasz=LW_TRUE;
+ json_tokener* jstok = NULL;
+ json_object* poObj = NULL;
+ json_object* poObjSrs = NULL;
+ *srs = NULL;
+
+ /* Begin to Parse json */
+ jstok = json_tokener_new();
+ poObj = json_tokener_parse_ex(jstok, geojson, -1);
+ if( jstok->err != json_tokener_success)
+ {
+ char err[256];
+ snprintf(err, 256, "%s (at offset %d)", json_tokener_errors[jstok->err], jstok->char_offset);
+ json_tokener_free(jstok);
+ json_object_put(poObj);
+ geojson_lwerror(err, 1);
+ return NULL;
+ }
+ json_tokener_free(jstok);
+
+ poObjSrs = findMemberByName( poObj, "crs" );
+ if (poObjSrs != NULL)
+ {
+ json_object* poObjSrsType = findMemberByName( poObjSrs, "type" );
+ if (poObjSrsType != NULL)
+ {
+ json_object* poObjSrsProps = findMemberByName( poObjSrs, "properties" );
+ json_object* poNameURL = findMemberByName( poObjSrsProps, "name" );
+ const char* pszName = json_object_get_string( poNameURL );
+ *srs = lwalloc(strlen(pszName) + 1);
+ strcpy(*srs, pszName);
+ }
+ }
+
+ lwgeom = parse_geojson(poObj, &hasz, 0);
+ json_object_put(poObj);
+
+ lwgeom_add_bbox(lwgeom);
+
+ if (!hasz)
+ {
+ LWGEOM *tmp = lwgeom_force_2d(lwgeom);
+ lwgeom_free(lwgeom);
+ lwgeom = tmp;
+
+ LWDEBUG(2, "geom_from_geojson called.");
+ }
+
+ return lwgeom;
+#endif /* HAVE_LIBJSON */
+}
+
+
#include "../postgis_config.h"
#include "lwgeom_pg.h"
#include "liblwgeom.h"
+#include "lwgeom_export.h"
Datum geom_from_geojson(PG_FUNCTION_ARGS);
Datum postgis_libjson_version(PG_FUNCTION_ARGS);
-static void geojson_lwerror(char *msg, int error_code)
-{
- POSTGIS_DEBUGF(3, "ST_GeomFromGeoJSON ERROR %i", error_code);
- lwerror("%s", msg);
-}
-
-#ifdef HAVE_LIBJSON
-
-#include "lwgeom_export.h"
-#include <json/json.h>
-#include <json/json_object_private.h>
-
-/* Prototype */
-LWGEOM* parse_geojson(json_object *geojson, bool *hasz, int *root_srid);
-
-static json_object*
-findMemberByName(json_object* poObj, const char* pszName )
-{
- json_object* poTmp;
- json_object_iter it;
-
- poTmp = poObj;
-
- if( NULL == pszName || NULL == poObj)
- return NULL;
-
- it.key = NULL;
- it.val = NULL;
- it.entry = NULL;
-
- if( NULL != json_object_get_object(poTmp) )
- {
- assert( NULL != json_object_get_object(poTmp)->head );
-
- for( it.entry = json_object_get_object(poTmp)->head;
- ( it.entry ?
- ( it.key = (char*)it.entry->k,
- it.val = (json_object*)it.entry->v, it.entry) : 0);
- it.entry = it.entry->next)
- {
- if( strcasecmp((char *)it.key, pszName )==0 )
- return it.val;
- }
- }
-
- return NULL;
-}
-
-
-static int
-parse_geojson_coord(json_object *poObj, bool *hasz, POINTARRAY *pa)
-{
- POINT4D pt;
- int iType = 0;
-
- POSTGIS_DEBUGF(3, "parse_geojson_coord called for object %s.", json_object_to_json_string( poObj ) );
-
- if( json_type_array == json_object_get_type( poObj ) )
- {
-
- json_object* poObjCoord = NULL;
- const int nSize = json_object_array_length( poObj );
- POSTGIS_DEBUGF(3, "parse_geojson_coord called for array size %d.", nSize );
-
-
- // Read X coordinate
- poObjCoord = json_object_array_get_idx( poObj, 0 );
- iType = json_object_get_type(poObjCoord);
- if (iType == json_type_double)
- pt.x = json_object_get_double( poObjCoord );
- else
- pt.x = json_object_get_int( poObjCoord );
- POSTGIS_DEBUGF(3, "parse_geojson_coord pt.x = %f.", pt.x );
-
- // Read Y coordiante
- poObjCoord = json_object_array_get_idx( poObj, 1 );
- if (iType == json_type_double)
- pt.y = json_object_get_double( poObjCoord );
- else
- pt.y = json_object_get_int( poObjCoord );
- POSTGIS_DEBUGF(3, "parse_geojson_coord pt.y = %f.", pt.y );
-
- if( nSize == 3 ) /* should this be >= 3 ? */
- {
- // Read Z coordiante
- poObjCoord = json_object_array_get_idx( poObj, 2 );
- if (iType == 3)
- pt.z = json_object_get_double( poObjCoord );
- else
- pt.z = json_object_get_int( poObjCoord );
- POSTGIS_DEBUGF(3, "parse_geojson_coord pt.z = %f.", pt.z );
- *hasz = true;
- }
- else
- {
- *hasz = false;
- /* Initialize Z coordinate, if required */
- if ( FLAGS_GET_Z(pa->flags) ) pt.z = 0.0;
- }
-
- /* TODO: should we account for nSize > 3 ? */
-
- /* Initialize M coordinate, if required */
- if ( FLAGS_GET_M(pa->flags) ) pt.m = 0.0;
-
- }
-
- return ptarray_append_point(pa, &pt, LW_FALSE);
-}
-
-static LWGEOM*
-parse_geojson_point(json_object *geojson, bool *hasz, int *root_srid)
-{
- LWGEOM *geom;
- POINTARRAY *pa;
- json_object* coords = NULL;
-
- POSTGIS_DEBUGF(3, "parse_geojson_point called with root_srid = %d.", *root_srid );
-
- coords = findMemberByName( geojson, "coordinates" );
- if ( ! coords )
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-
- pa = ptarray_construct_empty(1, 0, 1);
- parse_geojson_coord(coords, hasz, pa);
-
- geom = (LWGEOM *) lwpoint_construct(*root_srid, NULL, pa);
- POSTGIS_DEBUG(2, "parse_geojson_point finished.");
- return geom;
-}
-
-static LWGEOM*
-parse_geojson_linestring(json_object *geojson, bool *hasz, int *root_srid)
-{
- LWGEOM *geom;
- POINTARRAY *pa;
- json_object* points = NULL;
- int i = 0;
-
- POSTGIS_DEBUG(2, "parse_geojson_linestring called.");
-
- points = findMemberByName( geojson, "coordinates" );
- if ( ! points )
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-
- pa = ptarray_construct_empty(1, 0, 1);
-
- if( json_type_array == json_object_get_type( points ) )
- {
- const int nPoints = json_object_array_length( points );
- for(i = 0; i < nPoints; ++i)
- {
- json_object* coords = NULL;
- coords = json_object_array_get_idx( points, i );
- parse_geojson_coord(coords, hasz, pa);
- }
- }
-
- geom = (LWGEOM *) lwline_construct(*root_srid, NULL, pa);
-
- POSTGIS_DEBUG(2, "parse_geojson_linestring finished.");
- return geom;
-}
-
-static LWGEOM*
-parse_geojson_polygon(json_object *geojson, bool *hasz, int *root_srid)
-{
- LWGEOM *geom;
- POINTARRAY **ppa;
- json_object* rings = NULL;
- int i = 0, j = 0;
- int ring = 0;
-
- rings = findMemberByName( geojson, "coordinates" );
- if ( ! rings )
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-
- ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));
-
- if( json_type_array == json_object_get_type( rings ) )
- {
- int nPoints;
- json_object* points = NULL;
- ppa[0] = ptarray_construct_empty(1, 0, 1);
- ring = json_object_array_length( rings );
- points = json_object_array_get_idx( rings, 0 );
- nPoints = json_object_array_length( points );
-
- for (i=0; i < nPoints; i++ )
- {
- json_object* coords = NULL;
- coords = json_object_array_get_idx( points, i );
- parse_geojson_coord(coords, hasz, ppa[0]);
- }
-
- for(i = 1; i < ring; ++i)
- {
- int nPoints;
- ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, sizeof(POINTARRAY*) * (i + 1));
- ppa[i] = ptarray_construct_empty(1, 0, 1);
- points = json_object_array_get_idx( rings, i );
- nPoints = json_object_array_length( points );
- for (j=0; j < nPoints; j++ )
- {
- json_object* coords = NULL;
- coords = json_object_array_get_idx( points, j );
- parse_geojson_coord(coords, hasz, ppa[i]);
- }
- }
- }
-
- geom = (LWGEOM *) lwpoly_construct(*root_srid, NULL, ring, ppa);
- return geom;
-}
-
-static LWGEOM*
-parse_geojson_multipoint(json_object *geojson, bool *hasz, int *root_srid)
-{
- LWGEOM *geom;
- int i = 0;
- json_object* poObjPoints = NULL;
-
- if (!*root_srid)
- {
- geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, *root_srid, 1, 0);
- }
- else
- {
- geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, -1, 1, 0);
- }
-
- poObjPoints = findMemberByName( geojson, "coordinates" );
- if ( ! poObjPoints )
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-
- if( json_type_array == json_object_get_type( poObjPoints ) )
- {
- const int nPoints = json_object_array_length( poObjPoints );
- for( i = 0; i < nPoints; ++i)
- {
- POINTARRAY *pa;
- json_object* poObjCoords = NULL;
- poObjCoords = json_object_array_get_idx( poObjPoints, i );
-
- pa = ptarray_construct_empty(1, 0, 1);
- parse_geojson_coord(poObjCoords, hasz, pa);
-
- geom = (LWGEOM*)lwmpoint_add_lwpoint((LWMPOINT*)geom,
- (LWPOINT*)lwpoint_construct(*root_srid, NULL, pa));
- }
- }
-
- return geom;
-}
-
-static LWGEOM*
-parse_geojson_multilinestring(json_object *geojson, bool *hasz, int *root_srid)
-{
- LWGEOM *geom = NULL;
- int i, j;
- json_object* poObjLines = NULL;
-
- if (!*root_srid)
- {
- geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, *root_srid, 1, 0);
- }
- else
- {
- geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, -1, 1, 0);
- }
-
- poObjLines = findMemberByName( geojson, "coordinates" );
- if ( ! poObjLines )
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-
- if( json_type_array == json_object_get_type( poObjLines ) )
- {
- const int nLines = json_object_array_length( poObjLines );
- for( i = 0; i < nLines; ++i)
- {
- POINTARRAY *pa = NULL;
- json_object* poObjLine = NULL;
- poObjLine = json_object_array_get_idx( poObjLines, i );
- pa = ptarray_construct_empty(1, 0, 1);
-
- if( json_type_array == json_object_get_type( poObjLine ) )
- {
- const int nPoints = json_object_array_length( poObjLine );
- for(j = 0; j < nPoints; ++j)
- {
- json_object* coords = NULL;
- coords = json_object_array_get_idx( poObjLine, j );
- parse_geojson_coord(coords, hasz, pa);
- }
-
- geom = (LWGEOM*)lwmline_add_lwline((LWMLINE*)geom,
- (LWLINE*)lwline_construct(*root_srid, NULL, pa));
- }
- }
- }
-
- return geom;
-}
-
-static LWGEOM*
-parse_geojson_multipolygon(json_object *geojson, bool *hasz, int *root_srid)
-{
- LWGEOM *geom = NULL;
- int i, j, k;
- json_object* poObjPolys = NULL;
-
- if (!*root_srid)
- {
- geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, *root_srid, 1, 0);
- }
- else
- {
- geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, -1, 1, 0);
- }
-
- poObjPolys = findMemberByName( geojson, "coordinates" );
- if ( ! poObjPolys )
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-
- if( json_type_array == json_object_get_type( poObjPolys ) )
- {
- const int nPolys = json_object_array_length( poObjPolys );
-
- for(i = 0; i < nPolys; ++i)
- {
- POINTARRAY **ppa;
- json_object* poObjPoly = NULL;
- poObjPoly = json_object_array_get_idx( poObjPolys, i );
-
- ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));
-
- if( json_type_array == json_object_get_type( poObjPoly ) )
- {
- int nPoints;
- json_object* points = NULL;
- int ring = json_object_array_length( poObjPoly );
- ppa[0] = ptarray_construct_empty(1, 0, 1);
-
- points = json_object_array_get_idx( poObjPoly, 0 );
- nPoints = json_object_array_length( points );
-
- for (j=0; j < nPoints; j++ )
- {
- json_object* coords = NULL;
- coords = json_object_array_get_idx( points, j );
- parse_geojson_coord(coords, hasz, ppa[0]);
- }
-
- for(j = 1; j < ring; ++j)
- {
- int nPoints;
- ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, sizeof(POINTARRAY*) * (j + 1));
- ppa[j] = ptarray_construct_empty(1, 0, 1);
- points = json_object_array_get_idx( poObjPoly, j );
-
- nPoints = json_object_array_length( points );
- for (k=0; k < nPoints; k++ )
- {
- json_object* coords = NULL;
- coords = json_object_array_get_idx( points, k );
- parse_geojson_coord(coords, hasz, ppa[i]);
- }
- }
-
- geom = (LWGEOM*)lwmpoly_add_lwpoly((LWMPOLY*)geom,
- (LWPOLY*)lwpoly_construct(*root_srid, NULL, ring, ppa));
- }
- }
- }
-
- return geom;
-}
-
-static LWGEOM*
-parse_geojson_geometrycollection(json_object *geojson, bool *hasz, int *root_srid)
-{
- LWGEOM *geom = NULL;
- int i;
- json_object* poObjGeoms = NULL;
-
- if (!*root_srid)
- {
- geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, *root_srid, 1, 0);
- }
- else
- {
- geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, -1, 1, 0);
- }
-
- poObjGeoms = findMemberByName( geojson, "geometries" );
- if ( ! poObjGeoms )
- geojson_lwerror("Unable to find 'geometries' in GeoJSON string", 4);
-
- if( json_type_array == json_object_get_type( poObjGeoms ) )
- {
- const int nGeoms = json_object_array_length( poObjGeoms );
- json_object* poObjGeom = NULL;
- for(i = 0; i < nGeoms; ++i )
- {
- poObjGeom = json_object_array_get_idx( poObjGeoms, i );
- geom = (LWGEOM*)lwcollection_add_lwgeom((LWCOLLECTION *)geom,
- parse_geojson(poObjGeom, hasz, root_srid));
- }
- }
-
- return geom;
-}
-
-LWGEOM*
-parse_geojson(json_object *geojson, bool *hasz, int *root_srid)
-{
- json_object* type = NULL;
- const char* name;
-
- if( NULL == geojson )
- geojson_lwerror("invalid GeoJSON representation", 2);
-
- type = findMemberByName( geojson, "type" );
- if( NULL == type )
- geojson_lwerror("unknown GeoJSON type", 3);
-
- name = json_object_get_string( type );
-
- if( strcasecmp( name, "Point" )==0 )
- return parse_geojson_point(geojson, hasz, root_srid);
-
- if( strcasecmp( name, "LineString" )==0 )
- return parse_geojson_linestring(geojson, hasz, root_srid);
-
- if( strcasecmp( name, "Polygon" )==0 )
- return parse_geojson_polygon(geojson, hasz, root_srid);
-
- if( strcasecmp( name, "MultiPoint" )==0 )
- return parse_geojson_multipoint(geojson, hasz, root_srid);
-
- if( strcasecmp( name, "MultiLineString" )==0 )
- return parse_geojson_multilinestring(geojson, hasz, root_srid);
-
- if( strcasecmp( name, "MultiPolygon" )==0 )
- return parse_geojson_multipolygon(geojson, hasz, root_srid);
-
- if( strcasecmp( name, "GeometryCollection" )==0 )
- return parse_geojson_geometrycollection(geojson, hasz, root_srid);
-
- lwerror("invalid GeoJson representation");
- return NULL; /* Never reach */
-}
-#endif /* HAVE_LIBJSON */
-
PG_FUNCTION_INFO_V1(postgis_libjson_version);
Datum postgis_libjson_version(PG_FUNCTION_ARGS)
{
GSERIALIZED *geom;
LWGEOM *lwgeom;
text *geojson_input;
- int geojson_size;
char *geojson;
- int root_srid=0;
- bool hasz=true;
- json_tokener* jstok = NULL;
- json_object* poObj = NULL;
- json_object* poObjSrs = NULL;
+ char *srs = NULL;
/* Get the geojson stream */
if (PG_ARGISNULL(0)) PG_RETURN_NULL();
geojson_input = PG_GETARG_TEXT_P(0);
geojson = text2cstring(geojson_input);
- geojson_size = VARSIZE(geojson_input) - VARHDRSZ;
-
- /* Begin to Parse json */
- jstok = json_tokener_new();
- poObj = json_tokener_parse_ex(jstok, geojson, -1);
- if( jstok->err != json_tokener_success)
- {
- char err[256];
- snprintf(err, 256, "%s (at offset %d)", json_tokener_errors[jstok->err], jstok->char_offset);
- json_tokener_free(jstok);
- geojson_lwerror(err, 1);
- }
- json_tokener_free(jstok);
-
- poObjSrs = findMemberByName( poObj, "crs" );
- if (poObjSrs != NULL)
- {
- json_object* poObjSrsType = findMemberByName( poObjSrs, "type" );
- if (poObjSrsType != NULL)
- {
- json_object* poObjSrsProps = findMemberByName( poObjSrs, "properties" );
- json_object* poNameURL = findMemberByName( poObjSrsProps, "name" );
- const char* pszName = json_object_get_string( poNameURL );
- root_srid = getSRIDbySRS(pszName);
- POSTGIS_DEBUGF(3, "getSRIDbySRS returned root_srid = %d.", root_srid );
- }
- }
-
- lwgeom = parse_geojson(poObj, &hasz, &root_srid);
-
- lwgeom_add_bbox(lwgeom);
- if (root_srid && lwgeom->srid == -1) lwgeom->srid = root_srid;
-
- if (!hasz)
- {
- LWGEOM *tmp = lwgeom_force_2d(lwgeom);
- lwgeom_free(lwgeom);
- lwgeom = tmp;
- POSTGIS_DEBUG(2, "geom_from_geojson called.");
- }
+ lwgeom = lwgeom_from_geojson(geojson, &srs);
+ if ( ! lwgeom ) {
+ /* Shouldn't get here */
+ elog(ERROR, "lwgeom_from_geojson returned NULL");
+ PG_RETURN_NULL();
+ }
+
+ if ( srs ) {
+ lwgeom_set_srid(lwgeom, getSRIDbySRS(srs));
+ lwfree(srs);
+ }
geom = geometry_serialize(lwgeom);
lwgeom_free(lwgeom);