Opened 7 years ago

Closed 7 years ago

#27971 closed Bug (invalid)

GeoDjango LinearRing and Polygon handle contains/covers differently

Reported by: Geoffrey Fairchild Owned by: nobody
Component: GIS Version: 1.10
Severity: Normal Keywords: GeoDjango, LinearRing, Polygon, covers, contains
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I'm running Python 3.6.0 and Django 1.10.6. I'm seeing a difference in how the LinearRing and Polygon types deal with the contains and covers methods. The gist is that LinearRing objects seem not to properly handle contains/covers, while Polygon objects do. See the following example:

> python
Python 3.6.0 (default, Mar  6 2017, 11:41:46)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from django.contrib.gis.geos import GEOSGeometry
>>> aruba = GEOSGeometry('SRID=4326;LINEARRING (-69.89912109375 12.45200195312499, -69.895703125 12.42299804687499, -69.94218749999999 12.43852539062499, -70.004150390625 12.50048828125, -70.06611328125 12.54697265624999, -70.05087890624999 12.59707031249999, -70.035107421875 12.61411132812499, -69.97314453125 12.567626953125, -69.91181640625 12.48046875, -69.89912109375 12.45200195312499)')
>>> print(aruba)
SRID=4326;LINEARRING (-69.89912109375 12.45200195312499, -69.895703125 12.42299804687499, -69.94218749999999 12.43852539062499, -70.004150390625 12.50048828125, -70.06611328125 12.54697265624999, -70.05087890624999 12.59707031249999, -70.035107421875 12.61411132812499, -69.97314453125 12.567626953125, -69.91181640625 12.48046875, -69.89912109375 12.45200195312499)
>>> point = GEOSGeometry('POINT (-69.95647745161588 12.48564548990554)')
>>> print(point)
POINT (-69.95647745161588 12.48564548990554)
>>> aruba.contains(point)
False
>>> aruba.covers(point)
False
>>> aruba = GEOSGeometry('SRID=4326;POLYGON ((-69.89912109375 12.45200195312499, -69.895703125 12.42299804687499, -69.94218749999999 12.43852539062499, -70.004150390625 12.50048828125, -70.06611328125 12.54697265624999, -70.05087890624999 12.59707031249999, -70.035107421875 12.61411132812499, -69.97314453125 12.567626953125, -69.91181640625 12.48046875, -69.89912109375 12.45200195312499))')
>>> print(aruba)
SRID=4326;POLYGON ((-69.89912109375 12.45200195312499, -69.895703125 12.42299804687499, -69.94218749999999 12.43852539062499, -70.004150390625 12.50048828125, -70.06611328125 12.54697265624999, -70.05087890624999 12.59707031249999, -70.035107421875 12.61411132812499, -69.97314453125 12.567626953125, -69.91181640625 12.48046875, -69.89912109375 12.45200195312499))
>>> aruba.contains(point)
True
>>> aruba.covers(point)
True

For what it's worth, while writing this issue, I just discovered that Shapely, which also relies on GEOS, displays the same behavior:

> python
Python 3.6.0 (default, Mar  6 2017, 11:41:46)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from shapely.geometry.polygon import LinearRing, Polygon
>>> from shapely.geometry import Point
>>> aruba = LinearRing([(-69.89912109375, 12.45200195312499), (-69.895703125, 12.42299804687499), (-69.94218749999999, 12.43852539062499), (-70.004150390625, 12.50048828125), (-70.06611328125, 12.54697265624999), (-70.05087890624999, 12.59707031249999), (-70.035107421875, 12.61411132812499), (-69.97314453125, 12.567626953125), (-69.91181640625, 12.48046875), (-69.89912109375, 12.45200195312499)])
>>> print(aruba)
LINEARRING (-69.89912109375 12.45200195312499, -69.895703125 12.42299804687499, -69.94218749999999 12.43852539062499, -70.004150390625 12.50048828125, -70.06611328125 12.54697265624999, -70.05087890624999 12.59707031249999, -70.035107421875 12.61411132812499, -69.97314453125 12.567626953125, -69.91181640625 12.48046875, -69.89912109375 12.45200195312499)
>>> point = Point(-69.95647745161588, 12.48564548990554)
>>> print(point)
POINT (-69.95647745161588 12.48564548990554)
>>> aruba.contains(point)
False
>>> aruba = Polygon([(-69.89912109375, 12.45200195312499), (-69.895703125, 12.42299804687499), (-69.94218749999999, 12.43852539062499), (-70.004150390625, 12.50048828125), (-70.06611328125, 12.54697265624999), (-70.05087890624999, 12.59707031249999), (-70.035107421875, 12.61411132812499), (-69.97314453125, 12.567626953125), (-69.91181640625, 12.48046875), (-69.89912109375, 12.45200195312499)])
>>> print(aruba)
POLYGON ((-69.89912109375 12.45200195312499, -69.895703125 12.42299804687499, -69.94218749999999 12.43852539062499, -70.004150390625 12.50048828125, -70.06611328125 12.54697265624999, -70.05087890624999 12.59707031249999, -70.035107421875 12.61411132812499, -69.97314453125 12.567626953125, -69.91181640625 12.48046875, -69.89912109375 12.45200195312499))
>>> aruba.contains(point)
True

Is this a bug (perhaps a GEOS bug since both Shapely and GeoDjango display the same behavior), or is this to be expected (i.e., am I misunderstanding some fundamental concept about LinearRings)?

Change History (2)

comment:1 by Geoffrey Fairchild, 7 years ago

Search results for this topic seem sparse. Interestingly, I can compute centroids for both LinearRings and Polygons:

> python
Python 3.6.0 (default, Mar  6 2017, 11:41:46)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from django.contrib.gis.geos import GEOSGeometry
>>> aruba = GEOSGeometry('SRID=4326;LINEARRING (-69.89912109375 12.45200195312499, -69.895703125 12.42299804687499, -69.94218749999999 12.43852539062499, -70.004150390625 12.50048828125, -70.06611328125 12.54697265624999, -70.05087890624999 12.59707031249999, -70.035107421875 12.61411132812499, -69.97314453125 12.567626953125, -69.91181640625 12.48046875, -69.89912109375 12.45200195312499)')
>>> print(aruba)
SRID=4326;LINEARRING (-69.89912109375 12.45200195312499, -69.895703125 12.42299804687499, -69.94218749999999 12.43852539062499, -70.004150390625 12.50048828125, -70.06611328125 12.54697265624999, -70.05087890624999 12.59707031249999, -70.035107421875 12.61411132812499, -69.97314453125 12.567626953125, -69.91181640625 12.48046875, -69.89912109375 12.45200195312499)
>>> print(aruba.centroid)
SRID=4326;POINT (-69.97885392271023 12.51632637412778)
>>> aruba = GEOSGeometry('SRID=4326;POLYGON ((-69.89912109375 12.45200195312499, -69.895703125 12.42299804687499, -69.94218749999999 12.43852539062499, -70.004150390625 12.50048828125, -70.06611328125 12.54697265624999, -70.05087890624999 12.59707031249999, -70.035107421875 12.61411132812499, -69.97314453125 12.567626953125, -69.91181640625 12.48046875, -69.89912109375 12.45200195312499))')
>>> print(aruba)
SRID=4326;POLYGON ((-69.89912109375 12.45200195312499, -69.895703125 12.42299804687499, -69.94218749999999 12.43852539062499, -70.004150390625 12.50048828125, -70.06611328125 12.54697265624999, -70.05087890624999 12.59707031249999, -70.035107421875 12.61411132812499, -69.97314453125 12.567626953125, -69.91181640625 12.48046875, -69.89912109375 12.45200195312499))
>>> print(aruba.centroid)
SRID=4326;POINT (-69.98267711250941 12.52088038384019)

If I can compute a centroid, why can't I compute whether another geometry is interior to the LinearRing?

comment:2 by Sergey Fedoseev, 7 years ago

Resolution: invalid
Status: newclosed

LinearRing is a line, so it doesn't contain or cover the specified point.
Look at http://bl.ocks.org/d/51034db6faf00af30734b1e7e1b2bf03

Note: See TracTickets for help on using tickets.
Back to Top