mirror of https://github.com/django/django.git
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):
|
def __eq__(self, other):
|
||||||
"""
|
"""
|
||||||
Equivalence testing, a Geometry may be compared with another Geometry
|
Equivalence testing, a Geometry may be compared with another Geometry
|
||||||
or a WKT representation.
|
or an EWKT representation.
|
||||||
"""
|
"""
|
||||||
if isinstance(other, six.string_types):
|
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):
|
elif isinstance(other, GEOSGeometry):
|
||||||
return self.equals_exact(other)
|
return self.srid == other.srid and self.equals_exact(other)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -160,15 +160,23 @@ Geometries support set-like operators::
|
||||||
The :class:`~GEOSGeometry` equality operator uses
|
The :class:`~GEOSGeometry` equality operator uses
|
||||||
:meth:`~GEOSGeometry.equals_exact`, not :meth:`~GEOSGeometry.equals`, i.e.
|
:meth:`~GEOSGeometry.equals_exact`, not :meth:`~GEOSGeometry.equals`, i.e.
|
||||||
it requires the compared geometries to have the same coordinates in the
|
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
|
>>> from django.contrib.gis.geos import LineString
|
||||||
>>> ls1 = LineString((0, 0), (1, 1))
|
>>> ls1 = LineString((0, 0), (1, 1))
|
||||||
>>> ls2 = LineString((1, 1), (0, 0))
|
>>> ls2 = LineString((1, 1), (0, 0))
|
||||||
|
>>> ls3 = LineString((1, 1), (0, 0), srid=4326)
|
||||||
>>> ls1.equals(ls2)
|
>>> ls1.equals(ls2)
|
||||||
True
|
True
|
||||||
>>> ls1 == ls2
|
>>> ls1 == ls2
|
||||||
False
|
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
|
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
|
the Google Maps API and seems to be unmaintained. If you're using it, `let
|
||||||
us know <https://code.djangoproject.com/ticket/14284>`_.
|
us know <https://code.djangoproject.com/ticket/14284>`_.
|
||||||
|
|
||||||
|
* The ``GEOSGeometry`` equality operator now also compares SRID.
|
||||||
|
|
||||||
Database backend API
|
Database backend API
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
|
|
@ -266,7 +266,7 @@ class GISFunctionsTests(TestCase):
|
||||||
State.objects.create(name='invalid', poly=invalid_geom)
|
State.objects.create(name='invalid', poly=invalid_geom)
|
||||||
invalid = State.objects.filter(name='invalid').annotate(repaired=functions.MakeValid('poly')).first()
|
invalid = State.objects.filter(name='invalid').annotate(repaired=functions.MakeValid('poly')).first()
|
||||||
self.assertIs(invalid.repaired.valid, True)
|
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")
|
@skipUnlessDBFeature("has_MemSize_function")
|
||||||
def test_memsize(self):
|
def test_memsize(self):
|
||||||
|
|
|
@ -63,9 +63,9 @@ class GeoModelTest(TestCase):
|
||||||
nullcity.point.x = 23
|
nullcity.point.x = 23
|
||||||
nullcity.point.y = 5
|
nullcity.point.y = 5
|
||||||
# Checking assignments pre & post-save.
|
# 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()
|
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()
|
nullcity.delete()
|
||||||
|
|
||||||
# Testing on a Polygon
|
# Testing on a Polygon
|
||||||
|
@ -479,8 +479,11 @@ class GeoQuerySetTest(TestCase):
|
||||||
# SpatiaLite).
|
# SpatiaLite).
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.assertEqual(c.mpoly.difference(geom), c.difference)
|
if spatialite:
|
||||||
if not 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)
|
self.assertEqual(c.mpoly.intersection(geom), c.intersection)
|
||||||
# Ordering might differ in collections
|
# Ordering might differ in collections
|
||||||
self.assertSetEqual(set(g.wkt for g in c.mpoly.sym_difference(geom)),
|
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, {'foo': 'bar'})
|
||||||
self.assertNotEqual(g, False)
|
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):
|
def test_points(self):
|
||||||
"Testing Point objects."
|
"Testing Point objects."
|
||||||
prev = fromstr('POINT(0 0)')
|
prev = fromstr('POINT(0 0)')
|
||||||
|
|
|
@ -36,7 +36,7 @@ class RelatedGeoModelTest(TestCase):
|
||||||
nm, st, lon, lat = ref
|
nm, st, lon, lat = ref
|
||||||
self.assertEqual(nm, c.name)
|
self.assertEqual(nm, c.name)
|
||||||
self.assertEqual(st, c.state)
|
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")
|
@skipUnlessDBFeature("has_transform_method")
|
||||||
def test03_transform_related(self):
|
def test03_transform_related(self):
|
||||||
|
|
|
@ -48,12 +48,17 @@ class GeometryFieldTest(SimpleTestCase):
|
||||||
# By default, all geometry types are allowed.
|
# By default, all geometry types are allowed.
|
||||||
fld = forms.GeometryField()
|
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)'):
|
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')
|
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`
|
# 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`
|
# but rejected by `clean`
|
||||||
with self.assertRaises(forms.ValidationError):
|
with self.assertRaises(forms.ValidationError):
|
||||||
pnt_fld.clean('LINESTRING(0 0, 1 1)')
|
pnt_fld.clean('LINESTRING(0 0, 1 1)')
|
||||||
|
@ -66,7 +71,7 @@ class GeometryFieldTest(SimpleTestCase):
|
||||||
fld = forms.GeometryField()
|
fld = forms.GeometryField()
|
||||||
# to_python returns the same GEOSGeometry for a WKT
|
# 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)'):
|
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
|
# 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)'):
|
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):
|
with self.assertRaises(forms.ValidationError):
|
||||||
|
@ -78,7 +83,7 @@ class GeometryFieldTest(SimpleTestCase):
|
||||||
|
|
||||||
form = PointForm()
|
form = PointForm()
|
||||||
cleaned_pt = form.fields['pt'].clean('POINT(5 23)')
|
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)
|
self.assertEqual(4326, cleaned_pt.srid)
|
||||||
|
|
||||||
point = GEOSGeometry('SRID=4326;POINT(5 23)')
|
point = GEOSGeometry('SRID=4326;POINT(5 23)')
|
||||||
|
|
Loading…
Reference in New Issue