Julia Koncha
Julia Koncha

Reputation: 95

Checking whether point is within polygon returns wrong results in Shapely

I have a polygon as a string in wkt format:

polygon_as_string = 'POLYGON ((1190500.159499999 7144386.067199998, 1190487.2751 7144390.519699998,...,1190500.159499999 7144386.067199998))'

which I convert to a Shapely's Polygon object:

import shapely.wkt
polygon = shapely.wkt.loads(polygon_as_string)

Then I check with within() or with contains() functions whether the point is in my polygon.

from shapely.geometry import Point, Polygon
point = Point(1190500.159499999, 7144386.067199998)
polygon.contains(point)
point.within(polygon)

Both functions return False although I take the point which is actually inside of the polygon. What could be wrong here?

Upvotes: 2

Views: 3619

Answers (2)

Georgy
Georgy

Reputation: 13697

You are using the wrong predicate to check if a point is inside or on the boundary of a polygon.

From documentation on contains (which is inverse of within):

object.contains(other)
Returns True if no points of other lie in the exterior of the object and at least one point of the interior of other lies in the interior of object.

Instead, as your point lies on the boundary, you should use intersects:

object.intersects(other)
Returns True if the boundary or interior of the object intersect in any way with those of the other.

In other words, geometric objects intersect if they have any boundary or interior point in common.

(emphasis mine).


Small reproducible example:
enter image description here

>>> from shapely.geometry import Point, Polygon
>>> Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]).contains(Point(1, 1))
False
>>> Point(1, 1).within(Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]))
False
>>> Point(1, 1).intersects(Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]))
True

Note, however, that due to precision errors you indeed can have an unexpected result:
enter image description here

>>> Point(2/3, 2).intersects(Polygon([(0, 0), (1, 0), (1, 3)]))
False
>>> Point(2/3, 2).distance(Polygon([(0, 0), (1, 0), (1, 3)]))
>>> 0.0

In cases like this you might consider either checking the distance to the polygon as shown above, or dilating your polygon a bit using buffer:

>>> Point(2/3, 2).intersects(Polygon([(0, 0), (1, 0), (1, 3)]).buffer(1e-9))
True

Upvotes: 10

marco romelli
marco romelli

Reputation: 1163

The reason could be that the point you are testing sits exactly on top of one of the vertices and due to rounding errors, the point actually moves a little bit and is not on the edge of the polygon anymore.

To check this hypothesis, try to move the test point a little bit towards the center of the polygon.

Upvotes: 0

Related Questions