Nous allons cette semaine commencer par définir les premiers éléments nécessaires à la réalisation de notre projet : des vecteurs (au sens mathématique) de dimension quelconque (c.-à-d. non connue a priori lors de la programmation de la classe).
Je propose aussi, à celles et ceux qui le souhaitent, de commencer dès cette semaine par prendre en main l'environnement graphique de base que nous vous suggérons pour votre projet.
Notez bien que ce dernier point est pour le moment optionnel. Vous pouvez très bien choisir, en connaissance de cause, d'abordez ce point plus tard dans le semestre. L'interface graphique ne sera vraiment importante qu'en huitième semaine (voir l'échéancier du projet), mais beaucoup risquent d'être, à ce moment là, un peu submergés... (mauvaise organisation). Ce sera un sujet difficile pour celles et ceux qui envisagent de l'aborder. Ne tardez donc pas trop non plus...
En clair, si vous avez du temps, mieux vaut ne pas prendre de retard ! A bon entendeur...
Avant de commencer les exercices décrits dans
cette série, créez, si ce n'est pas déjà fait, le répertoire
~/myfiles/cpp/projet
et travaillez dans ce répertoire.
IMPORTANT ! Commencez déjà à songer
à vous organiser en binômes. Nous vous demanderons d'ici le 13 mars de
vous être officiellement inscrits par binômes (il n'y a
pas d'autre alternative).
Voir pour cela la page d'administration du projet.
Par ailleurs, nous vous conseillons de rapidement vous répartir les tâches au sein du binôme. Nous attendons que chaque membre d'un binôme réalise environ la moitié du travail.
Autre remarque: les consignes données ici (et chaque semaine) sont synchronisées avec le cours et ne sont pas contraignantes en soi, dans ce sens que, si vous voulez faire différemment, en particulier parce que vous avez déjà un peu d'avance sur le cours, vous pouvez (bien sûr : mon but n'a jamais été de contraindre/freiner mes étudiant(e)s). Ces données sont faites pour permettre à chacune et chacun qui suit le cours de pouvoir avancer à son rythme.
Rappelez vous cependant aussi le conseil: n'aborder le projet que quand vous pensez maîtriser suffisamment les concepts de la semaine en cours. Il ne serait pas bon/pas efficace de découvrir les notions du cours en faisant le projet.
Pour terminer avec les conseils et remarques préliminaires, n'oubliez de revenir de temps en temps consulter la page de description générale du projet et la page d'administration afin de situer votre travail courant par rapport au projet dans son ensemble et d'essayer ne de pas prendre trop de retard.
Vecteur
permettant
la manipulation de vecteurs
de dimension quelconque.
On s'intéresse ici à créer une classe représentant les vecteurs (au sens mathématique) en dimension quelconque (mais finie !). Cette notion va apparaître de façon répétée tout au long du projet. Elle permettra en effet de représenter les vecteurs d'état des objets, leur dérivée, mais aussi des paramètres géométriques (graphiques) comme une position, un axe, une normale, etc.
Nous allons donc représenter ces vecteurs n-D par une classe de base
que je vous propose de nommer
Vecteur
.
Nous coderons cette semaine une version simple que nous
améliorerons dans deux semaines.
NOTE : Vous êtes tout à fait libres
de définir, en plus des classes proposées en exercice, toutes celles
qui vous semblent pertinentes et utiles. Vous pouvez également changer
l'implémentation proposée. Dans tous les cas, expliquez clairement ce
que vous faites dans vos fichiers JOURNAL
,
REPONSES
et CONCEPTION
, et ajoutez des commentaires à votre code.
AUTRE REMARQUE : Si vous ne vous
sentez pas encore d'attaque pour faire de la programmation
modulaire et un Makefile
, mettez pour
l'instant tout dans un seul et même fichier Vecteur.cc
. On mettra les Makefile
s en pratique la semaine prochaine.
Sinon [c'est-à-dire si vous voyez de quoi je parle et
vous savez le faire], le mieux est de créer déjà quatre
fichiers : les fichiers Vecteur.h
et Vecteur.cc
, ainsi qu'un fichier de test de la classe
testVecteur.cc
et le Makefile
.
Dans tous les cas, il faudra le faire à un moment ou l'autre du projet (typiquement à partir de la semaine prochaine).
Définissez la classe Vecteur
représentant un
vecteur (mathématique)
de dimension quelconque, non connue a priori et
possédant les méthodes suivantes :
augmente()
permettant d'ajouter une
dimension au vecteur et une valeur pour cette dimension
(voir exemple ci-dessous) ;
set_coord()
permettant de modifier la valeur d'une
coordonnée du vecteur
(voir exemple ci-dessous) ;
affiche()
permettant l'affichage sur
«cout
» d'un objet Vecteur
;
pour cet affichage, je vous recommande de simplement lister les composantes les unes après les autres, séparées simplement par un blanc, comme ceci :
1.3 -4.5 7.8123
cela vous sera utile par la suite pour comparer les sorties de vos programmes aux résultats attendus donnés dans les énoncés ;
compare()
permettant de
tester l'égalité de
l'objet Vecteur
courant à un autre objet similaire (c.-à-d. aussi de type
Vecteur
) passé en paramètre.
Pour être égaux, deux vecteurs doivent
tout d'abord avoir la même dimension. Ensuite, s'ils sont de même dimension, ils doivent
avoir chacune de leurs coordonnées égales, à une certaine précision près (disons 1e-10
; cette valeur pourra être passée en paramètre optionnel).
Dans le fichier testVecteur.cc
(ou simplement
Vecteur.cc
si vous ne faites pas de
conception modulaire), créez trois vecteurs dont deux avec des
coordonnées identiques (mais naturellement dans des variables
différentes) et testez les méthodes écrites.
On pourrait par exemple avoir un code de test qui ressemble à (variantes possibles suivant vos choix d'implémentation.) :
Vecteur vect1; Vecteur vect2; Vecteur vect3; /* Cette partie * (1) pourrait être écrite autrement, par exemple avec des * manipulateurs (set_coord()) ; * (2) sera revue dans 2 semaines (constructeurs, surcharge des opérateurs). */ // v1 = (1.0, 2.0, -0.1) vect1.augmente(1.0); vect1.augmente(0.0); vect1.augmente(-0.1); vect1.set_coord(1, 2.0); // pour tester set_coord() // v2 = (2.6, 3.5, 4.1) vect2.augmente(2.6); vect2.augmente(3.5); vect2.augmente(4.1); vect3 = vect1; cout << "Vecteur 1 : "; vect1.affiche(); cout << endl; cout << "Vecteur 2 : "; vect2.affiche(); cout << endl; cout << "Le vecteur 1 est "; if (vect1.compare(vect2)) { cout << "égal au"; } else { cout << "différent du"; } cout << " vecteur 2," << endl << "et est "; if (not vect1.compare(vect3)) { cout << "différent du"; } else { cout << "égal au"; } cout << " vecteur 3." << endl;
[Question P1.1] Comment représentez-vous ces vecteurs ? Comment sont-ils organisés : quels attributs ? quelles méthodes ? quels droits d'accès ?
Réfléchissez à ces questions et répondez y dans votre
fichier REPONSES
(qui devra être rendu tout à la fin
du projet, cf la description
du projet).
Argumentez vos réponses.
Notez que je ne vous demande pas ici de me redonner votre code C++
mais de brièvement (et clairement) m'expliquer en français votre
réflexion et votre
démarche/conception.
Complétez maintenant la classe Vecteur
de sorte à
pouvoir effectuer les opérations suivantes :
Vecteur addition(Vecteur autre) const;
qui s'utiliserait comme ceci :
Vecteur a, b, c; // ... (affectation de a et b) c = a.addition(b);
Vecteur oppose() const;
qui s'utiliserait comme ceci :
Vecteur a, b; // ... (affectation de a) b = a.oppose();
Vecteur mult(double) const;
qui s'utiliserait comme ceci :
Vecteur a, b; double x; // ... (affectation de a et de x) b = a.mult(x);
double prod_scal(Vecteur autre) const;
qui s'utiliserait comme ceci :
Vecteur a, b; double x; // ... (affectation de a et de b) x = a.prod_scal(b);
Vecteur prod_vect(Vecteur) const;
norme()
et norme2()
calculant respectivement la norme et le carré de la norme du vecteur.
Note : c'est pour des raisons d'efficacité de calcul (évite le calcul de la racine carrée), que l'on décide ici d'implémenter une méthode qui retourne le carré de la norme. Utilisez la dans la suite de votre projet dans toutes les équations qui impliquent le carré de la norme (p.ex. des distances au carré).
une méthode unitaire()
qui retourne le vecteur
unitaire et de même sens (même fonctionnement que pour l'opposé décrit plus haut).
Pour toutes ces opérations, dans le cas où les deux vecteurs n'ont pas la même dimension, on pourra au choix :
v1.addition(v2)
ne
sera pas forcément la même chose que v2.addition(v1)
, par
exemple si v1
est de dimension 2 et v2
de dimension 3, v1.addition(v2)
serait de dimension 2 (projection de
v2
dans le plan) alors que v2.addition(v1)
serait de dimension 3 (plongement naturel de v1
dans l'espace
3D).
Par contre, en aucun cas les opérandes ne doivent être modifiés ! [malus]
[Question P1.2] Quel choix avez vous fait pour les opérations entre vecteurs de dimensions différentes ?
Répondez à cette question dans votre
fichier REPONSES
.
Ajoutez à votre programme testVecteur.cc
au moins les tests suivants :
(1.0, 2.0, -0.1) + (2.6, 3.5, 4.1) = (3.6, 5.5, 4.0)
(1.0, 2.0, -0.1)
est (-1.0, -2.0, 0.1)
3 * (1.0, 2.0, -0.1) = (3.0, 6.0, -0.3)
(1.0, 2.0, -0.1) * (2.6, 3.5, 4.1) = 9.19
(1.0, 2.0, -0.1) ^ (2.6, 3.5, 4.1) = (8.55, -4.36, -1.7)
||(1.0, 2.0, -0.1)||^2 = 5.01
||(2.6, 3.5, 4.1)||^2 = 35.82
Exemple de sortie possible :
Vecteur 1 : 1 2 -0.1 Vecteur 2 : 2.6 3.5 4.1 Le vecteur 1 est différent du vecteur 2, et est égal au vecteur 3. (1 2 -0.1) + (2.6 3.5 4.1) = (3.6 5.5 4.0) (2.6 3.5 4.1) + (1 2 -0.1) = (3.6 5.5 4.0) (1 2 -0.1) + (0 0 0) = (1 2 -0.1) (0 0 0) + (1 2 -0.1) = (1 2 -0.1) (1 2 -0.1) - (2.6 3.5 4.1) = (-1.6 -1.5 -4.2) (2.6 3.5 4.1) - (2.6 3.5 4.1) = (0 0 0) (2.6 3.5 4.1) + (1 2) = #... à vous de voir (1 2) + (2.6 3.5 4.1) = #... à vous de voir #... - (1 2 -0.1) = (-1 -2 0.1) - (2.6 3.5 4.1) + (1 2 -0.1) = (-1.6 -1.5 -4.2) 3 * (1 2 -0.1) = (3 6 -0.3) (1 2 -0.1) * (2.6 3.5 4.1) = 9.19 (2.6 3.5 4.1) * (1 2 -0.1) = 9.19 (1 2 -0.1) ^ (2.6 3.5 4.1) = (8.55 -4.36 -1.7) ||1 2 -0.1||^2 = 5.01 ||1 2 -0.1|| = 2.23830292855994 ||2.6 3.5 4.1||^2 = 35.82 ||2.6 3.5 4.1|| = 5.98498120297800
Je voudrais ici proposer, à celles et ceux qui le souhaitent, de commencer dès maintenant par prendre en main l'environnement graphique de base que nous vous suggérons d'utiliser pour votre projet.
Mais je tiens à insister ici que ce point est pour le moment optionnel. Vous pouvez très bien choisir, en connaissance de cause, d'aborder ce point plus tard dans le semestre. L'interface graphique ne sera vraiment importante qu'en neuvième semaine (voir l'échéancier du projet).
Je pense aussi que celles et ceux qui ont le plus de difficultés avec la programmation devraient plutôt à ce stade se focaliser sur les bases de la programmation objet et bien les acquérir (c.-à-d. faire des exercices) plutôt que de se plonger tout de suite dans cet aspect graphique qui sera tout de même plus superficiel (et puis avoir du beau graphisme ne sert à rien dans un projet qui ne tourne pas !)
Bref... ordonnez correctement vos priorités (cela fait partie d'une bonne gestion d'un projet).
Pour celles et ceux qui le souhaitent donc, je vous propose :
premièrement de vous initier à l'aspect graphique « temps réel » en suivant ce tutoriel
à développer ensuite vous-même votre propre exemple simple. Par exemple un cube en rotation autour d'une sphère... ...puis si vous avez encore du courage, en rotation sur lui-même.