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)

modifier

La 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

modifier

On 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

modifier

De 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

modifier

Choix du point par l'utilisateur

modifier

Le 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

modifier

Position du problème

modifier

Tout 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

modifier

Pour 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

modifier

Si 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

modifier

Mé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