在Python中测量LineString上两点之间的距离

问题描述 投票:0回答:1

我有以下问题:我有一条路线(作为 LineString,从 A 到 B)。该路线经过点C1附近。我想知道从 A 点到 C1 点的路径有多长(见图)。在 JS-Package 中,有一个函数 nearest-point-on-line 正是这样做的(它也计算直线上的长度)。但是Python中有类似的东西吗?

这是我尝试过的两次尝试。

1.将点捕捉到线,将线与新点相交

在 = C2 线上找到 C1 的下一个点。然后通过将 LineString 与点 C2 相交来生成新的 LineString。这条新线的长度是线上 A 和 C2 之间的长度。

from shapely.ops import nearest_points, split

# Snap to line
c2 = nearest_points(line, c1)[0]

# Split line at point
splitted_line = split(line, c2)

问题:

该线永远不会被切断,因为 c2 不在线上,即使它已被折断。它们相差几位小数。

2.在 C1 和 C2 之间创建线,延伸它,与 LineString 相交

在此变体中,我尝试将 LineString 与第二条线相交。与之前一样,搜索到 C1 的直线上的下一个点 (=C2)。现在我从 C1 和 C2 生成一个 LineString。我将这个 LineString 在 C2 方向上增加一个固定值。然后路线与新的 LineString 相交。

import cmath
import geopandas as gpd
from shapely.ops import nearest_points, split, LineString

# This function expands the line in given direction.
def expandLineInDirection(x1, y1, x2, y2, dist):
    # calculate the x,y change between the points
    difference = complex(x2,y2) - complex(x1,y1) 

    # convert the difference to polar coordinates
    (distance, angle) = cmath.polar(difference) 

    #calculate a new x,y change based on the angle and desired distance
    displacement = cmath.rect(dist, angle) 

    # add the displacement to the start and end point
    xy3 = displacement + complex(x2,y2)  

    x3 = xy3.real
    y3 = xy3.imag
    return (x3, y3)

# This function will split the line with a line that is build with two points and extended
def getLineLengthFromPointOnLine(line, p1, p2):
    # p1 = unsnapped
    # p2 = snapped
    # p3 = will be calculated. Expand the line so that it cross the original line on all cases

    cuttingLine = LineString([p1, expandLineInDirection(p1.x, p1.y, p2.x, p2.y, 2)])

    result = split(line, cuttingLine)
    
    if len(result.geoms) < 2:
        #print("Split hat nicht funktioniert, nicht zwei Linien")
        return -1

    return result.geoms[0].length

point_length = getLineLengthFromPointOnLine(line, c1, c2)

问题

这在大多数情况下都有效——但并非总是如此。 在极少数情况下,新线可能不与 LineString 相交(见图)

有没有更简单的方法来解决这个问题?

python gis shapely
1个回答
0
投票

尝试沿着各个线段寻找最近的点,并使用匹配点来指示分割位置。

import shapely as shp
import itertools as it

line_coords = [[0, 0], [0, -2], [5, -2], [7, -4]]
line = shp.LineString(line_coords)
pt = shp.Point(4, -1)

closest_pt = shp.ops.nearest_points(line, pt)[0]

segments = [shp.LineString([a,b]) for a,b in it.pairwise(line_coords)]
closest_segment_pts = [shp.ops.nearest_points(seg, pt)[0] for seg in segments]
match = closest_segment_pts.index(closest_pt[0])

split_line = shp.LineString(line_coords[0:match+2])
© www.soinside.com 2019 - 2024. All rights reserved.