mirror of
https://github.com/django/django.git
synced 2025-06-03 18:49:12 +00:00
Fixed #34739 -- Added GEOSGeometry.equals_identical() method.
This commit is contained in:
parent
8edaf07a28
commit
0f3b1a783d
@ -11,7 +11,7 @@ from django.contrib.gis.geos import prototypes as capi
|
|||||||
from django.contrib.gis.geos.base import GEOSBase
|
from django.contrib.gis.geos.base import GEOSBase
|
||||||
from django.contrib.gis.geos.coordseq import GEOSCoordSeq
|
from django.contrib.gis.geos.coordseq import GEOSCoordSeq
|
||||||
from django.contrib.gis.geos.error import GEOSException
|
from django.contrib.gis.geos.error import GEOSException
|
||||||
from django.contrib.gis.geos.libgeos import GEOM_PTR
|
from django.contrib.gis.geos.libgeos import GEOM_PTR, geos_version_tuple
|
||||||
from django.contrib.gis.geos.mutable_list import ListMixin
|
from django.contrib.gis.geos.mutable_list import ListMixin
|
||||||
from django.contrib.gis.geos.prepared import PreparedGeometry
|
from django.contrib.gis.geos.prepared import PreparedGeometry
|
||||||
from django.contrib.gis.geos.prototypes.io import ewkb_w, wkb_r, wkb_w, wkt_r, wkt_w
|
from django.contrib.gis.geos.prototypes.io import ewkb_w, wkb_r, wkb_w, wkt_r, wkt_w
|
||||||
@ -318,6 +318,16 @@ class GEOSGeometryBase(GEOSBase):
|
|||||||
"""
|
"""
|
||||||
return capi.geos_equalsexact(self.ptr, other.ptr, float(tolerance))
|
return capi.geos_equalsexact(self.ptr, other.ptr, float(tolerance))
|
||||||
|
|
||||||
|
def equals_identical(self, other):
|
||||||
|
"""
|
||||||
|
Return true if the two Geometries are point-wise equivalent.
|
||||||
|
"""
|
||||||
|
if geos_version_tuple() < (3, 12):
|
||||||
|
raise GEOSException(
|
||||||
|
"GEOSGeometry.equals_identical() requires GEOS >= 3.12.0."
|
||||||
|
)
|
||||||
|
return capi.geos_equalsidentical(self.ptr, other.ptr)
|
||||||
|
|
||||||
def intersects(self, other):
|
def intersects(self, other):
|
||||||
"Return true if disjoint return false."
|
"Return true if disjoint return false."
|
||||||
return capi.geos_intersects(self.ptr, other.ptr)
|
return capi.geos_intersects(self.ptr, other.ptr)
|
||||||
|
@ -51,6 +51,7 @@ from django.contrib.gis.geos.prototypes.predicates import ( # NOQA
|
|||||||
geos_disjoint,
|
geos_disjoint,
|
||||||
geos_equals,
|
geos_equals,
|
||||||
geos_equalsexact,
|
geos_equalsexact,
|
||||||
|
geos_equalsidentical,
|
||||||
geos_hasz,
|
geos_hasz,
|
||||||
geos_intersects,
|
geos_intersects,
|
||||||
geos_isclosed,
|
geos_isclosed,
|
||||||
|
@ -38,6 +38,7 @@ geos_equals = BinaryPredicate("GEOSEquals")
|
|||||||
geos_equalsexact = BinaryPredicate(
|
geos_equalsexact = BinaryPredicate(
|
||||||
"GEOSEqualsExact", argtypes=[GEOM_PTR, GEOM_PTR, c_double]
|
"GEOSEqualsExact", argtypes=[GEOM_PTR, GEOM_PTR, c_double]
|
||||||
)
|
)
|
||||||
|
geos_equalsidentical = BinaryPredicate("GEOSEqualsIdentical")
|
||||||
geos_intersects = BinaryPredicate("GEOSIntersects")
|
geos_intersects = BinaryPredicate("GEOSIntersects")
|
||||||
geos_overlaps = BinaryPredicate("GEOSOverlaps")
|
geos_overlaps = BinaryPredicate("GEOSOverlaps")
|
||||||
geos_relatepattern = BinaryPredicate(
|
geos_relatepattern = BinaryPredicate(
|
||||||
|
@ -483,6 +483,15 @@ return a boolean.
|
|||||||
``poly1.equals_exact(poly2, 0.001)`` will compare equality to within
|
``poly1.equals_exact(poly2, 0.001)`` will compare equality to within
|
||||||
one thousandth of a unit.
|
one thousandth of a unit.
|
||||||
|
|
||||||
|
.. method:: GEOSGeometry.equals_identical(other)
|
||||||
|
|
||||||
|
.. versionadded:: 5.0
|
||||||
|
|
||||||
|
Returns ``True`` if the two geometries are point-wise equivalent by
|
||||||
|
checking that the structure, ordering, and values of all vertices are
|
||||||
|
identical in all dimensions. ``NaN`` values are considered to be equal to
|
||||||
|
other ``NaN`` values. Requires GEOS 3.12.
|
||||||
|
|
||||||
.. method:: GEOSGeometry.intersects(other)
|
.. method:: GEOSGeometry.intersects(other)
|
||||||
|
|
||||||
Returns ``True`` if :meth:`GEOSGeometry.disjoint` is ``False``.
|
Returns ``True`` if :meth:`GEOSGeometry.disjoint` is ``False``.
|
||||||
|
@ -192,6 +192,9 @@ Minor features
|
|||||||
|
|
||||||
* Added support for GEOS 3.12.
|
* Added support for GEOS 3.12.
|
||||||
|
|
||||||
|
* The new :meth:`.GEOSGeometry.equals_identical` method allows point-wise
|
||||||
|
equivalence checking of geometries.
|
||||||
|
|
||||||
:mod:`django.contrib.messages`
|
:mod:`django.contrib.messages`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import ctypes
|
import ctypes
|
||||||
import itertools
|
import itertools
|
||||||
import json
|
import json
|
||||||
|
import math
|
||||||
import pickle
|
import pickle
|
||||||
import random
|
import random
|
||||||
from binascii import a2b_hex
|
from binascii import a2b_hex
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from unittest import mock
|
from unittest import mock, skipIf
|
||||||
|
|
||||||
from django.contrib.gis import gdal
|
from django.contrib.gis import gdal
|
||||||
from django.contrib.gis.geos import (
|
from django.contrib.gis.geos import (
|
||||||
@ -241,6 +242,75 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
|
|||||||
self.assertEqual(p0, "SRID=0;POINT (5 23)")
|
self.assertEqual(p0, "SRID=0;POINT (5 23)")
|
||||||
self.assertNotEqual(p1, "SRID=0;POINT (5 23)")
|
self.assertNotEqual(p1, "SRID=0;POINT (5 23)")
|
||||||
|
|
||||||
|
@skipIf(geos_version_tuple() < (3, 12), "GEOS >= 3.12.0 is required")
|
||||||
|
def test_equals_identical(self):
|
||||||
|
tests = [
|
||||||
|
# Empty inputs of different types are not equals_identical.
|
||||||
|
("POINT EMPTY", "LINESTRING EMPTY", False),
|
||||||
|
# Empty inputs of different dimensions are not equals_identical.
|
||||||
|
("POINT EMPTY", "POINT Z EMPTY", False),
|
||||||
|
# Non-empty inputs of different dimensions are not equals_identical.
|
||||||
|
("POINT Z (1 2 3)", "POINT M (1 2 3)", False),
|
||||||
|
("POINT ZM (1 2 3 4)", "POINT Z (1 2 3)", False),
|
||||||
|
# Inputs with different structure are not equals_identical.
|
||||||
|
("LINESTRING (1 1, 2 2)", "MULTILINESTRING ((1 1, 2 2))", False),
|
||||||
|
# Inputs with different types are not equals_identical.
|
||||||
|
(
|
||||||
|
"GEOMETRYCOLLECTION (LINESTRING (1 1, 2 2))",
|
||||||
|
"MULTILINESTRING ((1 1, 2 2))",
|
||||||
|
False,
|
||||||
|
),
|
||||||
|
# Same lines are equals_identical.
|
||||||
|
("LINESTRING M (1 1 0, 2 2 1)", "LINESTRING M (1 1 0, 2 2 1)", True),
|
||||||
|
# Different lines are not equals_identical.
|
||||||
|
("LINESTRING M (1 1 0, 2 2 1)", "LINESTRING M (1 1 1, 2 2 1)", False),
|
||||||
|
# Same polygons are equals_identical.
|
||||||
|
("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0, 1 0, 1 1, 0 0))", True),
|
||||||
|
# Different polygons are not equals_identical.
|
||||||
|
("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((1 0, 1 1, 0 0, 1 0))", False),
|
||||||
|
# Different polygons (number of holes) are not equals_identical.
|
||||||
|
(
|
||||||
|
"POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 2 1, 2 2, 1 1))",
|
||||||
|
(
|
||||||
|
"POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 2 1, 2 2, 1 1), "
|
||||||
|
"(3 3, 4 3, 4 4, 3 3))"
|
||||||
|
),
|
||||||
|
False,
|
||||||
|
),
|
||||||
|
# Same collections are equals_identical.
|
||||||
|
(
|
||||||
|
"MULTILINESTRING ((1 1, 2 2), (2 2, 3 3))",
|
||||||
|
"MULTILINESTRING ((1 1, 2 2), (2 2, 3 3))",
|
||||||
|
True,
|
||||||
|
),
|
||||||
|
# Different collections (structure) are not equals_identical.
|
||||||
|
(
|
||||||
|
"MULTILINESTRING ((1 1, 2 2), (2 2, 3 3))",
|
||||||
|
"MULTILINESTRING ((2 2, 3 3), (1 1, 2 2))",
|
||||||
|
False,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
for g1, g2, is_equal_identical in tests:
|
||||||
|
with self.subTest(g1=g1, g2=g2):
|
||||||
|
self.assertIs(
|
||||||
|
fromstr(g1).equals_identical(fromstr(g2)), is_equal_identical
|
||||||
|
)
|
||||||
|
|
||||||
|
@skipIf(geos_version_tuple() < (3, 12), "GEOS >= 3.12.0 is required")
|
||||||
|
def test_infinite_values_equals_identical(self):
|
||||||
|
# Input with identical infinite values are equals_identical.
|
||||||
|
g1 = Point(x=float("nan"), y=math.inf)
|
||||||
|
g2 = Point(x=float("nan"), y=math.inf)
|
||||||
|
self.assertIs(g1.equals_identical(g2), True)
|
||||||
|
|
||||||
|
@mock.patch("django.contrib.gis.geos.libgeos.geos_version", lambda: b"3.11.0")
|
||||||
|
def test_equals_identical_geos_version(self):
|
||||||
|
g1 = fromstr("POINT (1 2 3)")
|
||||||
|
g2 = fromstr("POINT (1 2 3)")
|
||||||
|
msg = "GEOSGeometry.equals_identical() requires GEOS >= 3.12.0"
|
||||||
|
with self.assertRaisesMessage(GEOSException, msg):
|
||||||
|
g1.equals_identical(g2)
|
||||||
|
|
||||||
def test_points(self):
|
def test_points(self):
|
||||||
"Testing Point objects."
|
"Testing Point objects."
|
||||||
prev = fromstr("POINT(0 0)")
|
prev = fromstr("POINT(0 0)")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user