From 5ce660cd65a4ffcf74d94ba987fe03a16b7436a0 Mon Sep 17 00:00:00 2001 From: Sergey Fedoseev Date: Fri, 10 Jun 2016 11:50:07 +0500 Subject: [PATCH] Fixed #25940 -- Added OGRGeometry.from_gml() and GEOSGeometry.from_gml(). --- django/contrib/gis/gdal/geometries.py | 5 +++++ django/contrib/gis/gdal/prototypes/geom.py | 1 + django/contrib/gis/geos/geometry.py | 4 ++++ docs/ref/contrib/gis/gdal.txt | 6 ++++++ docs/ref/contrib/gis/geos.txt | 6 ++++++ docs/releases/1.11.txt | 3 ++- tests/gis_tests/gdal_tests/test_geom.py | 10 ++++++++++ tests/gis_tests/geos_tests/test_geos.py | 10 ++++++++++ 8 files changed, 44 insertions(+), 1 deletion(-) diff --git a/django/contrib/gis/gdal/geometries.py b/django/contrib/gis/gdal/geometries.py index 1d76da18d8..4407e147e5 100644 --- a/django/contrib/gis/gdal/geometries.py +++ b/django/contrib/gis/gdal/geometries.py @@ -52,6 +52,7 @@ 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 from django.utils import six +from django.utils.encoding import force_bytes from django.utils.six.moves import range @@ -150,6 +151,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)) + @classmethod + def from_gml(cls, gml_string): + return cls(capi.from_gml(force_bytes(gml_string))) + # ### Geometry set-like operations ### # g = g1 | g2 def __or__(self, other): diff --git a/django/contrib/gis/gdal/prototypes/geom.py b/django/contrib/gis/gdal/prototypes/geom.py index d1c43a47c2..aac8b99bae 100644 --- a/django/contrib/gis/gdal/prototypes/geom.py +++ b/django/contrib/gis/gdal/prototypes/geom.py @@ -44,6 +44,7 @@ getz = pnt_func(lgdal.OGR_G_GetZ) # Geometry creation routines. from_wkb = geom_output(lgdal.OGR_G_CreateFromWkb, [c_char_p, c_void_p, POINTER(c_void_p), c_int], offset=-2) from_wkt = geom_output(lgdal.OGR_G_CreateFromWkt, [POINTER(c_char_p), c_void_p, POINTER(c_void_p)], offset=-1) +from_gml = geom_output(lgdal.OGR_G_CreateFromGML, [c_char_p]) create_geom = geom_output(lgdal.OGR_G_CreateGeometry, [c_int]) clone_geom = geom_output(lgdal.OGR_G_Clone, [c_void_p]) get_geom_ref = geom_output(lgdal.OGR_G_GetGeometryRef, [c_void_p, c_int]) diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py index d0a9455659..66f78e70de 100644 --- a/django/contrib/gis/geos/geometry.py +++ b/django/contrib/gis/geos/geometry.py @@ -166,6 +166,10 @@ class GEOSGeometry(GEOSBase, ListMixin): self.ptr = ptr self._post_init(srid) + @classmethod + def from_gml(cls, gml_string): + return gdal.OGRGeometry.from_gml(gml_string).geos + # Comparison operators def __eq__(self, other): """ diff --git a/docs/ref/contrib/gis/gdal.txt b/docs/ref/contrib/gis/gdal.txt index da81ce5e03..9bd2df8dad 100644 --- a/docs/ref/contrib/gis/gdal.txt +++ b/docs/ref/contrib/gis/gdal.txt @@ -448,6 +448,12 @@ coordinate transformation:: __ http://www.gdal.org/classOGRGeometry.html + .. classmethod:: from_gml(gml_string) + + .. versionadded:: 1.11 + + Constructs an :class:`OGRGeometry` from the given GML string. + .. classmethod:: from_bbox(bbox) Constructs a :class:`Polygon` from the given bounding-box (a 4-tuple). diff --git a/docs/ref/contrib/gis/geos.txt b/docs/ref/contrib/gis/geos.txt index 811a9ba946..e6d609736e 100644 --- a/docs/ref/contrib/gis/geos.txt +++ b/docs/ref/contrib/gis/geos.txt @@ -198,6 +198,12 @@ WKB / EWKB ``buffer`` GeoJSON ``str`` or ``unicode`` ======================= ====================== +.. classmethod:: GEOSGeometry.from_gml(gml_string) + + .. versionadded:: 1.11 + + Constructs a :class:`GEOSGeometry` from the given GML string. + Properties ~~~~~~~~~~ diff --git a/docs/releases/1.11.txt b/docs/releases/1.11.txt index 9a1cc81d8d..001fb1ead1 100644 --- a/docs/releases/1.11.txt +++ b/docs/releases/1.11.txt @@ -74,7 +74,8 @@ Minor features :mod:`django.contrib.gis` ~~~~~~~~~~~~~~~~~~~~~~~~~ -* ... +* The new :meth:`.GEOSGeometry.from_gml` and :meth:`.OGRGeometry.from_gml` + methods allow creating geometries from GML. :mod:`django.contrib.messages` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/gis_tests/gdal_tests/test_geom.py b/tests/gis_tests/gdal_tests/test_geom.py index 163399289a..7ec1b4b990 100644 --- a/tests/gis_tests/gdal_tests/test_geom.py +++ b/tests/gis_tests/gdal_tests/test_geom.py @@ -543,3 +543,13 @@ class OGRGeomTest(unittest.TestCase, TestDataMixin): OGRGeometry('POINT(0.5 0.5)').within(OGRGeometry('POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))')), True ) self.assertIs(OGRGeometry('POINT(0 0)').within(OGRGeometry('POINT(0 1)')), False) + + def test_from_gml(self): + self.assertEqual( + OGRGeometry('POINT(0 0)'), + OGRGeometry.from_gml( + '' + ' 0 0' + '' + ), + ) diff --git a/tests/gis_tests/geos_tests/test_geos.py b/tests/gis_tests/geos_tests/test_geos.py index 36457f4f51..a7724de9bc 100644 --- a/tests/gis_tests/geos_tests/test_geos.py +++ b/tests/gis_tests/geos_tests/test_geos.py @@ -1300,6 +1300,16 @@ class GEOSTest(SimpleTestCase, TestDataMixin): self.assertEqual(m.group('version'), v_geos) self.assertEqual(m.group('capi_version'), v_capi) + def test_from_gml(self): + self.assertEqual( + GEOSGeometry('POINT(0 0)'), + GEOSGeometry.from_gml( + '' + ' 0 0' + '' + ), + ) + @ignore_warnings(category=RemovedInDjango20Warning) def test_deprecated_srid_getters_setters(self): p = Point(1, 2, srid=123)