Fixed #26920 -- Made GEOSGeometry equality check consider the srid
This commit is contained in:
parent
10d49b96e6
commit
50613d957a
|
@ -174,12 +174,14 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
def __eq__(self, other):
|
||||
"""
|
||||
Equivalence testing, a Geometry may be compared with another Geometry
|
||||
or a WKT representation.
|
||||
or an EWKT representation.
|
||||
"""
|
||||
if isinstance(other, six.string_types):
|
||||
return self.wkt == other
|
||||
if other.startswith('SRID=0;'):
|
||||
return self.ewkt == other[7:] # Test only WKT part of other
|
||||
return self.ewkt == other
|
||||
elif isinstance(other, GEOSGeometry):
|
||||
return self.equals_exact(other)
|
||||
return self.srid == other.srid and self.equals_exact(other)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
|
|
@ -160,15 +160,23 @@ Geometries support set-like operators::
|
|||
The :class:`~GEOSGeometry` equality operator uses
|
||||
:meth:`~GEOSGeometry.equals_exact`, not :meth:`~GEOSGeometry.equals`, i.e.
|
||||
it requires the compared geometries to have the same coordinates in the
|
||||
same positions::
|
||||
same positions with the same SRIDs::
|
||||
|
||||
>>> from django.contrib.gis.geos import LineString
|
||||
>>> ls1 = LineString((0, 0), (1, 1))
|
||||
>>> ls2 = LineString((1, 1), (0, 0))
|
||||
>>> ls3 = LineString((1, 1), (0, 0), srid=4326)
|
||||
>>> ls1.equals(ls2)
|
||||
True
|
||||
>>> ls1 == ls2
|
||||
False
|
||||
>>> ls3 == ls2 # different SRIDs
|
||||
False
|
||||
|
||||
.. versionchanged:: 1.11
|
||||
|
||||
Older versions didn't check the ``srid`` when comparing
|
||||
``GEOSGeometry`` objects using the equality operator.
|
||||
|
||||
Geometry Objects
|
||||
================
|
||||
|
|
|
@ -423,6 +423,8 @@ Backwards incompatible changes in 1.11
|
|||
the Google Maps API and seems to be unmaintained. If you're using it, `let
|
||||
us know <https://code.djangoproject.com/ticket/14284>`_.
|
||||
|
||||
* The ``GEOSGeometry`` equality operator now also compares SRID.
|
||||
|
||||
Database backend API
|
||||
--------------------
|
||||
|
||||
|
|
|
@ -266,7 +266,7 @@ class GISFunctionsTests(TestCase):
|
|||
State.objects.create(name='invalid', poly=invalid_geom)
|
||||
invalid = State.objects.filter(name='invalid').annotate(repaired=functions.MakeValid('poly')).first()
|
||||
self.assertIs(invalid.repaired.valid, True)
|
||||
self.assertEqual(invalid.repaired, fromstr('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'))
|
||||
self.assertEqual(invalid.repaired, fromstr('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', srid=invalid.poly.srid))
|
||||
|
||||
@skipUnlessDBFeature("has_MemSize_function")
|
||||
def test_memsize(self):
|
||||
|
|
|
@ -63,9 +63,9 @@ class GeoModelTest(TestCase):
|
|||
nullcity.point.x = 23
|
||||
nullcity.point.y = 5
|
||||
# Checking assignments pre & post-save.
|
||||
self.assertNotEqual(Point(23, 5), City.objects.get(name='NullCity').point)
|
||||
self.assertNotEqual(Point(23, 5, srid=4326), City.objects.get(name='NullCity').point)
|
||||
nullcity.save()
|
||||
self.assertEqual(Point(23, 5), City.objects.get(name='NullCity').point)
|
||||
self.assertEqual(Point(23, 5, srid=4326), City.objects.get(name='NullCity').point)
|
||||
nullcity.delete()
|
||||
|
||||
# Testing on a Polygon
|
||||
|
@ -479,8 +479,11 @@ class GeoQuerySetTest(TestCase):
|
|||
# SpatiaLite).
|
||||
pass
|
||||
else:
|
||||
self.assertEqual(c.mpoly.difference(geom), c.difference)
|
||||
if not spatialite:
|
||||
if spatialite:
|
||||
# Spatialite `difference` doesn't have an SRID
|
||||
self.assertEqual(c.mpoly.difference(geom).wkt, c.difference.wkt)
|
||||
else:
|
||||
self.assertEqual(c.mpoly.difference(geom), c.difference)
|
||||
self.assertEqual(c.mpoly.intersection(geom), c.intersection)
|
||||
# Ordering might differ in collections
|
||||
self.assertSetEqual(set(g.wkt for g in c.mpoly.sym_difference(geom)),
|
||||
|
|
|
@ -227,6 +227,27 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
|
|||
self.assertNotEqual(g, {'foo': 'bar'})
|
||||
self.assertNotEqual(g, False)
|
||||
|
||||
def test_eq_with_srid(self):
|
||||
"Testing non-equivalence with different srids."
|
||||
p0 = Point(5, 23)
|
||||
p1 = Point(5, 23, srid=4326)
|
||||
p2 = Point(5, 23, srid=32632)
|
||||
# GEOS
|
||||
self.assertNotEqual(p0, p1)
|
||||
self.assertNotEqual(p1, p2)
|
||||
# EWKT
|
||||
self.assertNotEqual(p0, p1.ewkt)
|
||||
self.assertNotEqual(p1, p0.ewkt)
|
||||
self.assertNotEqual(p1, p2.ewkt)
|
||||
# Equivalence with matching SRIDs
|
||||
self.assertEqual(p2, p2)
|
||||
self.assertEqual(p2, p2.ewkt)
|
||||
# WKT contains no SRID so will not equal
|
||||
self.assertNotEqual(p2, p2.wkt)
|
||||
# SRID of 0
|
||||
self.assertEqual(p0, 'SRID=0;POINT (5 23)')
|
||||
self.assertNotEqual(p1, 'SRID=0;POINT (5 23)')
|
||||
|
||||
def test_points(self):
|
||||
"Testing Point objects."
|
||||
prev = fromstr('POINT(0 0)')
|
||||
|
|
|
@ -36,7 +36,7 @@ class RelatedGeoModelTest(TestCase):
|
|||
nm, st, lon, lat = ref
|
||||
self.assertEqual(nm, c.name)
|
||||
self.assertEqual(st, c.state)
|
||||
self.assertEqual(Point(lon, lat), c.location.point)
|
||||
self.assertEqual(Point(lon, lat, srid=c.location.point.srid), c.location.point)
|
||||
|
||||
@skipUnlessDBFeature("has_transform_method")
|
||||
def test03_transform_related(self):
|
||||
|
|
|
@ -48,12 +48,17 @@ class GeometryFieldTest(SimpleTestCase):
|
|||
# By default, all geometry types are allowed.
|
||||
fld = forms.GeometryField()
|
||||
for wkt in ('POINT(5 23)', 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))', 'LINESTRING(0 0, 1 1)'):
|
||||
self.assertEqual(GEOSGeometry(wkt), fld.clean(wkt))
|
||||
# `to_python` uses the SRID of OpenLayersWidget if the converted
|
||||
# value doesn't have an SRID itself.
|
||||
self.assertEqual(GEOSGeometry(wkt, srid=fld.widget.map_srid), fld.clean(wkt))
|
||||
|
||||
pnt_fld = forms.GeometryField(geom_type='POINT')
|
||||
self.assertEqual(GEOSGeometry('POINT(5 23)'), pnt_fld.clean('POINT(5 23)'))
|
||||
self.assertEqual(GEOSGeometry('POINT(5 23)', srid=pnt_fld.widget.map_srid), pnt_fld.clean('POINT(5 23)'))
|
||||
# a WKT for any other geom_type will be properly transformed by `to_python`
|
||||
self.assertEqual(GEOSGeometry('LINESTRING(0 0, 1 1)'), pnt_fld.to_python('LINESTRING(0 0, 1 1)'))
|
||||
self.assertEqual(
|
||||
GEOSGeometry('LINESTRING(0 0, 1 1)', srid=pnt_fld.widget.map_srid),
|
||||
pnt_fld.to_python('LINESTRING(0 0, 1 1)')
|
||||
)
|
||||
# but rejected by `clean`
|
||||
with self.assertRaises(forms.ValidationError):
|
||||
pnt_fld.clean('LINESTRING(0 0, 1 1)')
|
||||
|
@ -66,7 +71,7 @@ class GeometryFieldTest(SimpleTestCase):
|
|||
fld = forms.GeometryField()
|
||||
# to_python returns the same GEOSGeometry for a WKT
|
||||
for wkt in ('POINT(5 23)', 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))', 'LINESTRING(0 0, 1 1)'):
|
||||
self.assertEqual(GEOSGeometry(wkt), fld.to_python(wkt))
|
||||
self.assertEqual(GEOSGeometry(wkt, srid=fld.widget.map_srid), fld.to_python(wkt))
|
||||
# but raises a ValidationError for any other string
|
||||
for wkt in ('POINT(5)', 'MULTI POLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))', 'BLAH(0 0, 1 1)'):
|
||||
with self.assertRaises(forms.ValidationError):
|
||||
|
@ -78,7 +83,7 @@ class GeometryFieldTest(SimpleTestCase):
|
|||
|
||||
form = PointForm()
|
||||
cleaned_pt = form.fields['pt'].clean('POINT(5 23)')
|
||||
self.assertEqual(cleaned_pt, GEOSGeometry('POINT(5 23)'))
|
||||
self.assertEqual(cleaned_pt, GEOSGeometry('POINT(5 23)', srid=4326))
|
||||
self.assertEqual(4326, cleaned_pt.srid)
|
||||
|
||||
point = GEOSGeometry('SRID=4326;POINT(5 23)')
|
||||
|
|
Loading…
Reference in New Issue