Python 中的区域交集
Area intersection in Python
我有一个代码将条件 C 作为输入,并将我的问题的解决方案计算为 (x,y) space 上的 'allowed area' A。这个区域由几个'tubes'组成,它们由2条永远不会交叉的线定义。
我要找的最终结果必须满足k个条件{C1, .., Ck},因此是k个区域{A1, .. , Ak}之间的交集S。
这是一个有2个条件的例子(A1:绿色,3管。A2:紫色,1管);溶液 S 为红色。
当我处理 4 个区域,每个区域大约有 10 个管子时,如何找到 S? (最后的剧情太烂了!)
我需要能够绘制它,并找到 S 中各点的平均坐标和方差(每个坐标的方差)。 [如果有一种有效的方法可以知道点 P 是否属于 S,我将使用 Monte Carlo 方法。
理想情况下,我还希望能够实现我将从 S 中移除的“禁管”[这可能比将 S 与我的禁区外部相交要复杂一些,因为两个管来自同一区域可以交叉(即使定义管道的线永远不会交叉)]。
注:
代码中还存储了直线的弧长
这些线存储为点数组(每条线约 1000 个点)。定义管子的两条线不一定具有相同数量的点,但 Python 可以在 1 秒内将所有这些线作为其弧长的函数进行插值。
线条是参数函数(即我们不能写 y = f(x),因为线条允许是垂直的)。
绘图用paint编辑得到右边的结果...效率不高!
编辑:
我不知道如何将 plt.fill_between 用于多重交集(我可以在这里为 2 种情况做,但我需要代码在有线条太多,肉眼无法判断)。
现在我只生成线条。我没有为找到最终解决方案而写任何东西,因为我绝对不知道哪种结构最适合这个。 [然而,以前版本的代码能够找到 2 个不同管子的线之间的交点,我打算将它们作为多边形传递给 shapely,但这意味着其他几个问题..]
我不认为我可以用 sets
做到这一点:以所需的精度扫描整个 (x,y) 区域表示大约 6e8 个点... [这些线只有1e3分得益于可变步长(适应曲率),但整个问题相当大]
Shapely 解决了问题!
我将每个管定义为一个 Polygon
,区域 A 是一个 MultiPolygon
作为其管的并集构建的对象。
intersection
方法然后计算我正在寻找的解决方案(所有区域之间的重叠)。
整个过程几乎是瞬间完成的。我不知道 shapely 对于大物体如此好 [每管大约 2000 个点,每个区域 10 个管,4 个区域]。
感谢您的帮助! :)
编辑:
一个工作示例。
import matplotlib.pyplot as plt
import shapely
from shapely.geometry import Polygon
from descartes import PolygonPatch
import numpy as np
def create_tube(a,height):
x_tube_up = np.linspace(-4,4,300)
y_tube_up = a*x_tube_up**2 + height
x_tube_down = np.flipud(x_tube_up) #flip for correct definition of polygon
y_tube_down = np.flipud(y_tube_up - 2)
points_x = list(x_tube_up) + list(x_tube_down)
points_y = list(y_tube_up) + list(y_tube_down)
return Polygon([(points_x[i], points_y[i]) for i in range(600)])
def plot_coords(ax, ob):
x, y = ob.xy
ax.plot(x, y, '+', color='grey')
area_1 = Polygon() #First area, a MultiPolygon object
for h in [-5, 0, 5]:
area_1 = area_1.union(create_tube(2, h))
area_2 = Polygon()
for h in [8, 13, 18]:
area_2 = area_2.union(create_tube(-1, h))
solution = area_1.intersection(area_2) #What I was looking for
########## PLOT ##########
fig = plt.figure()
ax = fig.add_subplot(111)
for tube in area_1:
plot_coords(ax, tube.exterior)
patch = PolygonPatch(tube, facecolor='g', edgecolor='g', alpha=0.25)
ax.add_patch(patch)
for tube in area_2:
plot_coords(ax, tube.exterior)
patch = PolygonPatch(tube, facecolor='m', edgecolor='m', alpha=0.25)
ax.add_patch(patch)
for sol in solution:
plot_coords(ax, sol.exterior)
patch = PolygonPatch(sol, facecolor='r', edgecolor='r')
ax.add_patch(patch)
plt.show()
情节:
我有一个代码将条件 C 作为输入,并将我的问题的解决方案计算为 (x,y) space 上的 'allowed area' A。这个区域由几个'tubes'组成,它们由2条永远不会交叉的线定义。
我要找的最终结果必须满足k个条件{C1, .., Ck},因此是k个区域{A1, .. , Ak}之间的交集S。
这是一个有2个条件的例子(A1:绿色,3管。A2:紫色,1管);溶液 S 为红色。
当我处理 4 个区域,每个区域大约有 10 个管子时,如何找到 S? (最后的剧情太烂了!)
我需要能够绘制它,并找到 S 中各点的平均坐标和方差(每个坐标的方差)。 [如果有一种有效的方法可以知道点 P 是否属于 S,我将使用 Monte Carlo 方法。
理想情况下,我还希望能够实现我将从 S 中移除的“禁管”[这可能比将 S 与我的禁区外部相交要复杂一些,因为两个管来自同一区域可以交叉(即使定义管道的线永远不会交叉)]。
注:
代码中还存储了直线的弧长
这些线存储为点数组(每条线约 1000 个点)。定义管子的两条线不一定具有相同数量的点,但 Python 可以在 1 秒内将所有这些线作为其弧长的函数进行插值。
线条是参数函数(即我们不能写 y = f(x),因为线条允许是垂直的)。
绘图用paint编辑得到右边的结果...效率不高!
编辑:
我不知道如何将 plt.fill_between 用于多重交集(我可以在这里为 2 种情况做,但我需要代码在有线条太多,肉眼无法判断)。
现在我只生成线条。我没有为找到最终解决方案而写任何东西,因为我绝对不知道哪种结构最适合这个。 [然而,以前版本的代码能够找到 2 个不同管子的线之间的交点,我打算将它们作为多边形传递给 shapely,但这意味着其他几个问题..]
我不认为我可以用
sets
做到这一点:以所需的精度扫描整个 (x,y) 区域表示大约 6e8 个点... [这些线只有1e3分得益于可变步长(适应曲率),但整个问题相当大]
Shapely 解决了问题!
我将每个管定义为一个 Polygon
,区域 A 是一个 MultiPolygon
作为其管的并集构建的对象。
intersection
方法然后计算我正在寻找的解决方案(所有区域之间的重叠)。
整个过程几乎是瞬间完成的。我不知道 shapely 对于大物体如此好 [每管大约 2000 个点,每个区域 10 个管,4 个区域]。
感谢您的帮助! :)
编辑:
一个工作示例。
import matplotlib.pyplot as plt
import shapely
from shapely.geometry import Polygon
from descartes import PolygonPatch
import numpy as np
def create_tube(a,height):
x_tube_up = np.linspace(-4,4,300)
y_tube_up = a*x_tube_up**2 + height
x_tube_down = np.flipud(x_tube_up) #flip for correct definition of polygon
y_tube_down = np.flipud(y_tube_up - 2)
points_x = list(x_tube_up) + list(x_tube_down)
points_y = list(y_tube_up) + list(y_tube_down)
return Polygon([(points_x[i], points_y[i]) for i in range(600)])
def plot_coords(ax, ob):
x, y = ob.xy
ax.plot(x, y, '+', color='grey')
area_1 = Polygon() #First area, a MultiPolygon object
for h in [-5, 0, 5]:
area_1 = area_1.union(create_tube(2, h))
area_2 = Polygon()
for h in [8, 13, 18]:
area_2 = area_2.union(create_tube(-1, h))
solution = area_1.intersection(area_2) #What I was looking for
########## PLOT ##########
fig = plt.figure()
ax = fig.add_subplot(111)
for tube in area_1:
plot_coords(ax, tube.exterior)
patch = PolygonPatch(tube, facecolor='g', edgecolor='g', alpha=0.25)
ax.add_patch(patch)
for tube in area_2:
plot_coords(ax, tube.exterior)
patch = PolygonPatch(tube, facecolor='m', edgecolor='m', alpha=0.25)
ax.add_patch(patch)
for sol in solution:
plot_coords(ax, sol.exterior)
patch = PolygonPatch(sol, facecolor='r', edgecolor='r')
ax.add_patch(patch)
plt.show()
情节: