16 décembre 2021

Plan complexe en JavaScript

Pour illustrer mon article précédent, Nombres complexes, j'ai dû me faire un outil en JavaScript. Il permet de représenter un repère du plan complexe et d'y tracer des figures. L'avantage de JS est qu'il fait des dessins très propres.

Cet article s'adresse à des gens qui ont une connaissance de base de HTML, JavaScript et de l'API canvas.

Présentation

Exemple de la figure ci-contre

Fig. 1

JavaScript permet de dessiner dans une balise HTML <canvas>. L'interface JS est très verbeuse et nécessite des conversions incessantes vers les coordonnées du contexte graphique.

Le script argand.js(1)est spécialisé dans la représentation des nombres complexes dans le plan en se débarrassant de ces conversions.

Le code JS de la figure Fig. 1 utilisant l'interface argand.js est le suivant :

initCtx('fig1', 50, 120, 40); // initialisations : id, O.X, O.Y, scl
let M = new Pt(2, 2.8, "M"); // trace le point M
M.label(2, 3); // marque le nom du point
O._(M); // joint OM
let I = new Pt(1, 0, "I"); // nouveau point I
angle(O, I, M, 22, "θ"); // angle (OI, OM)
let P = new Pt(2.4, 1.2, "P"); // nouveau point P
P.label(2, 2); // marque son nom
M.to(P); // trace une «flèche» de M à P

Le script se charge de tout, les calculs de conversion, et les affichages. Sans lui il aurait fallu plus d'une centaine de lignes de code.

Mise en œuvre

Gardons l'exemple de la page courante http://arad.free.fr/plancomplexe.html, et plus précisément de la figure ci-dessus Fig. 1 . Trois fichiers contribuent à l'affichage de cette figure :

Pour commencer il faut inclure dans le head du fichier HTML de la page le fichier argand.js et celui(2)des commandes comme ci-dessous :

<script src="script/argand.js"></script>
<script src="script/plancomplexe.js"></script>

Ensuite, il faut créer un «canvas» dans le body, à l'endroit où va apparaître la figure. Par exemple pour la figure Fig. 1 ci dessus j'ai fait :

<canvas id='fig1' width='200' height='160'></canvas>

Maintenant on peut commencer à rédiger les commandes. Généralement on le fait dans un fichier js , mais on peut les placer dans une balise <script>.

La première commande doit être la fonction initCtx. Son premier paramètre est l'identifiant du canvas, c'est à dire ici 'fig1'. Les autres paramètres étant dans l'ordre : l'abscisse de l'origine O à l'écran, son ordonnée, et l'échelle du tracé, soit ici 50, 120 et 40.

Référence

Cheat sheet

Notations : (x, y) sur le papier, (X, Y) à l'écran

initCtx(id, X, Y, u); initialise avec id: identifiant du canvas, (X, Y): origine , u: unité;

let P = new Pt(x, y, "P"); crée un point P de coordonnées (x, y) nommé "P".

P.mark(); marque le point P (un petit «pâté»).

text(t, X, Y) affiche un texte t à (X, Y).(3)

P.label(dX, dY); marque le nom de P avec un décalage dX, dY par rapport à P.

O.to(M); trace une flèche de O à M

angle(O, M, P, "θ"); trace l'angle (OM, OP) (un petit arc) et le nomme θ (facultatif).

thin(w); fixe l'épaisseur du tracé, 1 par défaut.

dash(t); t = 0: traits pleins ; t = 1 pointillés serrés ; t > 1 plus larges et espacés.

P.info(); envoie sur le document les coordonnées de P pour ajuster la position d'un texte.

O: origine défini initCtx O = {x: 0, y:0, X: paramX, Y: paramY};

Créer un point

Pour créer un point M de coordonnées 1.5 et 2, nommé "M" sur la figure on fait :

let P = new Pt(1.5, 2, "M");

Le dernier argument "M" est facultatif, mais dans ce cas on ne peut pas inscrire son nom sur la figure.

Le point créé ne sera pas visible jusqu'à ce qu'on le relie à un autre, ou qu'on le demande explicitement par P.mark();.

Afficher le nom d'un point

P.label(2, -10);

Les paramètres de label sont les décalages à getContextdroite et en bas(4)mesurés à l'écran. Ceci permet d'inscrire à loisir le nom du point où l'on veut : à droite, à gauche, en haut en bas.

Attention : ces décalages sont relatifs à l'écran en pixels, rien à voir les coordonnées (1.5, 2) du point. Le deuxième paramètre Y est relatif à l'écran, lorsqu'il augmente le point descend.

Tracer un segment de droite

Exemple de code traçant le segment [OP] :

O._(P);

Alternative en style procédural : lineSegment(A, B).

Tracer un vecteur

M.to(P);

Trace le vecteur MP› (ajoute une flèche au segment)

Alternative non objet : arrow(M, P);.

Tracer un angle

angle(O, M, P, "θ");

Dessine un petit arc de cercle à l'intérieur de l'angle (OM, OP).

Le dernier paramètre "θ" est facultatif. S'il est fourni, la script argand.js va tenter de placer le nom de l'angle près de l'arc de cercle au milieu de celui-ci.

Dessiner un texte

text(t, X, Y);

Affiche un texte à l'emplacement désigné par X, Y, les coordonnées à l'écran. Par défaut textBaseline est positionné sur Alphabetic. Le placement se fait donc à l'abscisse X et à la hauteur de cette ligne de base, c'est à dire la ligne d'écriture.

Style des tracés

thin(w); règle l'épaisseur du trait à w. Par défaut ce paramètre est 1. Si on veut des traits plus épais on fera exécuter thin(2), thin(3), etc.

dash(l); commande le pointillé et le plein. l = 0 signifie trait plein, sinon les traits sont pointillés. Plus l est grand plus la longueur de chaque bout de trait est grande et les espaces entre eux sont grands.

En interne

Le paradigme orienté objet employé dans ce script est celui de prototype et non de classe : un objet point (Pt) est une fonction et non une classe. L'ajout de paramètres se fait Pt.protype.param, où param est soit une valeur, soit une fonction.

La variable ctx rendue par getContex('2d') est globale.

J'y ai fourré les paramètres du dessin : la position de l'origine O horizontalement et verticalement, l'échelle du dessin et la taille de la police d'éctiture. On peut y accéder par, respectivement, ctx.X0, ctx.Y0, ctx.u et ctx.fontSize. (Cf. initCtx)

La fonction axis() dessine le repère : les axes et les vecteurs de base. Elle doit être explicitement appelée.

Les fonctions de tracé de segment de droite et de «flèche»(5)ont une double version : procédurale et orientée objet.

Exemples d'affichages

Notes

(1)

Argand Jean-Robert est un mathématicien suisse qui a eu l'idée de représenter les nombres complexes dans le plan.

Retour à Introduction

(2)

On peut aussi écrire le code de commandes à la volée dans une balise <script>.

Retour

(3)

La fonction text interprète des expressions comme e^x, a_1, z = ρe^{iθ}, f_{1,2} et affiche respectivement : $e^x$, $a_1$, $z=\rhoe^{iθ}$, $f_{1,2}$.

Elle interprète aussi les fractions y = ∖frac{}{2x² + 1} - 1, qu'elle affiche $y = \frac{1}{2x² + 1} - 1$.

La fonction Pt.label en hérite.

(4)

Dans l'API canvas, pour des raisons de rapidité d'accès à la mémoire, les coordonnées sont mesurées à partir du point haut gauche. L'axe des ordonnées a ainsi le sens opposé du sens habituel. Ça fait partie du charme de JS.

Retour

(5)

Dans l'enseignement de la géométrie ont gagnerait peut-être à appeler «flèche» un représentant d'un vecteur. On éviterait les confusions entre vecteur (libre) et un de ses représentant (lié), et par la suite la confusion entre famille de vecteurs liée et vecteur lié.




Réalisé avec Qlam - LGPL