Reputation: 123
I would like to plot two arbitrary polygons (using shapely for calculation of area, intersection as I am not aware of another method) and then fill the intersection, and shapes as they intersect and move during the animation.
After searching I cannot figure out how to implement this.
I have reviewed:
However, I believe I must be missing something fundamental here, or possibly it does not support filling objects during animation as the only filled object examples I can locate are static graphs.
Example code (minimum example, with two shapely shapes) is below, and has been tested as functional with python 3.
import numpy as np
import matplotlib.pyplot as plt
import shapely.geometry as sg
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
xdata, ydata = [],[]
x2data, y2data = [],[]
ln, = plt.plot([],[])
ln2, = plt.plot([],[])
def init():
ax.axis('equal')
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
return ln,ln2,
def update(frame):
fig.text(0,0, 'hello')
circ1 = sg.Point(frame-2,0).buffer(1.0)
circ2 = sg.Point(-frame+2,0).buffer(1.0)
x,y = circ1.exterior.xy
x2,y2 = circ2.exterior.xy
intersection = circ1.intersection(circ2)
xdata.append(x)
ydata.append(y)
x2data.append(x2)
y2data.append(y2)
ln.set_data(x,y)
ln2.set_data(x2,y2)
return ln,ln2,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2, 200),
init_func=init, blit=True, interval = 10)
plt.show()
Upvotes: 1
Views: 844
Reputation: 1
You first need to make a fill object by:
fill = ax.fill_between(xdata, ydata, 0, color='cyan')
Then, access the PolyCollection Class and update its vertice in the animation function by using
def animation(t):
path = fill.get_paths()[0]
verts = path.vertices
# change vertice in numpy array hereof
verts[1:-1, 1][0:2] = np.array([x, x, x])
fill.set_color('cyan')
return line
Upvotes: 0
Reputation: 40697
Since you are working with Polygons, I would suggest you use matplotlib's Polygon
instead of a line to draw your shapes. This allows you to get the coordinates of the intersection shape, and draw the corresponding polygon with whatever color you choose:
import numpy as np
import matplotlib.pyplot as plt
import shapely.geometry as sg
from matplotlib.animation import FuncAnimation
from matplotlib.patches import Polygon
fig, ax = plt.subplots()
poly1 = Polygon(np.zeros(shape=(0, 2)), facecolor='none', edgecolor='C0')
poly2 = Polygon(np.zeros(shape=(0, 2)), facecolor='none', edgecolor='C1')
intersect = Polygon(np.zeros(shape=(0, 2)), facecolor='C2', edgecolor='none')
ax.add_artist(poly1)
ax.add_artist(poly2)
ax.add_artist(intersect)
t = ax.text(0.5, 0.9, "frame = ", transform=ax.transAxes, ha='center')
def init():
ax.axis('equal')
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
return poly1, poly2, t
def update(frame):
t.set_text(f'frame = {frame:.3f}')
circ1 = sg.Point(frame - 2, 0).buffer(1.0)
circ2 = sg.Point(-frame + 2, 0).buffer(1.0)
x, y = circ1.exterior.xy
x2, y2 = circ2.exterior.xy
intersection = circ1.intersection(circ2)
poly1.set_xy(np.c_[x, y])
poly2.set_xy(np.c_[x2, y2])
if len(intersection.exterior.coords)>0:
x3, y3 = intersection.exterior.coords.xy
intersect.set_xy(np.c_[x3, y3])
intersect.set_visible(True)
else:
intersect.set_visible(False)
return poly1, poly2, intersect, t
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2, 200),
init_func=init, blit=True, interval=10)
plt.show()
Upvotes: 4