检查点是否在多边形内 returns Shapely 中的错误结果
Checking whether point is within polygon returns wrong results in Shapely
我有一个多边形作为 wkt 格式的字符串:
polygon_as_string = 'POLYGON ((1190500.159499999 7144386.067199998, 1190487.2751 7144390.519699998,...,1190500.159499999 7144386.067199998))'
我将其转换为 Shapely 的 Polygon
对象:
import shapely.wkt
polygon = shapely.wkt.loads(polygon_as_string)
然后我使用 within()
或 contains()
函数检查该点是否在我的多边形中。
from shapely.geometry import Point, Polygon
point = Point(1190500.159499999, 7144386.067199998)
polygon.contains(point)
point.within(polygon)
两个函数return False
虽然我拿的点实际上是在polygon
里面。
这里可能有什么问题?
原因可能是您正在测试的点恰好位于其中一个顶点的顶部并且由于舍入误差,该点实际上移动了一点并且不再位于多边形的边缘。
要验证这个假设,请尝试将测试点向多边形的中心移动一点。
您使用错误的 predicate 来检查一个点是在多边形的内部 还是在多边形的边界 上。
来自 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.
相反,因为你的点在边界上,你应该使用 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.
(强调我的)。
可重现的小例子:
>>> 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
但是请注意,由于精度错误,您确实可能会得到意想不到的结果:
>>> 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
在这种情况下,您可以考虑如上所示检查到多边形的距离,或者使用 buffer
:
稍微扩大多边形
>>> Point(2/3, 2).intersects(Polygon([(0, 0), (1, 0), (1, 3)]).buffer(1e-9))
True
我有一个多边形作为 wkt 格式的字符串:
polygon_as_string = 'POLYGON ((1190500.159499999 7144386.067199998, 1190487.2751 7144390.519699998,...,1190500.159499999 7144386.067199998))'
我将其转换为 Shapely 的 Polygon
对象:
import shapely.wkt
polygon = shapely.wkt.loads(polygon_as_string)
然后我使用 within()
或 contains()
函数检查该点是否在我的多边形中。
from shapely.geometry import Point, Polygon
point = Point(1190500.159499999, 7144386.067199998)
polygon.contains(point)
point.within(polygon)
两个函数return False
虽然我拿的点实际上是在polygon
里面。
这里可能有什么问题?
原因可能是您正在测试的点恰好位于其中一个顶点的顶部并且由于舍入误差,该点实际上移动了一点并且不再位于多边形的边缘。
要验证这个假设,请尝试将测试点向多边形的中心移动一点。
您使用错误的 predicate 来检查一个点是在多边形的内部 还是在多边形的边界 上。
来自 documentation on contains
(which is inverse of within
):
object.contains(other)
ReturnsTrue
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.
相反,因为你的点在边界上,你应该使用 intersects
:
object.intersects(other)
ReturnsTrue
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.
(强调我的)。
可重现的小例子:
>>> 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
但是请注意,由于精度错误,您确实可能会得到意想不到的结果:
>>> 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
在这种情况下,您可以考虑如上所示检查到多边形的距离,或者使用 buffer
:
>>> Point(2/3, 2).intersects(Polygon([(0, 0), (1, 0), (1, 3)]).buffer(1e-9))
True