【问题标题】:Break a shapely Linestring at multiple points在多个点打破匀称的线串
【发布时间】:2016-09-10 10:24:44
【问题描述】:

下面的这段代码是根据我找到的here 修改的,它在沿线定义的点处将一个匀称的线串分成两段。我还检查了其他问题,但它们没有直接解决我的问题。但是,我想扩展它以将线分成多个段(在多个点),到目前为止,我所做的所有尝试都失败了。如何修改它以将字符串拆分为任何给定数量的段或在多个点上说((4,5),(9,18)和(6,5))。

input: 

line = LineString([(1,2),(8,7),(4,5),(2,4),(4,7),(8,5),(9,18),(1,2),(12,7),(4,5),(6,5),(4,9)])
       breakPoint = Point(2,4)

from shapely.geometry import Point,LineString

def make_line_segment(line_string, breakPoint):
    geoLoc = line_string.coords
    j = None
    for i in range(len(geoLoc) - 1):
        if LineString(geoLoc[i:i + 2]).intersects(breakPoint):
           j = i
           break
    assert j is not None
    # Make sure to always include the point in the first group
    if Point(geoLoc[j + 1:j + 2]).equals(breakPoint):
        return geoLoc[:j + 2], geoLoc[j + 1:]
    else:
        return geoLoc[:j + 1], geoLoc[j:]

line1,line2 = make_line_segment(line,breakPoint)
line1 = LineString(line1)
line2 = LineString(line2)
print line1, line2

output: `LINESTRING (1 2, 8 7, 4 5, 2 4) LINESTRING (2 4, 4 7, 8 5, 9 18, 1 2, 12 7, 4 5, 6 5, 4 9)`

【问题讨论】:

  • 你没有为我们提供太多的东西。例如,断点总是在线吗?也不清楚你遇到了什么麻烦。为什么不在第二点拆分line2 等等?提供更多细节说明为什么这很困难。

标签: python shapely


【解决方案1】:

projectioninterpolate lineString 方法通常对这类操作很方便。

from shapely.geometry import Point, LineString

def cut(line, distance):
    # Cuts a line in two at a distance from its starting point
    # This is taken from shapely manual
    if distance <= 0.0 or distance >= line.length:
        return [LineString(line)]
    coords = list(line.coords)
    for i, p in enumerate(coords):
        pd = line.project(Point(p))
        if pd == distance:
            return [
                LineString(coords[:i+1]),
                LineString(coords[i:])]
        if pd > distance:
            cp = line.interpolate(distance)
            return [
                LineString(coords[:i] + [(cp.x, cp.y)]),
                LineString([(cp.x, cp.y)] + coords[i:])]

def split_line_with_points(line, points):
    """Splits a line string in several segments considering a list of points.

    The points used to cut the line are assumed to be in the line string 
    and given in the order of appearance they have in the line string.

    >>> line = LineString( [(1,2), (8,7), (4,5), (2,4), (4,7), (8,5), (9,18), 
    ...        (1,2),(12,7),(4,5),(6,5),(4,9)] )
    >>> points = [Point(2,4), Point(9,18), Point(6,5)]
    >>> [str(s) for s in split_line_with_points(line, points)]
    ['LINESTRING (1 2, 8 7, 4 5, 2 4)', 'LINESTRING (2 4, 4 7, 8 5, 9 18)', 'LINESTRING (9 18, 1 2, 12 7, 4 5, 6 5)', 'LINESTRING (6 5, 4 9)']

    """
    segments = []
    current_line = line
    for p in points:
        d = current_line.project(p)
        seg, current_line = cut(current_line, d)
        segments.append(seg)
    segments.append(current_line)
    return segments

if __name__ == "__main__":
    import doctest
    doctest.testmod()

【讨论】:

  • Cut 只返回一个元素(一个列表),但在 split_line_with_points 中调用它需要两个,所以它总是会失败。
  • 如果列表l 包含恰好两个元素,则以下内容不会失败:a, b = l。事实上,如果列表没有两个元素,这是一种引发异常的隐含方式。
  • 哦,我从没见过。当我尝试运行它时,它以某种方式失败了。但无论如何,谢谢你的提示。
【解决方案2】:

在这种方法中,首先我将开头的点列表拆分并形成如下的线列表,

# List of coordinates
coords = [(1,2),(8,7),(4,5),(2,4),(4,7),(8,5),(9,18),(1,2),(12,7),(4,5),(6,5),(4,9)]



no_seg = 3 #Number of segments, you need from 'coords'
coords_sub = np.array_split(coords, no_seg)

list_lines = [] # empty list

for i in range(len(X_sub)):
    list_lines.append(LineString(X_sub[i]))

list_lines[1] # Displays the second line of the list

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多