获取线穿过多边形的点的坐标

get coordinate of points where a line crosses a polygon

我想找到一条线与多边形相交的点。我使用 .

的凹轮廓计算得到这个多边形
import alphashape
from shapely.geometry import LineString
import matplotlib.pyplot as plt
from descartes import PolygonPatch

points = [(17, 158),(15, 135),(38, 183),(43, 19),(93, 88),(96, 140),(149, 163),(128, 248),(216, 265),(248, 210),(223, 167),(256, 151),(331, 214),(340, 187),(316, 53),(298, 35),(182, 0),(121, 42)]
points = np.array(points)

alpha = 0.99 * alphashape.optimizealpha(points)
hull = alphashape.alphashape(points, alpha)
hull_pts = hull.exterior.coords.xy
path = PolygonPatch(hull, fill=False, color='green')
print(path.contains_point([128,248]))

fig, ax = plt.subplots()
ax.scatter(hull_pts[0], hull_pts[1], color='red')
ax.scatter(points[:,0], points[:,1], color='red')

p = np.array([[350, 100],[0, 100]])
ax.plot(p[:, 0], p[:, 1], color='blue')
ax.add_patch(path)

到目前为止,我尝试定义一行:

l = LineString(p)
inters = l.intersection(hull)

但是inters.xy returns一个NotImplemented错误,所以我不确定如何获取线穿过多边形的点的坐标。

交集returns a MultilineString,这是LineStrings列表的花哨词。我们可以从每个线串中检索坐标,例如:

import alphashape
from shapely.geometry import LineString
import matplotlib.pyplot as plt
import numpy as np

#replicating your example
fig, ax = plt.subplots()

line_xy = [[350, 100],[0, 120]]
points = np.asarray([(17, 158),(15, 135),(38, 183),(43, 19),(93, 88),(96, 140),(149, 163),(128, 248),(216, 265),(248, 210),(223, 167),(256, 151),(331, 214),(340, 187),(316, 53),(298, 35),(182, 0),(121, 42)])

alpha = 0.99 * alphashape.optimizealpha(points)
hull = alphashape.alphashape(points, alpha)
hull_pts = hull.exterior.coords.xy

p = LineString(line_xy)

ax.plot(*hull_pts, c="green")
ax.scatter(points[:,0], points[:,1], marker="o", color="red")
ax.scatter(*hull_pts, marker="s", color="red")

ax.plot(*p.coords.xy, color='blue')

#retrieving intersection 
inters = hull.intersection(p)

#checking for object type to retrieve all intersection coordinates
if inters.type == "LineString":
    coords = np.asarray([inters.coords.xy])
elif inters.type == "MultiLineString":
    coords = np.asarray([l.coords.xy for l in inters.geoms])
    
#reshaping array point coordinates into a form that does not make my head hurt
coords = coords.transpose(1, 0, 2).reshape(2, -1)
print(coords)

plt.show()

coords[:, i] 返回交点 i 的 x-y 值。

示例输出:

[[324.67707894 234.24811338 176.4217078   18.88111888]
 [101.44702406 106.61439352 109.91875955 118.92107892]]

奇怪的是,shapely 将外壳内的线点(如 300, 100)视为交点。严格来说,必须检查 none 个已识别点是否位于外壳多边形内。

并且 alphashape(此处使用 1.3.1)应该更新它们的例程,因为 alphashape.alphashape(points, alpha) 生成错误消息 ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the geoms property to access the constituent parts of a multi-part geometry.

当一条边的端点(令ab)的纵坐标跨越该线的纵坐标(令Y)时,一条边穿过一条水平线。因此相交测试非常简单。要获取交点本身,请使用

Xi = Xa + (Y - Ya) (Xb - Xa) / (Yb - Ya)
Yi = Y

Y = Ya = Yb 取决于应用程序时该怎么办。


如果直线是垂直的,只需交换XY的角色即可。

如果线是倾斜的,您可以使用使线水平的旋转。这可以通过变换

方便地用复数表示
Z = z e^(-iΘ)

虽然你不需要复数来实现这个,并且获得旋转系数的方式取决于线的指定方式。

计算交集后,你counter-rotate它。