使用Shapely将单个线段焊接到一个LineString中


13

我在python中使用Shapely,并给了MultiLineString它一堆Linestring对象。我可以保证所有LineString对象都是只有2个顶点的简单线,并且它们都是一条直线的一部分(无分支)。

我想“连接点”并创建一个LineString。我是否需要为此编写递归焊接方法,还是有更快的方法?

Answers:


20

您可以使用shapelyops.linemerge做到这一点:

from shapely import geometry, ops

# create three lines
line_a = geometry.LineString([[0,0], [1,1]])
line_b = geometry.LineString([[1,1], [1,0]])
line_c = geometry.LineString([[1,0], [2,0]])

# combine them into a multi-linestring
multi_line = geometry.MultiLineString([line_a, line_b, line_c])
print(multi_line)  # prints MULTILINESTRING ((0 0, 1 1), (1 1, 2 2), (2 2, 3 3))

# you can now merge the lines
merged_line = ops.linemerge(multi_line)
print(merged_line)  # prints LINESTRING (0 0, 1 1, 2 2, 3 3)

# if your lines aren't contiguous
line_a = geometry.LineString([[0,0], [1,1]])
line_b = geometry.LineString([[1,1], [1,0]])
line_c = geometry.LineString([[2,0], [3,0]])

# combine them into a multi-linestring
multi_line = geometry.MultiLineString([line_a, line_b, line_c])
print(multi_line)  # prints MULTILINESTRING ((0 0, 1 1), (1 1, 1 0), (2 0, 3 0))

# note that it will now merge only the contiguous portions into a component of a new multi-linestring
merged_line = ops.linemerge(multi_line)
print(merged_line)  # prints MULTILINESTRING ((0 0, 1 1, 1 0), (2 0, 3 0))

我怎么知道哪个线串被合并了?我想收到类似以下的列表:merged = [[line_a,line_b],[line_c]]
james

您可以遍历各个行的列表,并检查新合并的行是否contains()为各个行。没有包含的内容将不会合并。例如merged_line.contains(line_a),它将返回布尔值TrueFalse
songololo

非常感谢。您如何检查该行是否包含在merged_lines中?
詹姆斯

1
啊,我不明白“ .contains(line_a)”是一个预先编写的函数。完善。非常感谢 !
詹姆斯

1
抱歉,再次打扰您...但是您知道谁合并“闭合”线(彼此之间具有一定的最大距离)吗?我之所以问是因为我看到许多行应该合并,但是由于它们之间的细小间隙,它们没有被合并。
詹姆斯

2

我认为您可以使用shapely.ops.linemerge()方法使用Shapely做到这一点。

看起来它可以将行列表作为输入并合并它们。我以前使用过'polygonize'方法,它确实需要一行行。

在此处查看文档:http : //toblerity.org/shapely/manual.html#shapely.ops.linemerge


1
您知道如何合并“闭合”的线(彼此之间具有一定的最大距离)吗?
詹姆斯

polygonize_full工作得更好一些,但结果却得到了一些奇怪的数据结构
danuker19年

1

shapely.ops.linemerge()我的某些生产线失败了,所以我不得不手动进行。对于那些“返回”自身的线来说,似乎失败了,即,多次穿越同一点。就我而言,我知道行的顺序正确,因此很容易编写一个小的函数来合并它们。

from shapely.geometry import LineString
from typing import List


def merge_lines(lines: List[LineString]) -> LineString:
    last = None
    points = []
    for line in merged_line:
        current = line.coords[0]

        if last is None:
            points.extend(line.coords)
        else:
            if last == current:
                points.extend(line.coords[1:])
            else:
                print('Skipping to merge {} {}'.format(last, current))
                return None
        last = line.coords[-1]
    return LineString(points)

希望它能帮助某人


0

shapely.ops.linemerge如果行是连续的(“提示”与组成行的“尾部”重合),则可以使用,但是如果它们是不连续的(如果提示和尾部之间存在间隙),它将返回另一个MultiLineString。如果您的构成线排列有序(一条线在下一条线的开头附近结束),但是有尖到尾的间隙,则可以提取坐标并将其用作新的简单线。这种方法也适用于由更复杂的子线(即具有两个以上点的子线)组成的多线。

import shapely

# Make a MultiLineString to use for the example
inlines = shapely.geometry.MultiLineString(
    [shapely.geometry.LineString([(0,0),(0,0.9)]), 
     shapely.geometry.LineString([(0,1),(1,1)])]
)

# Put the sub-line coordinates into a list of sublists
outcoords = [list(i.coords) for i in inlines]

# Flatten the list of sublists and use it to make a new line
outline = shapely.geometry.LineString([i for sublist in outcoords for i in sublist])
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.