使用 python 从其他两条曲线创建第三条曲线

Create a third curve from other two using python

我有两个 xy 坐标列表,我用它们来绘制两条曲线。我对曲线上方的区域很感兴趣,所以我用 fill_between 得出了这个:

现在,我想要的是一种获取未被彩色区域覆盖的坐标的方法,这样我就可以绘制第三条曲线,就像我在下面的示例中使用 Paint 绘制的红色曲线一样:

我尝试对列表进行排序,然后比较每一对以找到具有较低 y 值的列表,但这不起作用,因为每个列表可以具有不同的大小和不同的 x 值。我还发现了一些关于叉积的话题,但那些使用的是直线,我无法理解如何将其外推到我的案例中。

这是一个mwe:

import matplotlib.pyplot as plt

points_x = [1,3,5,7,9,11,13,15,17,19]
points_y = [10,8,7,6,3,5,3,9,7,6]
points_x2= [0,2,4,8,10,12,14,15,17,19,20,21,22]
points_y2 = [12,10,9,4,2,7,3,8,8,8,8,8,8]

plt.scatter(points_x, points_y, color="blue")
plt.scatter(points_x2, points_y2, color="green")

plt.fill_between(points_x, points_y, plt.ylim()[1], color='blue', alpha=0.5)
plt.fill_between(points_x2, points_y2, plt.ylim()[1], color='green', alpha=0.5)

#way to make a points_x3/points_y3 with only the coordinates at the edge of the 
#overlapped areas

plt.show()

(我在想出正确的术语来定义我的问题时遇到了困难(非母语人士并且不习惯太多的数学术语),所以对于可能提出重复的问题我深表歉意)

如果我没理解错的话,你想要的是凸包,你可以用scipy:

来计算
from scipy.spatial import ConvexHull

points_x = [1,3,5,7,9,11,13,15,17,19]
points_y = [10,8,7,6,3,5,3,9,7,6]
points_x2= [0,2,4,8,10,12,14,15,17,19,20,21,22]
points_y2 = [12,10,9,4,2,7,3,8,8,8,8,8,8]

# making array of x/y coordinates
a = np.array([points_x+points_x2, points_y+points_y2]).T

min_x = a[:,0].min()
max_x = a[:,0].max()
max_y = a[:,1].max()+1 # arbitrary +1 for ylim

# concatenate extra points to array
a = np.r_[a,np.array([[min_x, max_y], [max_x, max_y]])]

# compute the convex hull
hull = ConvexHull(a)

plt.scatter(points_x, points_y, color="blue")
plt.scatter(points_x2, points_y2, color="green")

plt.fill_between(points_x, points_y, plt.ylim()[1], color='blue', alpha=0.5)
plt.fill_between(points_x2, points_y2, plt.ylim()[1], color='green', alpha=0.5)

idx = np.r_[hull.vertices,hull.vertices[0]]

plt.plot(a[idx,0], a[idx,1], 'r', lw=2)

输出:

您可以将两条曲线组织到一个共同的 x 轴上,然后计算它们的最小值:

import matplotlib.pyplot as plt
import numpy as np

points_x = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
points_y = [10, 8, 7, 6, 3, 5, 3, 9, 7, 6]
points_x2 = [0, 2, 4, 8, 10, 12, 14, 15, 17, 19, 20, 21, 22]
points_y2 = [12, 10, 9, 4, 2, 7, 3, 8, 8, 8, 8, 8, 8]

plt.scatter(points_x, points_y, color="blue")
plt.scatter(points_x2, points_y2, color="green")

plt.fill_between(points_x, points_y, plt.ylim()[1], color='blue', alpha=0.5)
plt.fill_between(points_x2, points_y2, plt.ylim()[1], color='green', alpha=0.5)

# way to make a points_x3/points_y3 with only the coordinates at the edge of the
# overlapped areas

x_long = np.unique(np.append(points_x, points_x2))
y_long = np.interp(x_long, points_x, points_y, left=np.nan, right=np.nan)
y2_long = np.interp(x_long, points_x2, points_y2, left=np.nan, right=np.nan)
y_min = np.nanmin([y_long, y2_long], axis=0)

plt.plot(x_long, y_min, color='red', ls='--', alpha=0.5, lw=4)
plt.show()