Get the vertices on a LineString either side of a Point

拟墨画扇 提交于 2019-12-19 10:26:13

问题


I have a shapely LineString and have defined a shapely Point which lies along the LineString.

How can I find the vertices of the LineString which lie either side of the point? (split the line in two)


回答1:


Locate the line segment in the LineString where the point lies. Then split in two groups the vertices of the LineString accordingly. To locate the line segment, simply apply a point / line segment intersection test to each segment.

from shapely.geometry import Point,LineString

def split(line_string, point):
    coords = line_string.coords
    j = None

    for i in range(len(coords) - 1):
        if LineString(coords[i:i + 2]).intersects(point):
           j = i
           break

    assert j is not None

    # Make sure to always include the point in the first group
    if Point(coords[j + 1:j + 2]).equals(point):
        return coords[:j + 2], coords[j + 1:]
    else:
        return coords[:j + 1], coords[j:]



回答2:


Newer versions of Shapely (>=1.6.0 (2017-08-21)) provide split function that can split a line by a point:

from shapely.geometry import LineString, Point
from shapely.ops import split

line = LineString([(0, 0), (1, 1), (2, 1)])
point = Point(1.5, 1)
print(split(line, point))
# GEOMETRYCOLLECTION (LINESTRING (0 0, 1 1, 1.5 1), LINESTRING (1.5 1, 2 1))

One must take care, though, that due to precision errors this sometimes doesn't work properly:

line = LineString([(0, 0), (3, 2)])
point = Point(1, 2 / 3)
print(split(line, point))
# GEOMETRYCOLLECTION (LINESTRING (0 0, 3 2))
print(point.distance(line))
# 0.0

One way to deal with this is to construct a new LineString that will contain the splitting point.

new_line = LineString([line.coords[0], point.coords[0], line.coords[1]])
print(split(new_line, point))
# GEOMETRYCOLLECTION (LINESTRING (0 0, 1 0.6666666666666666), LINESTRING (1 0.6666666666666666, 3 2))

or if you don't want to do it manually:

from itertools import chain

all_points_coords = chain(line.coords, point.coords)
all_points = map(Point, all_points_coords)
new_line = LineString(sorted(all_points, key=line.project))
print(split(new_line, point))
# GEOMETRYCOLLECTION (LINESTRING (0 0, 1 0.6666666666666666), LINESTRING (1 0.6666666666666666, 3 2))


来源:https://stackoverflow.com/questions/21407233/get-the-vertices-on-a-linestring-either-side-of-a-point

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!