Monday, February 26, 2024

PMAE 4 : regular polygons resembling a Ferris wheel

Python Matplotlib Animation Example 4

regular polygons resembling a Ferris wheel

This Python code utilizes the Matplotlib library to generate an animated Ferris wheel-like visualization featuring rotating regular polygons. The animation continues indefinitely, showcasing polygons with varying numbers of sides rotating around a central point. The update function dynamically adjusts the positions of the polygons based on a rotating angle, creating an engaging and visually intriguing effect. The rotation speed is controlled by the P parameter in the draw function, and each frame is updated at a 40-millisecond interval. Users can customize parameters such as the number of polygon sides, colors, and animation speed to achieve different visual effects. Overall, this code delivers a captivating and customizable representation of regular polygons in continuous rotation, resembling a Ferris wheel.



This Python code visualizes a rotating Ferris wheel with attached regular polygons. It combines mathematical functions, animation libraries, and visualization tools to create a visually appealing and informative animation of a rotating Ferris wheel with various polygons attached. The code effectively simulates the rotation of different sized polygons, showcasing animation capabilities in Python.

Python source code

import time
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from math import cos, sin, tan, pi

fig = plt.figure(figsize=(3,3), facecolor="#FFFFFF")
ax = plt.axes([0, 0, 1, 1])
ax.set_xlim([-1.3, 1.3])
ax.set_ylim([-1.5, 1.1])
ax.axis('off')

def getdata(n):
nth = 361
dth = 2*pi/(nth-1)
sth = 2*pi/n
xs, ys = [], []
for ith in range(nth):
theta = ith*dth
rth = int(theta/sth)*sth
x1 = cos(sth/2)
y1 = tan(sth/2-(theta-rth))*x1
x2 = x1*cos(rth) + y1*sin(rth)
y2 = -x1*sin(rth) + y1*cos(rth)
xs.append(x2)
ys.append(y2)
return xs, ys

def getinit(n):
dth = 2*pi/8
theta = dth*(n-3)
x0 = cos(theta)
y0 = sin(theta)
return x0, y0

def getposdata(n):
x, y = getdata(n)
sth = 2*pi/n
x0, y0 = getinit(n)
xs, ys = [], []
for i in range(len(x)):
x3 = x[i]*cos(pi/2-sth/2) - y[i]*sin(pi/2-sth/2)
y3 = x[i]*sin(pi/2-sth/2) + y[i]*cos(pi/2-sth/2)
x4 = x3*0.2+x0
y4 = (y3-1)*0.2+y0
xs.append(x4)
ys.append(y4)
return xs, ys

def getwheel():
nth = 25
dth = 2*pi/(nth-1)
xs, ys = [], []
for ith in range(nth):
theta = ith*dth
x1 = cos(theta)
y1 = sin(theta)
xs.append(x1)
ys.append(y1)
if ith%3 == 0:
nth2 = 13
dth2 = 2*pi/(nth2-1)
for ith2 in range(nth2):
theta2 = ith2*dth2
x2 = cos(theta2)*0.05 + x1
y2 = sin(theta2)*0.05 + y1
xs.append(x2)
ys.append(y2)
xs.append(x1)
ys.append(y1)
return xs, ys

xs1, ys1 = getwheel()
xs2, ys2 = getposdata(3)
xs3, ys3 = getposdata(4)
xs4, ys4 = getposdata(5)
xs5, ys5 = getposdata(6)
xs6, ys6 = getposdata(7)
xs7, ys7 = getposdata(8)
xs8, ys8 = getposdata(9)
xs9, ys9 = getposdata(10)

pl1 = ax.plot(xs1, ys1, color="#000000", lw=2.5, zorder=0)[0]
pl2 = ax.plot(xs2, ys2, color="#0000FF", lw=2.5, zorder=1)[0]
pl3 = ax.plot(xs3, ys3, color="#0000FF", lw=2.5, zorder=1)[0]
pl4 = ax.plot(xs4, ys4, color="#0000FF", lw=2.5, zorder=1)[0]
pl5 = ax.plot(xs5, ys5, color="#0000FF", lw=2.5, zorder=1)[0]
pl6 = ax.plot(xs6, ys6, color="#0000FF", lw=2.5, zorder=1)[0]
pl7 = ax.plot(xs7, ys7, color="#0000FF", lw=2.5, zorder=1)[0]
pl8 = ax.plot(xs8, ys8, color="#0000FF", lw=2.5, zorder=1)[0]
pl9 = ax.plot(xs9, ys9, color="#0000FF", lw=2.5, zorder=1)[0]

def rotate(x, y, theta):
xp, yp = [], []
for i in range(len(x)):
x1 = x[i]*cos(theta) - y[i]*sin(theta)
y1 = x[i]*sin(theta) + y[i]*cos(theta)
xp.append(x1)
yp.append(y1)
return xp, yp

def shift(x, y, n, theta):
x0, y0 = getinit(n)
x0p = x0*cos(theta) - y0*sin(theta)
y0p = x0*sin(theta) + y0*cos(theta)
xp, yp = [], []
for i in range(len(x)):
x1 = x[i] + (x0p-x0)
y1 = y[i] + (y0p-y0)
xp.append(x1)
yp.append(y1)
return xp, yp


def update(theta):
xp, yp = rotate(xs1, ys1, theta); pl1.set_data(xp, yp)
xp, yp = shift(xs2, ys2, 3, theta); pl2.set_data(xp, yp)
xp, yp = shift(xs3, ys3, 4, theta); pl3.set_data(xp, yp)
xp, yp = shift(xs4, ys4, 5, theta); pl4.set_data(xp, yp)
xp, yp = shift(xs5, ys5, 6, theta); pl5.set_data(xp, yp)
xp, yp = shift(xs6, ys6, 7, theta); pl6.set_data(xp, yp)
xp, yp = shift(xs7, ys7, 8, theta); pl7.set_data(xp, yp)
xp, yp = shift(xs8, ys8, 9, theta); pl8.set_data(xp, yp)
xp, yp = shift(xs9, ys9, 10, theta); pl9.set_data(xp, yp)

def draw(i):
P = 20.0
t = time.time()
theta = t/P*2*pi%(2*pi)
update(theta)

ani = animation.FuncAnimation(fig, draw, interval=40)

plt.show()

This code creates an animation of regular polygons resembling a Ferris wheel. Here's a breakdown:

■ Imports:
• Libraries for plotting (`matplotlib.pyplot`) and animation (`matplotlib.animation`) are imported.
• Mathematical functions (cosine, sine, tangent, and pi) are imported from the `math` library.

■ Figure and Axes Setup:
• A figure is created with a size of 3x3 inches and a white background.
• Axes are added to the figure, and their limits and visibility are set for a clean appearance.

■ Data Generation Functions:
• `getdata(n)`: Generates a regular polygon with `n` sides. It calculates the x and y coordinates of each vertex based on the angle and radius.
• `getinit(n)`: Provides the initial position (x and y coordinates) for a polygon with `n` sides.
• `getposdata(n)`: Creates a smaller, shifted, and rotated version of the polygon based on the original data and initial position.
• `getwheel()`: Defines the large base polygon with smaller polygons attached at specific intervals, resembling the Ferris wheel structure.

■ Variable Initialization:
• Nine sets of data (x and y coordinates) are generated for each polygon using the functions above.
• Each set is assigned to a corresponding variable (`xs1`, `ys1`, etc.).

■ Plotting:
• Nine lines representing the polygons are plotted using `ax.plot` with different colors and line widths.

■ Rotation and Shifting Functions:
• `rotate(x, y, theta)`: Takes x and y coordinates and a rotation angle. It returns the rotated coordinates.
• `shift(x, y, n, theta)`: Takes x and y coordinates, the number of sides (`n`), and a rotation angle. It returns the shifted and rotated coordinates based on the initial position.

■ Animation Update Function:
• `update(theta)`: Takes a rotation angle (`theta`) as input.
• It updates the data (x and y coordinates) of each plotted line using the `shift` and `rotate` functions with appropriate arguments.
• This essentially rotates and shifts the individual polygons based on their defined parameters.

■ Animation Drawing Function:
• `draw(i)`: This function is called repeatedly during the animation loop.
• It calculates the rotation angle based on the current time and a desired animation period (`P`).
• It calls the `update` function to update the data for each polygon based on the calculated angle.

■ Animation Creation:
• `ani`: Creates an animation object using `FuncAnimation`.
• It specifies the figure (`fig`), the drawing function (`draw`), and the interval (40 milliseconds) between frame updates.

■ Display:
• `plt.show()`: Displays the generated animation.

Overall, this code effectively utilizes mathematical functions, data generation, animation techniques, and plotting libraries to create a visually appealing animation of regular polygons rotating like a Ferris wheel.



No comments:

Post a Comment