12

我有一个案例,它基于在一条线上投影一个点,然后将这条线分开。我的用例稍微复杂一些,但我的问题可以用以下代码重现:

from shapely import *
line1 = LineString([(1,1.2), (2,2), (3, 2.), (4,1.2)])
pt = Point(2.5, 1.2)
pr = line1.interpolate(line1.project(pt))

通过构造,“pr”应该在 line1 和它们的交点上:

line1.contains(pr)
line1.intersects(LineString([pt, pr]))

打印两次“真”。但是更改输入坐标会稍微影响工作流程:

from shapely import *
line1 = LineString([(1,1.2), (2,2), (3, 2.3), (4,1.2)])
pt = Point(2.5, 1.2)
pr = line1.interpolate(line1.project(pt))
line1.contains(pr)
line1.intersects(LineString([pt, pr]))

打印“假”。

我理解这背后的浮动精度问题,但这是否意味着我永远无法测试线上的点?当我根据点列表构造一条线时,我能否确定至少所有“构造”点都在线上?

4

1 回答 1

12

从根本上说,需要一个精确模型,并且有各种计划在某个时候将其实施到 GEOS 中(不要屏住呼吸,因为这已经讨论了好几年了)。

否则,选项是基于距离的测试(推荐)或更昂贵的基于缓冲区的技术,只需稍作调整(参见machine epsilon):

from shapely.geometry import LineString, Point

line1 = LineString([(1, 1.2), (2, 2), (3, 2.3), (4, 1.2)])
pt = Point(2.5, 1.2)
pr = line1.interpolate(line1.project(pt))

# Distance based
print(line1.distance(pr) == 0.0)  # True

# Buffer based
EPS = 1.2e-16
print(line1.buffer(EPS).contains(pr))  # True
print(line1.buffer(EPS).intersects(LineString([pt, pr])))  # True

您还可以使用oroperator链接更便宜和更昂贵的测试,例如:

print(line1.contains(pr) or line1.buffer(EPS).contains(pr))

如果第一个返回,它只运行第二个和更昂贵的测试False

于 2015-01-20T01:03:27.400 回答