我有一个匀称的LineString
并定义了一个Point
的{{1}}。
如何找到位于该点两侧的LineString
的顶点? (将线分成两部分)
答案 0 :(得分:2)
找到该点所在的LineString
中的线段。然后相应地分成两组LineString
的顶点。要定位线段,只需将点/线段相交测试应用于每个线段。
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:]
答案 1 :(得分:0)
Shapely(>=1.6.0 (2017-08-21))的较新版本提供了split
功能,该功能可以按点分割线:
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))
但是,必须小心一点,由于精度错误,这有时无法正常工作:
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
一种解决方法是构造一个新的LineString
,其中将包含分割点。
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))
或者如果您不想手动进行操作:
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))