Programmation objet et géométrie/CaRScripts et nombres complexes
Dans CaRScript un nombre complexe peut être vu comme un objet à deux paramètres, sa partie réelle x et sa partie imaginaire y ; voir à ce sujet le paragraphe correspondant.
Pour une meilleure intégration avec le logiciel CaRMetal, il est possible de créer un objet ayant pour unique paramètre un point de la figure.
Complexe (point)
modifierLa fonction complexe(p) est en fait un constructeur - à défaut d'une classe - des objets "complexe". C'est-à-dire que dès qu'un objet "complexe" est créé par la commande z = new complexe(unPoint), cet objet est doté de ses attributs et de ses méthodes.
function complexe(p){// p est un point
this.reelle = X(p);// X commande CaRScript pour obtenir l'abscisse d'un point
this.imaginaire = Y(p);// idem avec l'ordonnée
this.module = Math.sqrt(X(p)*X(p)+Y(p)*Y(p));
this.argument = Math.atan2(Y(p),X(p));
this.image = p; // l'image du complexe est le point p
// fonction pour afficher l'image du complexe dans CaRMetal
this.dessine = function(){
SetHide(p,false); // commande CaRMetal pour afficher le point
SetShowName(p,true)}; // et son nom
}
Point("A",2,-3);// commande CaRMetal pour créer un nouveau point A
var z = new complexe("A");// objet CaRScript
Println("Le nombre complexe z a pour image "+z.image); //affichage dans la console CaRScript
Println("Son argument est "+z.argument);// idem
Println("et son module "+z.module);// idem
z.dessine();// affichage du point dans CaRMetal
Affichage de l'affixe
modifierOn peut aller un peu plus loin en affichant l'affixe du nombre complexe sous la forme d'une chaîne de caractères.
En CaRScript, X(p) et Y(p) seront vus comme des chaînes de caractères, qu'il suffit d'assembler avec l'opérateur + : X(p) + "+" + Y(p) + "i"
Sous CaRMetal, l'affichage est dynamique et doit changer lorsque le point A se déplace sans pour cela faire appel au CaRScript ; pour le point A on écrira donc "%x(A)%+%y(A)%i" , les % indiquent qu'il faut remplacer x(A) et y(A) par leur valeurs. De plus, le véritable nom du point est inconnu, on écrira donc "%x(" + p + ")%+%y(" + p + ")%i", CaRScript se chargeant de remplacer p par son nom.
function complexe(p){//p est un point
this.reelle = X(p);
this.imaginaire = Y(p);
this.module = Math.sqrt(X(p)*X(p)+Y(p)*Y(p));
this.argument = Math.atan2(Y(p),X(p));
this.image = p;
// affixe du nombre complexe sous forme d'une chaîne de caractères
this.affixeCS = (Y(p)>=0) ? (X(p)+"+"+Y(p)+"i") : (X(p)+""+Y(p)+"i");// a+bi pour CaRScript
this.affixeCM = "(%x("+p+")%%+y("+p+")%i)" // a+bi pour CaRMetal
this.dessine = function(){
SetHide(p,false); //CaRMetal affiche le point
SetAlias(p,p+" "+this.affixeCM);
SetShowName(p,true)}; //CaRMetal affiche le nom du point suivi de son affixe
}
Point("A",2,-3);
var z = new complexe("A");
Println("Le nombre complexe z a pour image "+z.image);
Println("Son affixe est "+z.affixeCS);
Println("Son argument est "+z.argument);
Println("et son module : "+z.module);
z1.dessine();
Remarquer la façon dont JavaScript gère l'affichage du signe de Y(p) ; si Y(p)>=0, alors on ajoute un "+" devant sa valeur, sinon "".
Dans CaRMetal le test est inutile, il suffit d'insérer le "+" à l'intérieur des %%. Le logiciel évaluera lui-même s'il faut écrire "+" ou non.
Opérations sur les complexes
modifierDe même, les opérations sur les nombres complexes peuvent être prises en compte par CaRMetal en mixant syntaxe JavaScript et commandes CaRMetal.
function complexe(p){//p est un point
this.reelle = X(p);
this.imaginaire = Y(p);
this.module = Math.sqrt(X(p)*X(p)+Y(p)*Y(p));
this.argument = Math.atan2(Y(p),X(p));
this.image = p;
// affixe du nombre complexe sous forme d'une chaîne de caractères
this.affixeCS = (Y(p)>=0) ? (X(p)+"+"+Y(p)+"i") : (X(p)+""+Y(p)+"i");// a+bi pour CaRScript
this.affixeCM = "(%x("+p+")%%+y("+p+")%i)" // a+bi pour CaRMetal
this.dessine = function(){
SetHide(p,false); //CaRMetal affiche le point
SetAlias(p,p+" "+this.affixeCM);
SetShowName(p,true)}; //CaRMetal affiche le nom du point suivi de son affixe
}
function complexe_somme(a,b){//a et b sont des complexes
return new complexe(Point("x(" + a.image + ")+x(" + b.image + ")","y(" + a.image + ")+y(" + b.image+ ")"))
}
var z1 = new complexe(Point(3,2));z1.dessine();
var z2 = new complexe(Point(-2,1));z2.dessine();
var zsomme=complexe_somme(z1,z2);zsomme.dessine();
Trois points sont créés dans CaRMetal, avec leurs affixes. Le déplacement de l'un des deux premiers entraîne celui du troisième.
Remarque: On constate que ci-dessus, le module, l'argument, l'image etc. sont des propriétés de l'objet nombre complexe, alors que l'affichage est une méthode de cet objet. De même, l'opposé, le conjugué et l'inverse sont des méthodes de cet objet. Par contre, ce n'est pas le cas de la somme de deux complexes, parce que cette somme fait intervenir deux instances de l'objet et pas seulement une. Ci-dessus la somme est une fonction de deux complexes, qui renvoie un objet de même nature.
Pour aller plus loin
modifierChoix du point par l'utilisateur
modifierLe CaRScript peut être rendu plus interactif en demandant à l'utilisateur de désigner un point. La commande utilisée est InteractiveInput, couplée à try pour prévoir les cas où l'utilisateur clique sur autre chose.
try{var pt=InteractiveInput("Choisissez un point","Point");
z = new complexe(pt);
z.dessine();}
catch(erreur){Println("Erreur : " + erreur)}
Prototypage
modifierPosition du problème
modifierTout ceci fonctionne très bien, de façon dynamique et interactive. Mais la gestion de la mémoire n'est pas optimisée parce que, chaque fois qu'on crée un nouveau nombre complexe par new complexe(a,b), les méthodes de l'objet complexe sont stockées avec la nouvelle instance de celui-ci, ce qui, lorsqu'on crée un grand nombre de complexes, encombre inutilement la mémoire de JavaScript, surtout si on n'utilise pas toutes ces méthodes!
Solution
modifierPour remédier à ce (petit) problème, on peut définir les méthodes une fois pour toutes, dans la classe complexe. Ces méthodes seront alors héritées par l'objet au moment de son instanciation (ou création). Seulement voilà: JavaScript ne possède pas de classes... Alors on fait avec ce qu'on a, c'est-à-dire avec un prototype. Maintenant l'objet complexe est toujours défini mais seulement avec ses trois propriétés reelle, imaginaire et image. Les méthodes sont toutes définies dans le prototype du nombre complexe (qui est d'ailleurs un objet, et plus précisément une méthode de l'objet complexe !) comme on le voit ci-dessous:
function complexe(p){//p est un point
this.reelle = X(p);
this.imaginaire = Y(p);
this.image=p;
}
//l'objet complexe n'a maintenant que trois propriétés et pas de méthode
//début de la liste des méthodes, prototypées:
complexe.prototype.module =function(){
return Math.sqrt(this.reelle*this.reelle+this.imaginaire*this.imaginaire);
}
complexe.prototype.argument = function(){
return Math.atan2(this.imaginaire,this.reelle);
}
complexe.prototype.affixeCS = function(){
return (this.reelle>=0) ? (this.reelle+"+"+this.imaginaire+"i") : (this.reelle+""+this.imaginaire+"i");// a+bi pour CaRScript
}
complexe.prototype.affixeCM = function(){
return "(%x("+this.image+")%%+y("+this.image+")%i)" // a+bi pour CaRMetal
}
complexe.prototype.dessine = function(){
SetHide(this.image,false); //CaRMetal affiche le point
SetAlias(this,this+" "+this.affixeCM);
SetShowName(this,true); //CaRMetal affiche le nom du point suivi de son affixe
}
//fin de la liste des méthodes
function complexe_somme(a,b){//a et b sont des complexes
return new complexe(Point("x(" + a.image + ")+x(" + b.image + ")","y(" + a.image + ")+y(" + b.image+ ")"))
}
var z1 = new complexe(Point(3,2));z1.dessine();
var z2 = new complexe(Point(-2,1));z2.dessine();
var zsomme=complexe_somme(z1,z2);zsomme.dessine();
Une erreur qu'il est bon de faire
modifierSi on veut afficher (en version CarScript : CS) l'affixe de z1 ci-dessus, on est tenté d'écrire
Println(z1.affixeCS);
Le résultat, quoique faux, est tellement intéressant qu'il serait dommage de ne pas faire l'erreur! D'où vient-elle d'ailleurs, cette erreur? C'est que puisque z1 est une instance de l'objet complexe (donc un complexe), z1.affixeCS est une méthode de l'objet complexe, et quand on demande à JavaScript d'afficher une méthode, il affiche une méthode!
Pour réellement appeler la fonction, il faut signaler à JavaScript que c'est une fonction, à l'aide des parenthèses:
Println(z1.affixeCS());
Exercices
modifierMéthodes
modifierÉcrire en CaRScript, des méthodes pour les nombres complexes:
- Conjugué
- Opposé
- Inverse
Opérations
modifierÉcrire des fonctions admettant deux complexes en entrée et renvoyant un complexe (des opérations):
- Différence
- Produit
- Quotient