{{{#!python
from django.contrib.gis.geos import Point
p1 = Point(x=1, y=1, z=1, srid=4326)
print p1 == p1 # True
p2 = Point(x=1.1, y=1, z=1, srid=4326)
print p1 == p2 # False
p3 = Point(x=1, y=1, z=2, srid=4326)
print p1 == p3 # True. Is this a bug?
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/25342>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0
Old description:
> Checking equality of two django.contrib.gis.geos.Point objects does not
> take into consideration the altitude of the point.
>
> {{{#!python
> from django.contrib.gis.geos import Point
>
> p1 = Point(x=1, y=1, z=1, srid=4326)
> print p1 == p1 # True
>
> p2 = Point(x=1.1, y=1, z=1, srid=4326)
> print p1 == p2 # False
>
> p3 = Point(x=1, y=1, z=2, srid=4326)
> print p1 == p3 # True. Is this a bug?
> }}}
New description:
Checking equality of two django.contrib.gis.geos.Point objects does not
take into consideration the altitude of the point.
{{{#!python
from django.contrib.gis.geos import Point
p1 = Point(x=1, y=1, z=1, srid=4326)
print p1 == p1 # True
p2 = Point(x=1.1, y=1, z=1, srid=4326)
print p1 == p2 # False
p3 = Point(x=1, y=1, z=2, srid=4326)
print p1 == p3 # True. Is this a bug?
}}}
--
--
Ticket URL: <https://code.djangoproject.com/ticket/25342#comment:1>
Comment (by bkowshik):
I began by checking if the `Point` object had the magic method `__eq__`.
https://github.com/django/django/blob/master/django/contrib/gis/geos/point.py#L10
The `Point` objects inherits `GEOSGeometry` which in-turn has the magic
method `__eq__`.
https://github.com/django/django/blob/master/django/contrib/gis/geos/geometry.py#L166
This in-turn calls `equals_exact` of `GEOSGeometry`.
https://github.com/django/django/blob/master/django/contrib/gis/geos/geometry.py#L317
This calls `geos_equalsexact` on the page below.
https://github.com/django/django/blob/8047e3666b0b50bb04e6f16c2a4fb21ddfd5713f/django/contrib/gis/geos/prototypes/predicates.py#L36
I don't understand what happens after this.
--
Ticket URL: <https://code.djangoproject.com/ticket/25342#comment:2>
* version: 1.7 => master
* stage: Unreviewed => Accepted
Comment:
This is most probably a GEOS issue, where the Z dimension support is
rather new.
Keeping open until we find where the problem really lies.
Here is some interesting GEOS code:
https://svn.osgeo.org/geos/trunk/src/geom/
--
Ticket URL: <https://code.djangoproject.com/ticket/25342#comment:3>
* cc: olivier.tabone@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/25342#comment:4>
Comment (by Claude Paroz):
GEOS is going to introduce a new API for a comparison considering a
possible 3rd dimension (`GEOSEqualsIdentical`) to not break backwards
compatibility. It will be included in the not-yet-released GEOS 3.12.0.
https://github.com/libgeos/geos/commit/85a1779e18
We will have to decide at some point if we want to break (and document)
backwards compatibility by using the new API in the basic equality
operator, or introduce a new API too.
--
Ticket URL: <https://code.djangoproject.com/ticket/25342#comment:5>
Comment (by Olivier Tabone):
Prior 3.12.0, GEOS already has [https://github.com/libgeos/geos/pull/810
multiple equality functions]:
- `GEOSEquals` (which uses topological equality, returning true for
different representations of the same structure)
- `GEOSEqualsExact` (which uses pointwise equality, but allows for a
distance tolerance and ignores Z/M values)
currently, django uses
[https://libgeos.org/doxygen/geos__c_8h.html#a23922c100edd72a8d82720213607e7bf
GEOSEqualsExact] in the
[https://github.com/django/django/blob/95e4d6b81312fdd9f8ebf3385be1c1331168b5cf/django/contrib/gis/geos/geometry.py#L144
__eq__() method] which is not a good fit regarding equality semantics when
z is used (thus this ticket).
`GEOSEquals()` does not work in 3D
[https://libgeos.org/doxygen/geos__c_8h.html#a45499a7d87851015d36e57d285da9d8e
as documented] which is not a good fit regarding equality semantics
either.
GEOS 3.12 introduces `GEOSEqualsIdentical` which is a good fit for
python's equality semantic in 2D and 3D.
I would suggest:
- implementing the `GEOSGeometryBase.equals_identical()` method,
available if GEOS >= 3.12.0. That should be an easy call, pure additive.
(new ticket ?)
- raising a warning if `GEOSGeometryBase.__eq__()` is called with one
operand having a third dimension (`geom.hasZ == True`). To fix this
warning, one should either use an explicit comparaison method
(`GEOSGeometryBase.equals()`, `GEOSGeometryBase.equals_exact()`,
`GEOSGeometryBase.equals_identical()`) or use a 2D point.
- when GEOS 3.12 becomes the minimum supported version, use
GEOSEqualsIdentical to perform `GEOSGeometryBase.__eq__()`. This will
give some time for one to adapt their code bases.
What do you think ?
--
Ticket URL: <https://code.djangoproject.com/ticket/25342#comment:6>
Comment (by Claude Paroz):
Looks like a good plan to me!
--
Ticket URL: <https://code.djangoproject.com/ticket/25342#comment:7>
* owner: nobody => Olivier Tabone
* status: new => assigned
--
Ticket URL: <https://code.djangoproject.com/ticket/25342#comment:8>
Comment (by Olivier Tabone):
ticket for `GEOSGeometryBase.equals_identical()` implementation: #34739
--
Ticket URL: <https://code.djangoproject.com/ticket/25342#comment:9>