如何在Shapely中获取LineString的端点

13
Linestring1 = LINESTRING (51.2176008 4.4177154, 51.21758 4.4178548, **51.2175729 4.4179023**, *51.21745162000732 4.41871738126533*)
Linestring2 = LINESTRING (*51.21745162000732 4.41871738126533*, **51.2174025 4.4190475**, 51.217338 4.4194807, 51.2172511 4.4200562, 51.2172411 4.4201077, 51.2172246 4.4201654, 51.2172067 4.420205, 51.2171806 4.4202355, 51.2171074 4.4202929, 51.2170063 4.4203409, 51.2169564 4.4203641, 51.2168076 4.4204243, 51.2166588 4.4204833, 51.2159018 4.420431, 51.2154117 4.4203843)
考虑到这两个线串是从一个更大的线串中剪切出来的,如何获取一条线串的端点?
- 删除了点(51.21745162000732 4.41871738126533) - Linestring1的新最后一个元素为“51.2175729 4.4179023” - Linestring2的新第一个元素为“51.2174025 4.4190475”
简而言之,我想获取第一部分(linestring1)的新最后一个值和第二部分(linestring2)的新第一个值,但不包括我将它们切开的点。如何实现?
4个回答

29

要获取LineString的端点,只需访问其boundary属性:

from shapely.geometry import LineString

line = LineString([(0, 0), (1, 1), (2, 2)])
endpoints = line.boundary
print(endpoints)
# MULTIPOINT (0 0, 2 2)
first, last = line.boundary
print(first, last)
# POINT (0 0) POINT (2 2)

或者,您可以从coords坐标序列中获取第一个和最后一个点:

from shapely.geometry import Point
first = Point(line.coords[0])
last = Point(line.coords[-1])
print(first, last)
# POINT (0 0) POINT (2 2)
在您的特定情况下,您想要删除第一行的最后一个点和第二行的第一个点,然后才获取终点。因此,您应该首先使用相同的coords属性构造新的LineString对象:
from shapely.wkt import loads

first_line = loads("LINESTRING (51.2176008 4.4177154, 51.21758 4.4178548, 51.2175729 4.4179023, 51.21745162000732 4.41871738126533)")
second_line = loads("LINESTRING (51.21745162000732 4.41871738126533, 51.2174025 4.4190475, 51.217338 4.4194807, 51.2172511 4.4200562, 51.2172411 4.4201077, 51.2172246 4.4201654, 51.2172067 4.420205, 51.2171806 4.4202355, 51.2171074 4.4202929, 51.2170063 4.4203409, 51.2169564 4.4203641, 51.2168076 4.4204243, 51.2166588 4.4204833, 51.2159018 4.420431, 51.2154117 4.4203843)")
first_line = LineString(first_line.coords[:-1])
second_line = LineString(second_line.coords[1:])
print(first_line.boundary[1], second_line.boundary[0])
# POINT (51.2175729 4.4179023) POINT (51.2174025 4.4190475)

3
请注意,在LineString的起点和终点重合的特殊情况下,边界是EMPTY。访问line.coords的方法是唯一健壮的解决方案(通常情况下)。 - Friedrich Gretz
我非常喜欢使用.boundary作为解决方案,但是在shapely 2.0中语法已经改变。请参见:https://dev59.com/UlIH5IYBdhLWcg3wAHcv#74792758 - CreekGeek

1
注意:从shapely 2.0开始,语法会发生变化。
根据Georgy的回答,.boundary仍然可用(截至2022年12月),但已被弃用并会抛出警告。
对于多部分对象,向前推荐使用.geoms。
要从坐标序列中访问单个点,请使用numpy。
因此,可以使用以下方式代替:
first = Point(line.coords[0])
last = Point(line.coords[-1])

使用:
first = np.array(line.coords)[0]
last = np.array(line.coords)[-1]

1

Georgy的解决方案类似,您可以通过使用*_来解包所需的coords并忽略其余部分。

from shapely.geometry import LineString

linestring1 = LineString([(51.2176008, 4.4177154), (51.21758, 4.4178548),
                         (51.2175729, 4.4179023),
                         (51.21745162000732, 4.41871738126533)])
linestring2 = LineString([(51.21745162000732, 4.41871738126533),
                         (51.2174025, 4.4190475), (51.217338, 4.4194807),
                         (51.2172511, 4.4200562), (51.2172411, 4.4201077),
                         (51.2172246, 4.4201654), (51.2172067, 4.420205),
                         (51.2171806, 4.4202355), (51.2171074, 4.4202929),
                         (51.2170063, 4.4203409), (51.2169564, 4.4203641),
                         (51.2168076, 4.4204243), (51.2166588, 4.4204833),
                         (51.2159018, 4.420431), (51.2154117, 4.4203843)])

*_, last_new_1, last_1 = linestring1.coords
first_2, first_new_2, *_ = linestring2.coords

print(last_new_1)
print(first_new_2)
# (51.2175729, 4.4179023)
# (51.2174025, 4.4190475)

-4

使用两个程序解决了将LineString拆分的问题,具体如下:

  1. 函数:split_first 返回第一个点和不包含第一个点的点的LineString

  2. 函数:split_last 返回最后一个点和从第一个点开始但不包括最后一个点的点的LineString

代码

from shapely.ops import nearest_points
from shapely.geometry import Point
from shapely.geometry import LineString

def split_first(linestring):
  " returns first point and linestring without first point "
  coords = list(linestring.coords)

  p, *x = coords
  return Point(p), LineString(x)

def split_last(linestring):
  " returns first point and linestring without first point "

  *x, p = list(linestring.coords) = list(linestring.coords)

  return Point(p), LineString(x)

测试

数据

linestring = LineString([(51.2176008,4.4177154), (51.21758,4.4178548), (51.2175729,4.4179023), (51.21745162000732,4.41871738126533)])

第一点,线串不包括第一个点

p, l = split_first(linestring)
print(p)
print(l)

输出

POINT (51.2176008 4.4177154)
LINESTRING (51.21758 4.4178548, 51.2175729 4.4179023, 51.21745162000732 4.41871738126533)

首尾点和线串不包括最后一个

p, l = split_last(linestring)
print(p)
print(l)

输出

POINT (51.21745162000732 4.41871738126533)
LINESTRING (51.2176008 4.4177154, 51.21758 4.4178548, 51.2175729 4.4179023)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接