如何使用Shapely移除MultiLineString中的孤立短线
解决MultiLineString中孤立短线段的过滤问题
咱们先聚焦第一个子问题:如何识别MultiLineString里的孤立线段。这里的孤立线段指的是和其他任何线段都没有接触(端点重合)或相交的线段,用Shapely自带的空间关系判断方法就能轻松实现。
核心思路
对于MultiLineString中的每一条线段,我们需要检查它是否和其他所有线段都没有空间交集。Shapely的intersects()方法正好能帮我们做这件事——它会返回True如果两个几何对象存在任何形式的空间重叠(包括端点接触、线段交叉、部分重合等)。反过来,如果一条线段和其他所有线段的intersects()结果都是False,那它就是孤立线段。
实现代码
先写一个函数来提取所有孤立线段:
from shapely.geometry import MultiLineString def get_isolated_segments(multiline): segments = list(multiline) isolated_segs = [] for idx, seg in enumerate(segments): # 标记当前线段是否和其他线段有连接 has_connection = False for other_idx, other_seg in enumerate(segments): if idx == other_idx: continue # 跳过自己和自己对比 if seg.intersects(other_seg): has_connection = True break # 只要有一个连接就不用继续检查了 if not has_connection: isolated_segs.append(seg) return isolated_segs
结合长度过滤的完整解决方案
现在把两个子问题结合起来:过滤掉既是孤立线段且长度小于2的线段,剩下的线段重新组成MultiLineString。完整代码如下(基于你的示例修改):
from shapely.geometry import MultiLineString from pprint import pprint from matplotlib import pyplot from figures import SIZE, set_limits, plot_line, plot_bounds, color_issimple from figures import plot_coords as _plot_coords def plot_coords(ax, ob): for line in ob: _plot_coords(ax, line, zorder=1) def plot_lines(ax, ob): color = color_issimple(ob) for line in ob: plot_line(ax, line, color=color, alpha=0.7, zorder=2) def get_isolated_segments(multiline): segments = list(multiline) isolated_segs = [] for idx, seg in enumerate(segments): has_connection = False for other_idx, other_seg in enumerate(segments): if idx == other_idx: continue if seg.intersects(other_seg): has_connection = True break if not has_connection: isolated_segs.append(seg) return isolated_segs fig = pyplot.figure(1, figsize=SIZE, dpi=90) # 1: 原始MultiLineString ax = fig.add_subplot(121) mline1 = MultiLineString([((0, 0), (2, 0)), ((1, 0), (1, 1)), ((1, 2), (3, 2)), ((3, 0), (3, 1))]) plot_coords(ax, mline1) plot_bounds(ax, mline1) plot_lines(ax, mline1) ax.set_title('a) original') set_limits(ax, -1, 4, -1, 3) # 2: 过滤后的结果 ax = fig.add_subplot(122) isolated_segs = get_isolated_segments(mline1) # 保留条件:非孤立线段 或者 是孤立但长度≥2的线段 filtered_segments = [ seg for seg in list(mline1) if seg not in isolated_segs or seg.length >= 2 ] mline2 = MultiLineString(filtered_segments) plot_coords(ax, mline2) plot_bounds(ax, mline2) plot_lines(ax, mline2) ax.set_title('b) filtered result') set_limits(ax, -1, 4, -1, 3) pyplot.show()
代码说明
get_isolated_segments()函数会返回所有孤立线段的列表- 过滤逻辑中,我们保留两类线段:
- 不属于孤立线段的(和其他线段有连接的)
- 是孤立线段但长度≥2的(符合长度要求的孤立线段)
- 运行这段代码后,右边的子图会和你示例中的
goal完全一致——那条长度为1的孤立竖直线段((3,0),(3,1))会被过滤掉。
内容的提问来源于stack exchange,提问作者yzhou
相关产品推荐
相关产品推荐

