2013-10-18 5 views
5

Ich möchte eine Linie zeichnen, deren Breite in der Dateneinheit angegeben ist. In diesem Fall macht einfachmatplotlib - Wie zeichnet man ein zufällig ausgerichtetes Rechteck (oder irgendeine Form)?

plot(x, y, linewidth=1) 

würde scheitern, da die linewidth gibt es nicht in Dateneinheit angegeben.

Um dies zu tun, ich fill_between() finden, aber ich finde alle hier im Format angegebenen Beispiele sind

fill_between(x, y1, y2) 

was bedeutet, wird die x immer geteilt durch y1 und y2.

also was ist, wenn y1 und y2 nicht die gleichen teilen x?

z.B. Ich möchte zwischen line1=[(0, 0), (2, 2)] und line2=[(-1, 1), (1, 3)] füllen (im Wesentlichen bilden sie ein Rechteck). In diesem Fall möchte ich so etwas wie

fill_between(x1, x2, y1, y2) 

Offenbar ist es nicht wie gewünscht funktioniert:

In [132]: x1 = [0,2] 
    .....: x2 = [-1, 1] 
    .....: y1 = [0,2] 
    .....: y2 = [1,3] 
    .....: fill_between(x1, x2, y1, y2) 
    .....: 
Out[132]: <matplotlib.collections.PolyCollection at 0x3e5b230> 

enter image description here

Wie soll ich in diesem Fall zeichnen?

Antwort

4

Gute Frage! Ich würde vorschlagen, dass Sie sich nicht in der fill_between Funktion beschränken. Ich sehe es immer als vorteilhaft für tief in das Innere schauen die Dinge. Lassen Sie uns in die Essenz der Python-Zeichnung eintauchen.

The object underlying all of the matplotlib.patch objects is the Path.

Deshalb, wenn Sie die Path beherrschen, können Sie grundsätzlich zeichnen, was Sie in welcher Weise auch immer mögen. Lassen Sie uns jetzt sehen, wie wir Ihr Ziel mit der magischen Path erreichen.

Um das Rechteck zu erhalten, das Sie in der Frage erwähnt haben, ist nur ein bisschen Anpassung im Beispiel erforderlich.

import matplotlib.pyplot as plt 
from matplotlib.path import Path 
import matplotlib.patches as patches 

verts = [(0., 0.), # left, bottom 
     (-1., 1.), # left, top 
     (1., 3.), # right, top 
     (2., 2.), # right, bottom 
     (0., 0.),] # ignored 

codes = [Path.MOVETO, 
     Path.LINETO, 
     Path.LINETO, 
     Path.LINETO, 
     Path.CLOSEPOLY,] 

path = Path(verts, codes) 
fig = plt.figure() 
ax = fig.add_subplot(111) 
patch = patches.PathPatch(path, facecolor='orange', lw=2) 
ax.add_patch(patch) 
ax.axis('equal') 
plt.show() 

Ich denke, der Code so einfach und selbsterklärend, dass ich brauche nicht meine Worte darauf zu verschwenden. Einfach kopieren und einfügen und ausführen, Sie erhalten genau das, was Sie wollen.

enter image description here

+0

Dank! Ich denke, das ist eine allgemeinere Lösung. –

2

Anstatt die Linien zu zeichnen, können Sie den gefüllten Bereich als polygon zeichnen. Um dies zu tun, müssen Sie x1 mit der Rückseite von x2 verketten und dasselbe für y1 und y2 tun. Etwas wie dieses:

In [1]: from pylab import * 
In [2]: x1 = arange(0,11,2) 
In [3]: x2 = arange(0,11) 
In [4]: y1 = x1**2+1 
In [5]: y2 = x2**2-1 
In [6]: xy = c_[r_[x1,x2[::-1]], r_[y1,y2[::-1]]] 
In [7]: ax = subplot(111) # we need an axis first 
In [8]: ax.add_patch(Polygon(xy)) 
Out[8]: <matplotlib.patches.Polygon at 0x3bff990> 
In [9]: axis([0,10,-10,110]) # axis does not automatically zoom to a patch 
Out[9]: [0, 10, -10, 110] 
In [10]: show() 
5

Noch einfacher, matplotlib.patches.Rectangle

rect = matplotlib.patches.Rectangle((.25, .25), .25, .5, angle=45) 
plt.gca().add_patch(rect) 
plt.draw() 
+0

Danke für die Antwort!Aber das erfordert, dass ich den Winkel für nicht so schön orientierte Rechtecke berechne, oder? –

+1

Sie wissen, wo die Ecken sind, den Winkel zu bekommen ist nur eine Frage von 'np.atan2'. – tacaswell

+0

Ja, danke für die Hilfe! :) –

Verwandte Themen