Le livre « The Nature of Code” dans le chapitre 3 nous propose de travailler avec le mouvement angulaire et la trigonométrie pour créer des effets intéressants basés sur les oscillations. En effet l’électricité n’est elle pas fournie sous la forme d’un courant alternatif représenté par une sinusoide? Ne faut-il pas prendre en compte ces mouvements dans la vie de tous les jours. Nos systèmes de particules n’en seront que plus intéressants car basés sur la physique des pendules ou des ressorts ils pourront créer des mouvements évocateurs.
Sin(theta) et cos(theta) forment des vagues lorsque l’on décrit le déplacement d’un objet selon ces fonctions. La combinaison de sin et cos crée des vagues plus complexes. La trigonométrie nous permet de définir la localisation d’un objet en coordonnées polaires par rapport aux coordonnées cartésiennes qui sont la façon par défaut d’interagir avec processing. Il nous suffit d’un angle et d’une distance. On pourrait aussi définir une forme en définissant ses vertex comme prenant les valeurs x = r*cos(theta) et y = r*sin(theta) en incrémentant la valeur de thêta entre 0 et 2*PI un certain nombre de fois pour obtenir un polygone comme dans processing pour android.
- Le pendule
https://github.com/Thibautomaton/TheNatureOfCodeChapitre3Pendulum
Essayons de décrire le mouvement d’un pendule. Les cours du lycée nous apprennent que dans ce cas sin(theta) = Fg / Fp avec Fg la force dû à la gravité et Fp la force du pendule perpendiculaire au mouvement. L’accélération est donc égale à -1*gravité*sin(theta). On additionne l’accélération angulaire à la vitesse angulaire, que l’on additionne à l’angle thêta du pendule. On a donc la fonction update suivante:
def update(self):
gravity = 0.4
self.aAcceleration = (-1*gravity*sin(self.angle))
self.aVelocity+=self.aAcceleration
self.aVelocity*=self.damping
self.angle +=self.aVelocity
self.location = PVector(self.r*sin(self.angle), self.r*cos(self.angle))
self.location.add(self.origin)
Pour chaîner les pendules et les voir reproduire le comportement souhaité, il suffit de changer l’origine du deuxième pendule pour correspondre à la localisation du premier pendule.
On introduit la fonction update_origin() :
def update_origin(self, origin):
self.origin = origin
Le reste de la fonction ne change pas. Dans la fonction draw() on update d’abord le pendule 1, puis on change l’origine du pendule 2 et on l’update à son tour. Le mouvement a plus d’amplitude et produit un effet intéressant mais ne correspond pas à une réalité physique.
- Le ressort
https://github.com/Thibautomaton/TheNatureOfCodeChapitre3Spring
Un ressort utilise aussi les formes sinusoïdales pour sa représentation, mais comme on se concentre sur la physique, nous ne nous occuperons que du comportement de la charge par rapport au point d’origine du ressort. Un bon exercice serait de faire une représentation sinusoïdale du fil du ressort en adaptant la période à la longueur d’élongation du fil.
La physique du ressort implique une force réactive proportionnelle à la distance d’élongation par rapport à distance nominale. On remarque que cette force peut être négative ou positive, et que cette alternance pourrait être représentée sous forme d’une sinusoïde. C’est cette force qui sera appliquée, multiplié par le coefficient du ressort dans la méthode connect().
def connect(self, bob):
force = PVector.sub(bob.location, self.anchor)
d = force.mag()
stretch = d-self.leng
force.normalize()
force.mult(-1*self.k*stretch)
bob.applyForce(force)
On a également la méthode displayLine() qui prend aussi bob en argument et crée une ligne à l’emplacement du ressort. Bob est un objet Mover classique si ce n’est que la force qui lui est appliquée est celle du ressort.
On remarque qu’ aucun damping est appliqué, ce qui pourrait aussi être un bon exercice.
- Combinaison ressort + pendulum
https://github.com/Thibautomaton/Chapitre3SpringPendulum
L’étape d’après est de combiner ces interactions (force du pendule qui crée une force rotative , et force du ressort qui décrit un mouvement de translation). Ainsi on obtiendra un effet intéressant à partir d’interactions physiques simples. Il est important d’ajouter que ces interactions bien que intéressantes et plaisantes mentalement ne correspondent pas à une interaction physique véritable. Un véritable ressort ne se comporterait pas comme ça si nous l’avions devant les yeux car les interactions sont plus complexes dans la nature. En effet on peut imaginer que la pénétration dans l’air du ressort lors du mouvement de pendule désaxe celui-ci et qu’en résulte un mouvement beaucoup plus erratique.
On a encore le fichier Spring et Bob, le deuxième ne change pas, c’est le premier qui revêt les fonctionnalités de Spring et de Pendulum. On définit donc les constantes k et leng. La fonction update_anchor() va nous permettre de chaîner, les ressorts/pendules. C’est la fonctionupdate_physics() qui peut paraître plus complexe.
def updatePhysics(self):
gravity = 0.4
rAcceleration = (-self.k*(self.r – self.leng))/self.m
self.rVelocity += rAcceleration
self.rVelocity *= self.damping
self.r += self.rVelocity
aAcceleration = (-gravity *sin(self.angle))/self.r
self.aVelocity += aAcceleration
self.aVelocity *= self.damping
self.angle += self.aVelocity
self.location.x = self.anchor.x + self.r*sin(self.angle)
self.location.y = self.anchor.y + self.r*cos(self.angle)
Le premier bloc correspond au ressort, le second bloc à l’accélération du pendule. ll faut mettre à jour la position du pendule, les coordonnées polaires nous aidant beaucoup dans ce cas.

un ressort et un pendule chainés crée un mouvement interessant
CONCLUSION:
Nous avons pu voir comment la trigonométrie nous permet de définir des forces de voir leurs effets sur un objet. Tout ceci se passe dans processing.py qui nous permet beaucoup de choses et de laisser libre court à notre imagination lorsqu’il s’agit de l’invention de forces. Cependant pour continuer dans l’exploration des forces, nous allons nous intéresser à une bibliothèque complémentaire qui s’appelle Box2D et nous permettra d’implémenter des interactions réalistes sans avoir à modéliser manuellement chaque interaction.
Voyons nous dans le prochain article où on explore un exemple utilisant la bibliothèque Box2D et pygame.
