在多个点处打破一个匀称的线串

时间:2016-09-10 10:24:45

标签: python shapely

下面的代码是从我发现的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)`

2 个答案:

答案 0 :(得分:2)

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()

答案 1 :(得分:0)

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

# 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