|
1 | 1 | # -----------------------------------------------------------------------------
|
2 | 2 | # Rain simulation
|
3 |
| -# Author: Nicolas P. Rougier |
| 3 | +# Author: Nicolas rain_drops. Rougier |
4 | 4 | # -----------------------------------------------------------------------------
|
5 |
| -import matplotlib |
| 5 | +""" |
| 6 | +Simulates rain drops on a surface but animating the growth and fade |
| 7 | +of 50 scatter points. |
| 8 | +
|
| 9 | +""" |
6 | 10 | import numpy as np
|
7 | 11 | import matplotlib.pyplot as plt
|
8 | 12 | from matplotlib.animation import FuncAnimation
|
9 | 13 |
|
10 | 14 |
|
11 |
| -# Create new figure |
| 15 | +# Create new Figure and an Axes which fills it. |
12 | 16 | fig = plt.figure(figsize=(7,7))
|
13 |
| -ax = fig.add_axes([0,0,1,1], frameon=False, aspect=1) |
14 |
| - |
15 |
| -# Create rain data |
16 |
| -P = np.zeros(50, dtype=[('position', float, 2), |
17 |
| - ('size', float, 1), |
18 |
| - ('growth', float, 1), |
19 |
| - ('color', float, 4)]) |
20 |
| - |
21 |
| -# Scatter plot is used to animate rain drops |
22 |
| -scat = ax.scatter(P['position'][:,0], P['position'][:,1], P['size'], |
23 |
| - lw=0.5, edgecolors = P['color'], facecolors='none') |
| 17 | +ax = fig.add_axes([0, 0, 1, 1], frameon=False) |
24 | 18 | ax.set_xlim(0,1), ax.set_xticks([])
|
25 | 19 | ax.set_ylim(0,1), ax.set_yticks([])
|
26 | 20 |
|
| 21 | +# Create rain data |
| 22 | +n_drops = 50 |
| 23 | +rain_drops = np.zeros(n_drops, dtype=[('position', float, 2), |
| 24 | + ('size', float, 1), |
| 25 | + ('growth', float, 1), |
| 26 | + ('color', float, 4)]) |
27 | 27 |
|
28 |
| -def update(frame): |
29 |
| - i = frame % len(P) |
30 |
| - |
31 |
| - # Make all colors more transparent |
32 |
| - P['color'][:,3] -= 1.0/len(P) |
33 |
| - P['color'][:,3] = np.clip(P['color'][:,3], 0, 1) |
| 28 | +# Initialize the raindrops in random positions and with |
| 29 | +# random growth rates. |
| 30 | +rain_drops['position'] = np.random.uniform(0, 1, (n_drops, 2)) |
| 31 | +rain_drops['growth'] = np.random.uniform(50, 200, n_drops) |
34 | 32 |
|
35 |
| - # Make all circles bigger |
36 |
| - P['size'] += P['growth'] |
| 33 | +# Construct the scatter which we will update during animation |
| 34 | +# as the raindrops develop. |
| 35 | +scat = ax.scatter(rain_drops['position'][:,0], rain_drops['position'][:,1], |
| 36 | + s=rain_drops['size'], lw=0.5, edgecolors=rain_drops['color'], |
| 37 | + facecolors='none') |
37 | 38 |
|
38 |
| - # Pick a new position for oldest rain drop |
39 |
| - P['position'][i] = np.random.uniform(0, 1, 2) |
40 | 39 |
|
41 |
| - # Reset size |
42 |
| - P['size'][i] = 5 |
| 40 | +def update(frame_number): |
| 41 | + # Get an index which we can use to re-spawn the oldest raindrop. |
| 42 | + current_index = frame_number % n_drops |
43 | 43 |
|
44 |
| - # Reset color |
45 |
| - P['color'][i] = (0, 0, 0, 1) |
| 44 | + # Make all colors more transparent as time progresses. |
| 45 | + rain_drops['color'][:, 3] -= 1.0/len(rain_drops) |
| 46 | + rain_drops['color'][:,3] = np.clip(rain_drops['color'][:,3], 0, 1) |
46 | 47 |
|
47 |
| - # Choose a random growth factor |
48 |
| - P['growth'][i] = np.random.uniform(50, 200) |
| 48 | + # Make all circles bigger. |
| 49 | + rain_drops['size'] += rain_drops['growth'] |
49 | 50 |
|
50 |
| - # Update scatter plot |
51 |
| - scat.set_edgecolors(P['color']) |
52 |
| - scat.set_sizes(P['size']) |
53 |
| - scat.set_offsets(P['position']) |
| 51 | + # Pick a new position for oldest rain drop, resetting its size, |
| 52 | + # color and growth factor. |
| 53 | + rain_drops['position'][current_index] = np.random.uniform(0, 1, 2) |
| 54 | + rain_drops['size'][current_index] = 5 |
| 55 | + rain_drops['color'][current_index] = (0, 0, 0, 1) |
| 56 | + rain_drops['growth'][current_index] = np.random.uniform(50, 200) |
54 | 57 |
|
55 |
| - return scat, |
| 58 | + # Update the scatter collection, with the new colors, sizes and positions. |
| 59 | + scat.set_edgecolors(rain_drops['color']) |
| 60 | + scat.set_sizes(rain_drops['size']) |
| 61 | + scat.set_offsets(rain_drops['position']) |
| 62 | + |
56 | 63 |
|
| 64 | +# Construct the animation, using the update function as the animation |
| 65 | +# director. |
57 | 66 | animation = FuncAnimation(fig, update, interval=10)
|
58 | 67 | plt.show()
|
0 commit comments