2017-02-27 3 views
0

Angenommen, ich habe einiges Hintergrundbild wie folgt gezeichnet:Cut Teile aufgetragen Künstler

fig, ax = plt.subplots() 
imdata = np.random.randn(10, 10) 
im = ax.imshow(imdata, extent=(0, 1, 0, 1), aspect='auto', 
       cmap='coolwarm', interpolation='nearest') 

nun eine Reihe von Rechtecken wie ich hinzufüge:

rect = matplotlib.patches.Rectangle((0.3,0.3),0.4,0.4) 
ax.add_artist(rect) 

Jetzt will ich einige andere schneiden Rechtecke aus dem zuvor hinzugefügten Rechteck, so dass das darunter liegende Bild erneut angezeigt wird. Mit Schnitt meine ich, dass das Angeben eines solchen "Löschrechtecks" Teile aus den zuvor gezeichneten Rechtecken ausschneidet. Wenn sie sich überlappen, werden nur die überlappenden Teile abgeschnitten. Wo die "Löschungsrechtecke" nicht den von den obigen Rechtecken belegten Raum schneiden, darf dem sichtbaren Bereich nichts passieren.

Wie kann ich das erreichen?

Antwort

1

Sie können einen Pfad verwenden, um die Rechtecke zu erstellen. Um die Rechtecke zu positionieren, können die Eckpunkte des Pfades übersetzt und transformiert werden. Mit der Tatsache, dass invertierte Scheitelpunkte aus einem Pfad ausgeschnitten werden, erzeugt man Löcher im äußeren Rechteck.

import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib.path import Path 
from matplotlib.patches import PathPatch, Rectangle 


fig, ax = plt.subplots() 
imdata = np.random.randn(10, 10) 


# create rectangle, coordinates are ignored 
rec = Rectangle((0,0),1,1).get_path() 

#the big rectangle 
r0 = rec.vertices+0.5 
# r1 and r2 are the rectangles to cut out of r0 
r1 = 0.6+rec.vertices[::-1]*0.35 
r2 = 1+rec.vertices[::-1]*0.35 

path = Path(vertices=np.concatenate([r0, r1, r2]), 
       codes=np.concatenate([rec.codes]*3)) 

im = ax.imshow(imdata, extent=(0, 2, 0, 2), aspect='equal', 
       cmap='coolwarm', interpolation='nearest') 


patch = PathPatch(path, facecolor='w') 
ax.add_patch(patch) 

plt.tight_layout() 
plt.show() 

enter image description here


Oder eine Lösung, die es einfacher zu spezifizieren die Koordinaten der Rechtecke macht:

import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib.path import Path 
from matplotlib.patches import PathPatch, Rectangle 


fig, ax = plt.subplots() 
imdata = np.random.randn(10, 10) 


def create_rec(x0, y0, width, height): 
    rec_patch = Rectangle((x0, y0),width, height) 
    rec_path = rec_patch.get_path() 
    rec_path = rec_patch.get_patch_transform().transform_path(rec_path) 
    return rec_path.vertices, rec_path.codes 

#the big rectangle 
r0,c = create_rec(0.3, 0.6, 1, 1.2) 
# r1 and r2 are the rectangles to cut out of r0 
r1,c = create_rec(0.4, 0.7, 0.3, 0.4) 
r2,c = create_rec(0.8, 1, 0.4, 0.5) 

path = Path(vertices=np.concatenate([r0, r1[::-1], r2[::-1]]), 
       codes=np.concatenate([c]*3)) 

im = ax.imshow(imdata, extent=(0, 2, 0, 2), aspect='equal', 
       cmap='coolwarm', interpolation='nearest') 


patch = PathPatch(path, facecolor='w') 
ax.add_patch(patch) 

plt.tight_layout() 
plt.show() 


Um den Fall, in dem das Rechteck teilweise außerhalb ist das ursprüngliche Rechteck, das folgende (basierend auf der zweiten Lösung) könnte helfen:

import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib.path import Path 
from matplotlib.patches import PathPatch, Rectangle 


fig, ax = plt.subplots() 
imdata = np.random.randn(10, 10) 


def create_rec(x0, y0, width, height): 
    rec_patch = Rectangle((x0, y0),width, height) 
    rec_path = rec_patch.get_path() 
    rec_path = rec_patch.get_patch_transform().transform_path(rec_path) 
    return rec_path.vertices, rec_path.codes 

#the big rectangle 
r0,c = create_rec(0.3, 0.6, 1, 1.2) 
# r1 and r2 are the rectangles to cut out of r0 
r1,c = create_rec(0.2, 0.5, 0.3, 0.4) 
r2,c = create_rec(0.8, 1, 0.4, 0.5) 

path = Path(vertices=np.concatenate([r0, r1[::-1], r2[::-1]]), 
       codes=np.concatenate([c]*3)) 

im = ax.imshow(imdata, extent=(0, 2, 0, 2), aspect='equal', 
       cmap='coolwarm', interpolation='nearest') 

patho = Path(vertices=r0,codes=c) 
patcho = PathPatch(patho, facecolor='none', edgecolor="none") 
ax.add_patch(patcho) 
patch = PathPatch(path, facecolor='w', clip_path=patcho, edgecolor="none") 
ax.add_patch(patch) 

plt.show() 

enter image description here

+0

Vielen Dank für Ihre Zeit. Leider ist das nur die halbe Wahrheit. Wenn Sie Ihr erstes Beispiel in 'r1 = 0.2 + rec.vertices [:: - 1] * 0.35 ändern, sehen Sie, dass es sich nicht um einen Schnitt handelt, sondern um eine Inversion. Irgendeine Idee, wie man das umgehen kann? –

+0

Nun, ich beantwortete Ihre Frage, die liest * "Ich möchte mehrere andere Rechtecke aus dem zuvor hinzugefügten Rechteck" *. Fühlen Sie sich frei, die Frage zu bearbeiten, wenn Sie etwas anderes wollen. – ImportanceOfBeingErnest

+0

Ich denke, dass meine Frage nicht wirklich irreführend ist. Ich betone jedoch genau dort. Danke noch einmal. P.S. Erledigt. –