2015-02-27 10 views

Antwort

33

Sie np.sign in Kombination mit np.diff und np.argwhere erhalten die Indizes der Punkte, an denen die Linien kreuzen können (in diesem Fall sind die Punkte [ 0, 149, 331, 448, 664, 743]):

import numpy as np 
import matplotlib.pyplot as plt 

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, '-') 

idx = np.argwhere(np.diff(np.sign(f - g)) != 0).reshape(-1) + 0 
plt.plot(x[idx], f[idx], 'ro') 
plt.show() 

plot of intersection points

Zuerst berechnet er f - g und die entsprechenden Zeichen mit np.sign. Durch Anwenden von np.diff werden alle Positionen angezeigt, an denen sich das Vorzeichen ändert (z. B. die Linien kreuzen sich). Using np.argwhere gibt uns die genauen Indizes.

+0

Ich denke, der obige Code gibt eine Linie interpolieren die Schnittpunkte. Infact Ich möchte 'x' Wert nicht die Zeile –

+2

'x [idx]' wird Ihnen die entsprechenden Werte geben. – Matt

+0

aber x [idx] gibt mir 10 Werte im obigen Code? –

0

Es können mehrere Kreuzungen sein, können Sie den (x,y) Punkt an jeder Kreuzung durch die folgende Liste Verständnis

intersections = [(x[i], f[i]) for i,_ in enumerate(zip(f,g)) if f[i] == g[i]] 

Als einfaches Beispiel

>>> 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)] 

So fanden diese einen Schnittpunkt bei x = 3, y = 6 finden . Beachten Sie, dass die beiden Werte möglicherweise nicht exakt gleich sind, wenn Sie float verwenden. Sie können also eine Toleranz anstelle von == verwenden.

+0

der Schnittpunkt ist nicht im Array vorhanden. Ich zeichne beide Kurven dann würde ich gerne eine Linie parallel zur y-Achse durch den Schnittpunkt ziehen und finden Sie den x-Wert –

1

Auch wenn f und g sich schneiden, können Sie nicht sicher sein, dass f [i] == g [i] für ganze Zahl i (der Schnittpunkt tritt wahrscheinlich zwischen Punkten auf).

Sie stattdessen wie

# 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] 
+0

Schreiben Sie dies in numpy-Sprache und Sie am Ende mit meiner Antwort;) – plonser

1

Für Arrays f und g testen sollten, könnten wir einfach Folgendes tun:

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

Dies wird das Array aller Kreuzungspunkte geben. Jede 1 ist ein Übergang von unten nach oben und jeder -1 ein Übergang von oben nach unten.

1

Nun, ich suchte nach einer Matplotlib für zwei Kurven, die in der Größe unterschiedlich waren und nicht die gleichen x-Werte hatten. Hier ist, was ich habe:

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() 
+0

Gefallen Ihren Ansatz. Daumen hoch –

0

Kreuzung wahrscheinlich zwischen den Punkten. Lassen Sie uns das Beispiel unten erkunden.

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]) 

Auftragen der Kurven 2 oben, zusammen mit ihren Kreuzungen, als Schnittpunkt mit den durchschnittlichen Koordinaten vor und nach der Kreuzung von idx vorgeschlagen, alle Punkte sind näher an der ersten Kurve.

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() 

enter image description here

als Schnittpunkt mit den durchschnittlichen Koordinaten vor und nach der aber für beide y1 und y2-Kurven sind in der Regel näher an wahre Kreuzung

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() 

enter image description here

Für eine noch genauere Schnittschätzung konnten wir interp verwenden olation.

Verwandte Themen