Logiciel libre de géométrie, d'analyse et de simulation multiplateforme par Yves Biton

Accueil Tutoriels l’API de MathGraph32

Programmer une figure en Python : Le jongleur (utilisation avancée)

modification vendredi 14 avril 2024.

Toutes les versions de cet article : [English] [français]



Cet article est inspiré de cet article de Vincent Pantaloni sur le site de l’APMEP : https://afdm.apmep.fr/rubriques/ouvertures/mathematiques-du-jonglage/

Depuis version 7.9.1, MathGraph32 permet de créer des objets dans une figure en langage Python.

Ici nous allons générer une figure animée : le jongleur.

Le programme utilise des fonctions avancées de MathGraph32, y compris des nombres complexes.

Une fois que la figure est apparue, cliquez sur le bouton Start - Stop pour lancer l’animation et cliquez sur ce même bouton pour l’arrêter.

L’animation peut être très rapide : remplacez dans la ligne 22 : addTimerButton(draw, 1/60) 1/60 par 1/120 (c’est la fréquence d’animation en secondes), cliquez à nouveau sur le bouton Exécuter puis sur le bouton Start - Stop.

Vous pouvez aussi changer le nombre de balles (qui doit rester impair) en changeant la ligne : n_balls = addCalc(’nballs’, ’5’) et en remplaçant par exemple le 5 par 7.

Des explications supplémentaires ici



La ligne 7 : ph = addCalc(’ph’, ’0’) crée dans la figure MathGraph32 un calcul nommé ph avec comme formule 0. C’est cet objet calcul qui est renvoyé dans la variable Python ph (on pourrait l’appeler différemment mais prendre le même nom rend le code Python plus facile à comprendre).

Cette figure crée un bouton Start - Stop en haut et à gauche de la figure avec la ligne suivante :
addTimerButton(draw, 1/60)
Quand on clique sur ce bouton pour lancer l’animation, la fonction draw est appelée tous les soixantièmes de seconde.
Examinons la fonction draw :

def draw():
        global valph
        valph += 0.0075
        giveFormulaTo('ph', str(valph))
        updateDependantDisplay(ph) # On ne calcule et redessine que les objets dépenant du calcul ph

Cette fonction augmente la variable globale valph de 0.0075, donne cette valeur au calcul MathGrap32 ph sous forme d’un calcul dans une chaîne de caractères à l’aide de de la fonction de l’API giveFormulaTo, puis la ligne updateDependantDisplay(ph) demande à MathGraph32 de recalculer tous les objets de la figure dépendant du calcul ph et de les réafficher. En particulier les boules créées dans la fonction make_ball qui dépendent de ph sont toutes recalculées à chaque étape de l’animation (avec les bras).
A chaque étape de l’animation ce ne sont donc que les boules et les bras dépendant de ph qui sont calculées et réaffichés.

Tout ce qui est géré dans la fonction make_ball(i) qui est appelée pour i = 1 à n_balls doit donc être des objets MathGraph32. Impossible donc ici d’utiliser par exemple un if else utilisant des variables Python.

MathGraph32 n’accepte pas qu’on rajoute à une figure un calcul ayant le nom d’un calcul (ou une fonction) déjà créé.

C’est pourquoi les noms des calculs MathGraph32 utilisés dans cette fonction sont suffixés par la valeur de i.

Un exemple :
Au premier appel de cette fonction avec i = 1, les lignes suivantes :

        stri = str(i)
        j = 'j' + stri # Nom du calcul qui repésente la valeur actuelle de i dans les calculs MathGraph32 suivants
        addCalc(j, stri)
<code>
vont créer un calcul MathGraph32 nommé j1 avec comme formule '1'.
Au deuxième appel de cette fonction avec i = 2, un nouveau calcul nommé j2 sera créé avec comme formule '2'.

Examinons les lignes suivantes de cette fonction make_ball :
<code>
        ballph = 'ballph' + stri # Nom de calcul dans mtg32
        ball_ph = addCalc(ballph, f"mod(2.0 * (ph * nballs + {j}),nballs * 2)")

La première ligne crée un calcul Python nommé ballph (local à la fonction make_ball).
Lors du premier appel de la fonction make_ball, la variable Python ballph contient la chaîne de caractères ’ballph1’ qui sera utilisée dans la ligne suivante comme nom du calcul MathGraph32 créé (qui sera renvoyé dans la variable Python ball_ph). :

ball_ph = addCalc(ballph, f"mod(2.0 * (ph * nballs + {j}),nballs * 2)")

La fonction addCalc de l’API ajoute à la figure MathGraph32 un calcul réel dont le nom est le premier argument et dont le deuxième argument est la formule utilisée pour créer ce calcul. L’objet Python renvoyé par cette fonction est le calcul MathGraph32 créé. (plus loin on utilise la fonction addCalcComp qui procède de même pour créer un calcul complexe MathGraph32).
Examinons la formule utilisée pour définir ce nouveau calcul : f"mod(2.0 * (ph * nballs + j),nballs * 2)"
Le f qui précède la chaîne de caractères indique qu’on doit y remplacer ce qui est entre accolades par le contenu de la variable Python correspondante. Ainsi, lors de la création du calcul pour i = 1, la chaîne de caractères servant à définir la fonction sera : mod(2.0 * (ph * nballs + j1),nballs * 2). MathGraph32 connaît les calculs ph, nballs et j1 (défini avant dans make_ball) donc cette formule est valide pour définir un calcul MathGraph32.

A noter que la fonction MathGraph32 mod (a, b) fournit le reste de la division euclidienne de a par b (l’équivalent de a%b en Python).

Plus loin, la ligne suivant :

forcalc = f"si({ballph} <= nballs - 1, {airltor}, si({ballph} <= nballs ,rhand, si({ballph} <= 2*nballs - 1,{airrtol}, lhand)))"

définit une variable Python forcalc contenant une chaîne de caractères contenant une formule valide pour un calcul complexe MathGraph32.

Par exemple, dans cette chaîne de caractères, rhand fait référence à un calcul complexe MathGraph32 créé ligne 82 qui contient l’affixe complexe de la main droite qui dépend de ph).

On pourrait procéder autrement sans utiliser de calculs MathGraph32 pour rendre ce qui dépend de ph dynamique (votre serviteur l’a fait) et de tout recalculer et réafficher à chaque passage dans la fonction draw mais dans ce cas impossible d’obtenir une animation de fréquence 1/120 s.

La fonction MathGraph32 si(valeurtest, valeursiun, valeursinon) renvoie valeursiun si valeurtest vaut 1 et valeursinon si valeurtest ne vaut pas 1. Elle est utilisable dans un calcul réel ou complexe.

La ligne suivante :

point = addPointZ(f"{forcalc}", '')

crée un point dont l’affixe est donnée par la formule contenue dans la variable chaîne de caractères Python forcalc. Le deuxième argument est le nom du point créé qui est ici une chaîne vide. Cet deuxième argument est optionnel et peut être omis : point = addPointZ(f"forcalc") donnera le même résultat.