用相交的线串 B 分割线串 A 不会产生预期的输出(返回 A)。 使用包含 B 和 C(C 也与 A 相交)的多线串拆分 A 会产生所需的输出(3 段)。 这似乎不一致。
from shapely.ops import split
from shapely.geometry import LineString, MultiLineString
A = LineString([(0, 0), (10, 0)])
B = LineString([(5, 0), (5, 5)])
C = LineString([(1, -1), (1, 1)])
assert (split(A, B).wkt == "GEOMETRYCOLLECTION (LINESTRING (0 0, 10 0))")
# Does not split
# Expected: "GEOMETRYCOLLECTION (LINESTRING (0 0, 5 0), LINESTRING (5 0, 10 0))"
assert (A.intersection(B).wkt == "POINT (5 0)")
# Although A and B do intersect
assert (split(A, MultiLineString([B, C])).wkt ==
"GEOMETRYCOLLECTION (LINESTRING (0 0, 1 0), LINESTRING (1 0, 5 0), LINESTRING (5 0, 10 0))")
# OK - A is split by both B and C - but A was not split by B in the previous example.
Ubuntu 18.04.2 LTS
Python 3.6.7 - Shapely 1.6.4.post2(使用 pip 从 PyPI 安装)
行。 我在这里看到了问题。
从视觉上看,这些线串如下所示:
当您将水平线 ( A ) 与顶部 ( B ) 上仅接触A的大垂直线分开时,没有任何反应。 但是用C分割A确实有效,因为C穿过A 。
现在,当您将A按MultiLineString([B, C])
拆分时,它会拆分为三个线串,而不是您期望的两个。 我同意这似乎不一致。
导致这种情况的代码实际上很容易访问(永久链接)。
<strong i="26">@staticmethod</strong>
def _split_line_with_line(line, splitter):
"""Split a LineString with another (Multi)LineString or (Multi)Polygon"""
# if splitter is a polygon, pick it's boundary
if splitter.type in ('Polygon', 'MultiPolygon'):
splitter = splitter.boundary
assert(isinstance(line, LineString))
assert(isinstance(splitter, LineString) or isinstance(splitter, MultiLineString))
if splitter.crosses(line):
# The lines cross --> return multilinestring from the split
return line.difference(splitter)
elif splitter.relate_pattern(line, '1********'):
# The lines overlap at some segment (linear intersection of interiors)
raise ValueError('Input geometry segment overlaps with the splitter.')
else:
# The lines do not cross --> return collection with identity line
return [line]
您可以看到splitter
需要穿过line
才能开始任何拆分。 但是一旦通过该检查点,就会对difference
进行简单调用以生成分割几何图形。 但是difference
不区分穿越和仅仅接触! 因此,如果在任何时候splitter
line
交叉,那么所有仅仅是接触点都将被拆分。
@Jeremiah-England 感谢您对此进行深入研究! 似乎,至少对于线条,我们可以将交叉测试更改为接触测试并获得不那么令人惊讶的结果? 你怎么看?
我认为这会很好,是的。 这种行为对我来说很有意义。
有一段时间,我认为我们可以过滤 MultiLineString splitter
的 goem,为那些穿过line
过滤,并只取那些的差异。 但这并不能解决单个 LineString splitter
钩回以触摸它在另一点穿过的line
情况。 我认为在使用difference
进行繁重工作时获得一致行为的唯一方法是拆分接触的线性几何图形。
我怀疑可能crosses
被使用了,所以当只有line
的边界接触splitter
时,函数会提前返回。 事实上,这个案例是针对. 但是我们目前的情况,其中splitter
的边界接触line
,不在测试中,并且可能是一个盲点。 但是,我是一个 Shapely 本地人,对其他简单的功能库没有太多经验。 而且我不知道仅在交叉时分裂是否是线性几何的标准行为。
那是 5 年前,但如果@georgeouzou记得,也许他可以确认或解释为什么使用crosses
?
如果我们想在测试的情况下早点返回,我们也可以吃蛋糕并吃掉它,但在这个问题的情况下继续拆分。 这将需要直接使用relate
。 但我怀疑两种方式都会有很大的性能差异。
@Jeremiah-England 我的记忆有点模糊,但再次看到代码我可以确认这是一个盲点。 代码还应测试当前案例是否完整。 你能继续改变吗?
嘿@georgeouzou ,感谢您抽出时间来查看!
而且,是的,如果每个人都可以,我想敲定这个案例并在某个时候提交 PR。
最有用的评论
我认为这会很好,是的。 这种行为对我来说很有意义。
有一段时间,我认为我们可以过滤 MultiLineString
splitter
的 goem,为那些穿过line
过滤,并只取那些的差异。 但这并不能解决单个 LineStringsplitter
钩回以触摸它在另一点穿过的line
情况。 我认为在使用difference
进行繁重工作时获得一致行为的唯一方法是拆分接触的线性几何图形。我怀疑可能
crosses
被使用了,所以当只有line
的边界接触splitter
时,函数会提前返回。 事实上,这个案例是针对. 但是我们目前的情况,其中splitter
的边界接触line
,不在测试中,并且可能是一个盲点。 但是,我是一个 Shapely 本地人,对其他简单的功能库没有太多经验。 而且我不知道仅在交叉时分裂是否是线性几何的标准行为。那是 5 年前,但如果@georgeouzou记得,也许他可以确认或解释为什么使用
crosses
?如果我们想在测试的情况下早点返回,我们也可以吃蛋糕并吃掉它,但在这个问题的情况下继续拆分。 这将需要直接使用
relate
。 但我怀疑两种方式都会有很大的性能差异。