浏览代码

Fixed #27550 -- Allowed GEOSGeometry.normalize() to return a normalized clone.

Marcelo Galigniana 2 年之前
父节点
当前提交
76af861356
共有 4 个文件被更改,包括 32 次插入9 次删除
  1. 10 2
      django/contrib/gis/geos/geometry.py
  2. 8 2
      docs/ref/contrib/gis/geos.txt
  3. 3 0
      docs/releases/4.1.txt
  4. 11 5
      tests/gis_tests/geos_tests/test_geos.py

+ 10 - 2
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):

+ 8 - 2
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``
 ---------
 

+ 3 - 0
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`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

+ 11 - 5
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):