diff --git a/NEWS b/NEWS index 44da35448..297c62446 100644 --- a/NEWS +++ b/NEWS @@ -68,6 +68,7 @@ PostGIS 2.1.0 - #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 diff --git a/configure.ac b/configure.ac index f904246df..929d2e8fd 100644 --- a/configure.ac +++ b/configure.ac @@ -840,7 +840,7 @@ dnl Always enable use of ANALYZE statistics by default 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" diff --git a/liblwgeom/Makefile.in b/liblwgeom/Makefile.in index cad453d8f..7ee6bd2ef 100644 --- a/liblwgeom/Makefile.in +++ b/liblwgeom/Makefile.in @@ -11,8 +11,8 @@ # ********************************************************************** 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@ @@ -57,6 +57,7 @@ SA_OBJS = \ lwpsurface.o \ lwtin.o \ lwout_wkb.o \ + lwin_geojson.o \ lwin_wkb.o \ lwout_wkt.o \ lwin_wkt_parse.o \ diff --git a/liblwgeom/cunit/Makefile.in b/liblwgeom/cunit/Makefile.in index fc3f399f9..e5723aeb1 100644 --- a/liblwgeom/cunit/Makefile.in +++ b/liblwgeom/cunit/Makefile.in @@ -46,6 +46,7 @@ OBJS= \ 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 diff --git a/liblwgeom/cunit/cu_in_geojson.c b/liblwgeom/cunit/cu_in_geojson.c new file mode 100644 index 000000000..5ecbf2346 --- /dev/null +++ b/liblwgeom/cunit/cu_in_geojson.c @@ -0,0 +1,228 @@ +/********************************************************************** + * $Id$ + * + * PostGIS - Spatial Types for PostgreSQL + * http://postgis.refractions.net + * + * Copyright 2013 Sandro Santilli + * + * 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 +#include +#include +#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}; diff --git a/liblwgeom/cunit/cu_tester.c b/liblwgeom/cunit/cu_tester.c index 3dc8677da..4fc8ffe85 100644 --- a/liblwgeom/cunit/cu_tester.c +++ b/liblwgeom/cunit/cu_tester.c @@ -40,6 +40,7 @@ extern CU_SuiteInfo geos_suite; 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; @@ -79,6 +80,7 @@ int main(int argc, char *argv[]) stringbuffer_suite, surface_suite, homogenize_suite, + in_geojson_suite, out_gml_suite, out_kml_suite, out_geojson_suite, diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in index 1cf353766..84c698f13 100644 --- a/liblwgeom/liblwgeom.h.in +++ b/liblwgeom/liblwgeom.h.in @@ -1349,6 +1349,17 @@ extern char* lwgeom_to_geojson(const LWGEOM *geo, char *srs, int precision, int 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. */ diff --git a/liblwgeom/lwin_geojson.c b/liblwgeom/lwin_geojson.c new file mode 100644 index 000000000..7e0d95f71 --- /dev/null +++ b/liblwgeom/lwin_geojson.c @@ -0,0 +1,555 @@ +/********************************************************************** + * + * PostGIS - Spatial Types for PostgreSQL + * + * Copyright 2013 Sandro Santilli + * Copyright 2011 Kashif Rasul + * + * 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 +#include "liblwgeom.h" +#include "lwgeom_log.h" +#include "../postgis_config.h" + +#ifdef HAVE_LIBJSON + +#include +#include +#include + +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 */ +} + + diff --git a/postgis/lwgeom_in_geojson.c b/postgis/lwgeom_in_geojson.c index f42202e66..8a0ddfc94 100644 --- a/postgis/lwgeom_in_geojson.c +++ b/postgis/lwgeom_in_geojson.c @@ -15,464 +15,11 @@ #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 -#include - -/* 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) { @@ -496,59 +43,25 @@ Datum geom_from_geojson(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); + lwgeom = lwgeom_from_geojson(geojson, &srs); + if ( ! lwgeom ) { + /* Shouldn't get here */ + elog(ERROR, "lwgeom_from_geojson returned NULL"); + PG_RETURN_NULL(); + } - 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."); - } + if ( srs ) { + lwgeom_set_srid(lwgeom, getSRIDbySRS(srs)); + lwfree(srs); + } geom = geometry_serialize(lwgeom); lwgeom_free(lwgeom);