我有一个案例,它基于在一条线上投射一个点然后在其上分开这一行。我的用例稍微复杂一些,但我的问题可以通过以下代码重现:
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"应该在第1行和它们的交叉点上:
line1.contains(pr)
line1.intersects(LineString([pt, pr]))
打印两次" True"。但是改变输入坐标会略微制动工作流程:
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]))
打印"错误"。
我理解这背后的浮动精度问题,但这是否意味着我永远不会测试线上的点?当我根据点列表构建一条线时,我能否确定至少所有"构造"积分会在线?
答案 0 :(得分:5)
从根本上说,需要precision model,并且有一些计划在某个时候将这一点实施到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
您还可以使用or operator链接更便宜,更昂贵的测试,例如:
print(line1.contains(pr) or line1.buffer(EPS).contains(pr))
如果第一个测试返回False
,则仅运行第二个且更昂贵的测试。