summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Fedoseev <fedoseev.sergey@gmail.com>2017-03-30 20:17:13 +0500
committerTim Graham <timograham@gmail.com>2017-04-01 15:35:30 -0400
commit24023c6a8fc768ccb72108d2dd4fd8ece04075fd (patch)
treea8b874de21a4a2cedc5a9a732d81ac477c775f09
parentede4f6d48c1fe060c239b2477c00df6bbfd4fd7c (diff)
Fixed #25874 -- Made GEOSGeometry read SRID from GeoJSON input.
-rw-r--r--django/contrib/gis/gdal/geometries.py21
-rw-r--r--django/contrib/gis/geos/geometry.py4
-rw-r--r--docs/ref/contrib/gis/geos.txt11
-rw-r--r--docs/releases/2.0.txt3
-rw-r--r--tests/gis_tests/geos_tests/test_geos.py16
5 files changed, 51 insertions, 4 deletions
diff --git a/django/contrib/gis/gdal/geometries.py b/django/contrib/gis/gdal/geometries.py
index d2cdaee64c..ca7732be75 100644
--- a/django/contrib/gis/gdal/geometries.py
+++ b/django/contrib/gis/gdal/geometries.py
@@ -48,6 +48,7 @@ from django.contrib.gis.gdal.error import (
GDALException, OGRIndexError, SRSException,
)
from django.contrib.gis.gdal.geomtype import OGRGeomType
+from django.contrib.gis.gdal.libgdal import GDAL_VERSION
from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api
from django.contrib.gis.gdal.srs import CoordTransform, SpatialReference
from django.contrib.gis.geometry.regex import hex_regex, json_regex, wkt_regex
@@ -87,7 +88,7 @@ class OGRGeometry(GDALBase):
else:
g = capi.from_wkt(byref(c_char_p(wkt_m.group('wkt').encode())), None, byref(c_void_p()))
elif json_m:
- g = capi.from_json(geom_input.encode())
+ g = self._from_json(geom_input.encode())
else:
# Seeing if the input is a valid short-hand string
# (e.g., 'Point', 'POLYGON').
@@ -139,6 +140,20 @@ class OGRGeometry(GDALBase):
def _from_wkb(cls, geom_input):
return capi.from_wkb(bytes(geom_input), None, byref(c_void_p()), len(geom_input))
+ @staticmethod
+ def _from_json(geom_input):
+ ptr = capi.from_json(geom_input)
+ if GDAL_VERSION < (2, 0):
+ has_srs = True
+ try:
+ capi.get_geom_srs(ptr)
+ except SRSException:
+ has_srs = False
+ if not has_srs:
+ srs = SpatialReference(4326)
+ capi.assign_srs(ptr, srs.ptr)
+ return ptr
+
@classmethod
def from_bbox(cls, bbox):
"Construct a Polygon from a bounding box (4-tuple)."
@@ -146,6 +161,10 @@ class OGRGeometry(GDALBase):
return OGRGeometry('POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))' % (
x0, y0, x0, y1, x1, y1, x1, y0, x0, y0))
+ @staticmethod
+ def from_json(geom_input):
+ return OGRGeometry(OGRGeometry._from_json(force_bytes(geom_input)))
+
@classmethod
def from_gml(cls, gml_string):
return cls(capi.from_gml(force_bytes(gml_string)))
diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py
index 8e0719f4fa..13047b0b5b 100644
--- a/django/contrib/gis/geos/geometry.py
+++ b/django/contrib/gis/geos/geometry.py
@@ -61,7 +61,9 @@ class GEOSGeometry(GEOSBase, ListMixin):
g = wkb_r().read(force_bytes(geo_input))
elif json_regex.match(geo_input):
# Handling GeoJSON input.
- g = wkb_r().read(gdal.OGRGeometry(geo_input).wkb)
+ ogr = gdal.OGRGeometry.from_json(geo_input)
+ g = ogr._geos_ptr()
+ input_srid = ogr.srid
else:
raise ValueError('String input unrecognized as WKT EWKT, and HEXEWKB.')
elif isinstance(geo_input, GEOM_PTR):
diff --git a/docs/ref/contrib/gis/geos.txt b/docs/ref/contrib/gis/geos.txt
index 0c8139d218..04789fd06e 100644
--- a/docs/ref/contrib/gis/geos.txt
+++ b/docs/ref/contrib/gis/geos.txt
@@ -224,9 +224,18 @@ Format Input Type
WKT / EWKT ``str``
HEX / HEXEWKB ``str``
WKB / EWKB ``buffer``
-GeoJSON ``str``
+GeoJSON_ ``str``
======================= ==========
+For the GeoJSON format, the SRID is set based on the ``crs`` member. If ``crs``
+isn't provided, the SRID defaults to 4326.
+
+.. versionchanged:: 2.0
+
+ In older versions, SRID isn't set for geometries initialized from GeoJSON.
+
+.. _GeoJSON: https://tools.ietf.org/html/rfc7946
+
.. classmethod:: GEOSGeometry.from_gml(gml_string)
.. versionadded:: 1.11
diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt
index 33f969d443..bff9e76c88 100644
--- a/docs/releases/2.0.txt
+++ b/docs/releases/2.0.txt
@@ -71,6 +71,9 @@ Minor features
* Added the :class:`~django.contrib.gis.db.models.functions.LineLocatePoint`
function, supported on PostGIS and SpatiaLite.
+* Any :class:`~django.contrib.gis.geos.GEOSGeometry` imported from GeoJSON now
+ has its SRID set.
+
:mod:`django.contrib.messages`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/gis_tests/geos_tests/test_geos.py b/tests/gis_tests/geos_tests/test_geos.py
index 72d035cc22..3270c75762 100644
--- a/tests/gis_tests/geos_tests/test_geos.py
+++ b/tests/gis_tests/geos_tests/test_geos.py
@@ -143,7 +143,21 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
# Loading jsons to prevent decimal differences
self.assertEqual(json.loads(g.json), json.loads(geom.json))
self.assertEqual(json.loads(g.json), json.loads(geom.geojson))
- self.assertEqual(GEOSGeometry(g.wkt), GEOSGeometry(geom.json))
+ self.assertEqual(GEOSGeometry(g.wkt, 4326), GEOSGeometry(geom.json))
+
+ @skipUnless(HAS_GDAL, "GDAL is required.")
+ def test_json_srid(self):
+ geojson_data = {
+ "type": "Point",
+ "coordinates": [2, 49],
+ "crs": {
+ "type": "name",
+ "properties": {
+ "name": "urn:ogc:def:crs:EPSG::4322"
+ }
+ }
+ }
+ self.assertEqual(GEOSGeometry(json.dumps(geojson_data)), Point(2, 49, srid=4322))
def test_fromfile(self):
"Testing the fromfile() factory."