# # PYTHON for DUMMIES 23-24 # Problème 1 # # Un cercle roule sans glisser autour d'un autre cercle. # # Vincent Legat # (avec l'aide bienveillante de copilotes anonymes) # # ------------------------------------------------------------------------- # import numpy as np # ============================================================ # FONCTIONS A MODIFIER [begin] # # -1- Création d'un cercle... # radius : rayon du cercle # n : nombre de points répartis entre [0,2*pi] pour tracer le cercle # il y aura donc n-1 arcs de cercles :-) # # theta : tableau numpy contenant les angles pour chaque point # x,y : tableaux numpy contenant les coordonnées x,y pour chaque point # def circlesCreate(radius,n) : theta = np.zeros(n) # à modifier ! x = np.zeros(n) # à modifier ! y = np.zeros(n) # à modifier ! return theta,x,y # # -2- Calcul des angles où le petit cercle aura retrouvé sa position initiale # ratio : rapport entre le rayon du cercle intérieur et le rayon du cercle extérieur # # thetas : tableau numpy contenant les angles où le cercle intérieur aura retrouvé sa position initiale def circlesAngles(ratio) : thetas = np.array([0,45,90]) # à modifier ! return thetas # # -3- Animation des deux cercles... # theta : angle du point de contact du petit cercle avec le grand cercle # x_rolling,y_rolling : tableaux numpy contenant les coordonnées x,y pour les points du cercle roulant # ratio : rapport entre le rayon du cercle intérieur et le rayon du cercle extérieur # # x,y : tableaux numpy contenant les coordonnées x,y pour les points du cercle roulant pour l'angle theta # def circlesAnimate(theta,x_rolling,y_rolling,ratio) : x = x_rolling # à modifier ! y = y_rolling # à modifier ! return x,y # # # FONCTIONS A MODIFIER [end] # ============================================================ # # -1- Test des fonctions et animation :-) def main() : # # -2- Paramètres du problème # ratio : rapport entre le rayon du cercle intérieur et le rayon du cercle extérieur # n_steps : nombre de pas pour une rotation complète du petit cercle # n : nombre de pas pour que le petit cercle revienne a sa position initiale # i_mid : indice du point initial droit du cercle roulant # (le point initial gauche est à l'indice 0) # ratio = 4 n_steps = 31 n = (ratio+1)*n_steps+1 i_mid = n_steps//2 # # -3- Création des cercles # [theta_inner,x_inner,y_inner] = circlesCreate(ratio,n) [theta_rolling,x_rolling,y_rolling] = circlesCreate(1,n_steps) # # -4- Et zou, un joli plot et une jolie animation :-) # x_left,y_left : tableaux numpy contenant les coordonnées x,y pour le point gauche du cercle roulant # x_right,y_right : tableaux numpy contenant les coordonnées x,y pour le point droit du cercle roulant # import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation plt.rcParams['toolbar'] = 'None' fig = plt.figure("Circle rolling around another circle") x_left = np.ones_like(x_inner) * np.nan y_left = np.ones_like(y_inner) * np.nan x_right = np.ones_like(x_inner) * np.nan y_right = np.ones_like(y_inner) * np.nan # # -4.1- Plot des trajectoires et des animations # line1,line2,Line3,Line4,Line5 : objets pour les animations qui permettront de mettre à jour les plots # plt.fill(x_inner,y_inner, 'b-') line1, = plt.plot([], [], 'r-') line2, = plt.plot([], [], 'b-') line3, = plt.plot([], [], 'k-') line4, = plt.plot([], [], 'ko-') line5, = plt.plot([], [], 'bo') # # -4.2- Plot du cercle roulant dans son configuration initiale # et du grand cercle fixe en bleu # (ces plots ne seront pas mis à jour par l'animation) for theta in circlesAngles(ratio) : [x,y] = circlesAnimate(theta,x_rolling,y_rolling,ratio) plt.fill(x[0:i_mid+1],y[0:i_mid+1],color='r',alpha=0.5) plt.fill(x[i_mid:],y[i_mid:],color='y',alpha=0.5) # # -4.3- Définition de la fonction callback pour l'animation # (elle sera appelée à chaque pas de temps) # (elle mettra à jour les plots) # def animate(i): [x,y] = circlesAnimate(theta_inner[i],x_rolling,y_rolling,ratio) x_left[i] = x[0] y_left[i] = y[0] x_right[i] = x[i_mid] y_right[i] = y[i_mid] line1.set_data(x,y) line2.set_data(x_left,y_left) line3.set_data(x_right,y_right) line4.set_data([x[0],x[i_mid]],[y[0],y[i_mid]]) line5.set_data([x[0]],[y[0]]) return line1,line2,line3,line4,line5 # # -4.4- Lancement de l'animation # (elle appelle la fonction callback à chaque pas de temps) # animation = FuncAnimation(fig,animate,frames=n,interval=200) size = 2.2 + ratio ax = plt.gca() ax.set_xlim(-size, size) ax.set_ylim(-size, size) ax.set_aspect('equal') plt.axis('off') # # -4.5- Sauvegarde de l'animation dans un fichier # (si ffmpeg est installé sur votre ordinateur) # # animation.save('circle_animation.mp4', writer='ffmpeg') # plt.show() main()