summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcelo Galigniana <marcelogaligniana@gmail.com>2022-05-13 22:51:12 -0300
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-05-16 06:46:53 +0200
commit76af861356eda3b08bc5e15ad1973f980c7604a3 (patch)
tree4811b4f55435ac40c7154c50de77b954b6c72c3a
parentd27e6b233f83c3429f21ff3c250a28ff302637ef (diff)
Fixed #27550 -- Allowed GEOSGeometry.normalize() to return a normalized clone.
-rw-r--r--django/contrib/gis/geos/geometry.py12
-rw-r--r--docs/ref/contrib/gis/geos.txt10
-rw-r--r--docs/releases/4.1.txt3
-rw-r--r--tests/gis_tests/geos_tests/test_geos.py16
4 files changed, 32 insertions, 9 deletions
diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py
index 9d22425fab..bafb99a058 100644
--- a/django/contrib/gis/geos/geometry.py
+++ b/django/contrib/gis/geos/geometry.py
@@ -222,8 +222,16 @@ class GEOSGeometryBase(GEOSBase):
"Return the dimension of this Geometry (0=point, 1=line, 2=surface)."
return capi.get_dims(self.ptr)
- def normalize(self):
- "Convert this Geometry to normal form (or canonical form)."
+ def normalize(self, clone=False):
+ """
+ Convert this Geometry to normal form (or canonical form).
+ If the `clone` keyword is set, then the geometry is not modified and a
+ normalized clone of the geometry is returned instead.
+ """
+ if clone:
+ clone = self.clone()
+ capi.geos_normalize(clone.ptr)
+ return clone
capi.geos_normalize(self.ptr)
def make_valid(self):
diff --git a/docs/ref/contrib/gis/geos.txt b/docs/ref/contrib/gis/geos.txt
index 93fe6e9895..a8057dc631 100644
--- a/docs/ref/contrib/gis/geos.txt
+++ b/docs/ref/contrib/gis/geos.txt
@@ -665,9 +665,11 @@ Other Properties & Methods
:class:`~django.contrib.gis.db.models.functions.MakeValid` database
function. Requires GEOS 3.8.
-.. method:: GEOSGeometry.normalize()
+.. method:: GEOSGeometry.normalize(clone=False)
- Converts this geometry to canonical form::
+ Converts this geometry to canonical form. If the ``clone`` keyword is set,
+ then the geometry is not modified and a normalized clone of the geometry is
+ returned instead::
>>> g = MultiPoint(Point(0, 0), Point(2, 2), Point(1, 1))
>>> print(g)
@@ -676,6 +678,10 @@ Other Properties & Methods
>>> print(g)
MULTIPOINT (2 2, 1 1, 0 0)
+ .. versionchanged:: 4.1
+
+ The ``clone`` argument was added.
+
``Point``
---------
diff --git a/docs/releases/4.1.txt b/docs/releases/4.1.txt
index 38dcdb94e0..dc95a653c3 100644
--- a/docs/releases/4.1.txt
+++ b/docs/releases/4.1.txt
@@ -139,6 +139,9 @@ Minor features
* The new :meth:`.GEOSGeometry.make_valid()` method allows converting invalid
geometries to valid ones.
+* The new ``clone`` argument for :meth:`.GEOSGeometry.normalize` allows
+ creating a normalized clone of the geometry.
+
: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 4754f17c9b..fd3f0b6ebd 100644
--- a/tests/gis_tests/geos_tests/test_geos.py
+++ b/tests/gis_tests/geos_tests/test_geos.py
@@ -1528,11 +1528,17 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
self.assertEqual(GEOSGeometry("POINT(1.0e-1 1.0e+1)"), Point(0.1, 10))
def test_normalize(self):
- g = MultiPoint(Point(0, 0), Point(2, 2), Point(1, 1))
- self.assertIsNone(g.normalize())
- self.assertTrue(
- g.equals_exact(MultiPoint(Point(2, 2), Point(1, 1), Point(0, 0)))
- )
+ multipoint = MultiPoint(Point(0, 0), Point(2, 2), Point(1, 1))
+ normalized = MultiPoint(Point(2, 2), Point(1, 1), Point(0, 0))
+ # Geometry is normalized in-place and nothing is returned.
+ multipoint_1 = multipoint.clone()
+ self.assertIsNone(multipoint_1.normalize())
+ self.assertEqual(multipoint_1, normalized)
+ # If the `clone` keyword is set, then the geometry is not modified and
+ # a normalized clone of the geometry is returned instead.
+ multipoint_2 = multipoint.normalize(clone=True)
+ self.assertEqual(multipoint_2, normalized)
+ self.assertNotEqual(multipoint, normalized)
@skipIf(geos_version_tuple() < (3, 8), "GEOS >= 3.8.0 is required")
def test_make_valid(self):