在Python中,求两个图的交集的x值

在Python中,求两个图的交集的x值,python,matplotlib,intersection,Python,Matplotlib,Intersection,设0您可以使用np.sign与np.diff和np.argwhere结合使用,以获得线交叉点的索引(在这种情况下,点是[0、149、331、448、664、743]): 首先,它计算f-g和使用np.sign的相应符号。应用np.diff显示符号变化的所有位置(例如,线交叉)。使用np.arg,其中给出了准确的索引。可能有多个交点,您可以通过以下列表在每个交点处找到(x,y)点 intersections = [(x[i], f[i]) for i,_ in enumerate(zip(f,g

设0您可以使用
np.sign
np.diff
np.argwhere
结合使用,以获得线交叉点的索引(在这种情况下,点是
[0、149、331、448、664、743]
):


首先,它计算
f-g
和使用
np.sign
的相应符号。应用
np.diff
显示符号变化的所有位置(例如,线交叉)。使用
np.arg,其中
给出了准确的索引。

可能有多个交点,您可以通过以下列表在每个交点处找到
(x,y)

intersections = [(x[i], f[i]) for i,_ in enumerate(zip(f,g)) if f[i] == g[i]]
举个简单的例子

>>> x = [1,2,3,4,5]
>>> f = [2,4,6,8,10]
>>> g = [10,8,6,4,2]
>>> [(x[i], f[i]) for i,_ in enumerate(zip(f,g)) if f[i] == g[i]]
[(3, 6)]

因此,这在
x=3,y=6处找到了一个交点。请注意,如果使用的是
float
这两个值可能并不完全相等,因此即使f和g相交,也可以使用一些公差来代替
=

,不能确保f[i]==g[i]表示整数i(交点可能发生在点之间)

你应该像这样测试

# detect intersection by change in sign of difference
d = f - g
for i in range(len(d) - 1):
    if d[i] == 0. or d[i] * d[i + 1] < 0.:
        # crossover at i
        x_ = x[i]
#通过差异符号的变化检测交叉口
d=f-g
对于范围内的i(透镜(d)-1):
如果d[i]==0。或d[i]*d[i+1]<0:
#在i交叉
x_uux=x[i]

对于阵列f和g,我们可以简单地执行以下操作:

np.pad(np.diff(np.array(f > g).astype(int)), (1,0), 'constant', constant_values = (0,))

这将给出所有交叉点的数组。每个1是从下方到上方的交叉,每个-1是从上方到下方的交叉。

好吧,我正在为两条大小不同且x值不相同的曲线寻找matplotlib。以下是我的想法:

import numpy as np
import matplotlib.pyplot as plt
import sys

fig = plt.figure()
ax = fig.add_subplot(111)

# x1 = [1,2,3,4,5,6,7,8]
# y1 = [20,100,50,120,55,240,50,25]
# x2 = [3,4,5,6,7,8,9]
# y2 = [25,200,14,67,88,44,120]

x1=[1.4,2.1,3,5.9,8,9,12,15]
y1=[2.3,3.1,1,3.9,8,9,11,9]
x2=[1,2,3,4,6,8,9,12,14]
y2=[4,12,7,1,6.3,7,5,6,11]

ax.plot(x1, y1, color='lightblue',linewidth=3, marker='s')
ax.plot(x2, y2, color='darkgreen', marker='^')

y_lists = y1[:]
y_lists.extend(y2)
y_dist = max(y_lists)/200.0

x_lists = x1[:]
x_lists.extend(x2)  
x_dist = max(x_lists)/900.0
division = 1000
x_begin = min(x1[0], x2[0])     # 3
x_end = max(x1[-1], x2[-1])     # 8

points1 = [t for t in zip(x1, y1) if x_begin<=t[0]<=x_end]  # [(3, 50), (4, 120), (5, 55), (6, 240), (7, 50), (8, 25)]
points2 = [t for t in zip(x2, y2) if x_begin<=t[0]<=x_end]  # [(3, 25), (4, 35), (5, 14), (6, 67), (7, 88), (8, 44)]
# print points1
# print points2

x_axis = np.linspace(x_begin, x_end, division)
idx = 0
id_px1 = 0
id_px2 = 0
x1_line = []
y1_line = []
x2_line = []
y2_line = []
xpoints = len(x_axis)
intersection = []
while idx < xpoints:
    # Iterate over two line segments
    x = x_axis[idx]
    if id_px1>-1:
        if x >= points1[id_px1][0] and id_px1<len(points1)-1:
            y1_line = np.linspace(points1[id_px1][1], points1[id_px1+1][1], 1000) # 1.4 1.401 1.402 etc. bis 2.1
            x1_line = np.linspace(points1[id_px1][0], points1[id_px1+1][0], 1000)
            id_px1 = id_px1 + 1
            if id_px1 == len(points1):
                x1_line = []
                y1_line = []
                id_px1 = -1
    if id_px2>-1:
        if x >= points2[id_px2][0] and id_px2<len(points2)-1:
            y2_line = np.linspace(points2[id_px2][1], points2[id_px2+1][1], 1000)
            x2_line = np.linspace(points2[id_px2][0], points2[id_px2+1][0], 1000)
            id_px2 = id_px2 + 1
            if id_px2 == len(points2):
                x2_line = []
                y2_line = []
                id_px2 = -1
    if x1_line!=[] and y1_line!=[] and x2_line!=[] and y2_line!=[]:
        i = 0
        while abs(x-x1_line[i])>x_dist and i < len(x1_line)-1:
            i = i + 1
        y1_current = y1_line[i]
        j = 0
        while abs(x-x2_line[j])>x_dist and j < len(x2_line)-1:
            j = j + 1
        y2_current = y2_line[j]
        if abs(y2_current-y1_current)<y_dist and i != len(x1_line) and j != len(x2_line):
            ymax = max(y1_current, y2_current)
            ymin = min(y1_current, y2_current)
            xmax = max(x1_line[i], x2_line[j])
            xmin = min(x1_line[i], x2_line[j])
            intersection.append((x, ymin+(ymax-ymin)/2))
            ax.plot(x, y1_current, 'ro') # Plot the cross point
    idx += 1    
print "intersection points", intersection
plt.show()
将numpy导入为np
将matplotlib.pyplot作为plt导入
导入系统
图=plt.图()
ax=图添加_子批次(111)
#x1=[1,2,3,4,5,6,7,8]
#y1=[20100,50120,55240,50,25]
#x2=[3,4,5,6,7,8,9]
#y2=[25200,14,67,88,44120]
x1=[1.4,2.1,3,5.9,8,9,12,15]
y1=[2.3,3.1,1,3.9,8,9,11,9]
x2=[1,2,3,4,6,8,9,12,14]
y2=[4,12,7,1,6.3,7,5,6,11]
ax.绘图(x1,y1,颜色为淡蓝色,线宽为3,标记为s)
ax.plot(x2,y2,color='darkgreen',marker='^')
y_列表=y1[:]
y_列表。扩展(y2)
y_dist=最大值(y_列表)/200.0
x_列表=x1[:]
x_列表扩展(x2)
x_dist=最大值(x_列表)/900.0
除法=1000
x_begin=min(x1[0],x2[0])#3
x_end=max(x1[-1],x2[-1])#8
点s1=[t表示zip(x1,y1)中的t,如果x_开始x_dist且j如果abs(y2_电流-y1_电流)交点可能发生在点之间。让我们探索下面的示例

import numpy as np
import matplotlib.pyplot as plt
xs=np.arange(0, 20)
y1=np.arange(0, 20)*2
y2=np.array([1, 1.5, 3,  8,  9,  20, 23, 21, 13, 23, 18, 20, 23, 24, 31, 28, 30, 33, 37, 36])
绘制上述两条曲线及其交点,使用从
idx
交点提出的前后平均坐标作为交点,所有点都更靠近第一条曲线

idx=np.argwhere(np.diff(np.sign(y1 - y2 )) != 0).reshape(-1) + 0
plt.plot(xs, y1)
plt.plot(xs, y2)
for i in range(len(idx)):
    plt.plot((xs[idx[i]]+xs[idx[i]+1])/2.,(y1[idx[i]]+y1[idx[i]+1])/2., 'ro')
plt.legend(['Y1', 'Y2'])
plt.show()   

作为交点,y1和y2曲线前后的平均坐标通常更接近真实交点

plt.plot(xs, y1)
plt.plot(xs, y2)
for i in range(len(idx)):
    plt.plot((xs[idx[i]]+xs[idx[i]+1])/2.,(y1[idx[i]]+y1[idx[i]+1]+y2[idx[i]]+y2[idx[i]+1])/4., 'ro')
plt.legend(['Y1', 'Y2'])
plt.show()   


为了获得更精确的交点估计,我们可以使用插值。

以下是一个解决方案:

  • 处理N维数据
  • 使用欧几里德距离,而不仅仅是在y轴上查找交叉点
  • 对于大量数据更有效(它查询a,它应该以对数时间而不是线性时间进行查询)
  • 您可以在KD树查询中更改距离上限,以定义距离是否足够近
  • 如果需要,您可以同时查询具有多个点的KD树。注意:如果您需要同时查询数千个点,您可以通过查询KD树获得显著的性能提升


对于正在使用或打开库进行几何相关计算的用户,获取交点将更加容易。您只需从每条线进行构造,并获得如下结果:

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

x = np.arange(0, 1000)
f = np.arange(0, 1000)
g = np.sin(np.arange(0, 10, 0.01) * 2) * 1000

plt.plot(x, f)
plt.plot(x, g)

first_line = LineString(np.column_stack((x, f)))
second_line = LineString(np.column_stack((x, g)))
intersection = first_line.intersection(second_line)

if intersection.geom_type == 'MultiPoint':
    plt.plot(*LineString(intersection).xy, 'o')
elif intersection.geom_type == 'Point':
    plt.plot(*intersection.xy, 'o')

要获得作为NumPy数组的
x
y
值,您只需编写:

x, y = LineString(intersection).xy
# x: array('d', [0.0, 149.5724669847373, 331.02906176584617, 448.01182730277833, 664.6733061190541, 743.4822641140581])
# y: array('d', [0.0, 149.5724669847373, 331.02906176584617, 448.01182730277833, 664.6733061190541, 743.4822641140581])
或者,如果交点仅为一个点:

x, y = intersection.xy

我有一个类似的问题,但是有一个中断函数,比如切线函数。为了避免不连续点上的点,女巫我不想考虑一个交叉点,我在以前的解决方案中使用NP.DIFF和NP-符号增加了一个容差参数。我将容限参数设置为两个数据P之间的差异的平均值。点,巫婆就够了

import numpy as np
import matplotlib.pyplot as plt

fig,ax = plt.subplots(nrows = 1,ncols = 2)

x = np.arange(0, 1000)
f = 2*np.arange(0, 1000)
g = np.tan(np.arange(0, 10, 0.01) * 2) * 1000


#here we set a threshold to decide if we will consider that point as a intersection
tolerance = np.abs(np.diff(f-g)).mean()
idx = np.argwhere((np.diff(np.sign(f - g)) != 0) & (np.abs(np.diff(f-g)) <= tolerance)).flatten()

#general case (tolerance = infinity)
tolerance = np.inf
idx2 = np.argwhere((np.diff(np.sign(f - g)) != 0) & (np.abs(np.diff(f-g)) <= tolerance)).flatten()

ax1,ax2 = ax

ax1.plot(x,f); ax1.plot(x,g)
ax2.plot(x,f); ax2.plot(x,g)

ax1.plot(x[idx], f[idx], 'o'); ax1.set_ylim(-3000,3000)
ax2.plot(x[idx2],f[idx2], 'o'); ax2.set_ylim(-3000,3000)
plt.show()
将numpy导入为np
将matplotlib.pyplot作为plt导入
图,ax=plt子批次(nrows=1,ncols=2)
x=np.arange(0,1000)
f=2*np.arange(0,1000)
g=np.tan(np.arange(0,10,0.01)*2)*1000
这里,我们设置一个阈值来决定是否将该点视为交叉点。
公差=np.abs(np.diff(f-g)).mean()

idx=np.argwhere((np.diff(np.sign(f-g))!=0)和(np.abs(np.diff(f-g))用numpy语言写这篇文章,你会得到我的答案;)我猜上面的代码给出了一条插值交点的线。实际上我想要的是“x”值,而不是线
x[idx]
会给出相应的值。但是x[idx]在上面的代码中是否给了我10个值?这可能是因为有10个相交点@Shivaprakash该相交点不在数组中。我绘制了两条曲线,然后我想画一条平行于通过相交点的y轴的线,并找到x值参见通过线性输入找到精确的相交点三极化。如果你想要一个相当准确的结果,最好的解决方案。
import numpy as np
import matplotlib.pyplot as plt
from shapely.geometry import LineString

x = np.arange(0, 1000)
f = np.arange(0, 1000)
g = np.sin(np.arange(0, 10, 0.01) * 2) * 1000

plt.plot(x, f)
plt.plot(x, g)

first_line = LineString(np.column_stack((x, f)))
second_line = LineString(np.column_stack((x, g)))
intersection = first_line.intersection(second_line)

if intersection.geom_type == 'MultiPoint':
    plt.plot(*LineString(intersection).xy, 'o')
elif intersection.geom_type == 'Point':
    plt.plot(*intersection.xy, 'o')
x, y = LineString(intersection).xy
# x: array('d', [0.0, 149.5724669847373, 331.02906176584617, 448.01182730277833, 664.6733061190541, 743.4822641140581])
# y: array('d', [0.0, 149.5724669847373, 331.02906176584617, 448.01182730277833, 664.6733061190541, 743.4822641140581])
x, y = intersection.xy
import numpy as np
import matplotlib.pyplot as plt

fig,ax = plt.subplots(nrows = 1,ncols = 2)

x = np.arange(0, 1000)
f = 2*np.arange(0, 1000)
g = np.tan(np.arange(0, 10, 0.01) * 2) * 1000


#here we set a threshold to decide if we will consider that point as a intersection
tolerance = np.abs(np.diff(f-g)).mean()
idx = np.argwhere((np.diff(np.sign(f - g)) != 0) & (np.abs(np.diff(f-g)) <= tolerance)).flatten()

#general case (tolerance = infinity)
tolerance = np.inf
idx2 = np.argwhere((np.diff(np.sign(f - g)) != 0) & (np.abs(np.diff(f-g)) <= tolerance)).flatten()

ax1,ax2 = ax

ax1.plot(x,f); ax1.plot(x,g)
ax2.plot(x,f); ax2.plot(x,g)

ax1.plot(x[idx], f[idx], 'o'); ax1.set_ylim(-3000,3000)
ax2.plot(x[idx2],f[idx2], 'o'); ax2.set_ylim(-3000,3000)
plt.show()