Projet : étape 7 (semaine 10 du semestre)

Buts

Nous allons cette semaine donner un aspect un peu plus visuel à notre projet. Concrètement, nous allons fournir un affichage graphique 3D de nos objets.

P11 - Révision des Particule

Nous souhaitons ici faire que les particules de notre système soient de différente nature. On peut imaginer différents types de particules, ayant par exemple différents types d'interactions. C'est ce que nous allons implémenter ici, mais on pourrait aussi imaginer toutes autres sortes de variations des types de particules.

Il faut bien comprendre la différence entre

Le but premier de ce projet étant de vous faire concrètement travailler les différents aspects de la POO, je vous oblige ici à utiliser le polymorphisme et plus particulièrement le « polymorphisme multiple » (« multiple dispatch ») à l'aide du « visitor pattern » tel que nous avons déjà pu le rencontrer avec les Dessinable et les SupportADessin.

Concrètement, je vous demande de renommer votre classe Particule en ParticuleNeige et de faire une classe abstraite Particule (voir ci-dessous), dont on créera différentes sous-classes (concrètes) pour représenter différents types de particules.

Dans cette première étape de la démarche, réfléchissez bien à ce que vous voulez « remonter » de ParticuleNeige dans Particule, et ce que vous voulez garder de spécifique dans ParticuleNeige. Vous êtes assez libres ici; c'est votre conception, votre envie d'abstraire, plus ou moins, vos particules, mais lisez peut être la suite jusqu'au bout afin d'avoir la vision complète avant de prendre vos décisions.

Pour aller plus loin, nous allons modéliser les interactions avec deux concepts: ce qui subit l'interaction (les Particule dans notre cas) et ce qui peut faire une interaction sur les Particule. Nous allons appeler cette dernière classe des Agent. (Vous pouvez changer ce nom si vous en trouvez un meilleur.)

Puisque les Particule peuvent interagir sur d'autres Particule, elles sont aussi des Agent. Mais tous les Agent ne sont pas des Particule: par exemple (le seul dans ce projet) les Obstacle sont des Agent mais ne sont pas des Particule...

Interlude: si ce qui précède, ou ce qui suit, est un peu trop compliqué/abstrait, j'ai fait un exemple similaire plus simple dans ce fichier. Je vous laisse faire le parallèle entre les deux.

La classe Agent est une classe abstraite qui aura autant de méthodes virtuelles (pures) que de Particule concrètes avec lesquelles interagir. Par exemple si vous avez des ParticuleNeige et des ParticuleRoche, alors la classe Agent aura (référence ou pointeur suivant votre choix) :

  virtual void opere_sur(ParticuleNeige&) = 0;
  virtual void opere_sur(ParticuleRoche&) = 0;

que toute sous-classe concrète d'Agent devra, bien sûr, redéfinir (« override »).
C'est dans ces redéfinitions qu'aura lieu toute la richesse, tout l'intérêt de la démarche :
ParticuleNeige::opere_sur(ParticuleNeige&) sera (pourra être) différent de ParticuleNeige::opere_sur(ParticuleRoche&) ;
ParticuleRoche::opere_sur(ParticuleNeige&) sera (pourra être) différent de ParticuleNeige::opere_sur(ParticuleRoche&) (dissymétrie des interactions) ;
Plan::opere_sur(ParticuleNeige&) sera (pourra être) différent de Plan::opere_sur(ParticuleRoche&) et aussi différent de Cylindre::opere_sur(ParticuleNeige&) et de Cylindre::opere_sur(ParticuleRoche&), etc.

Évidemment, si plusieurs de ces interactions ne sont pas différentes, on ne fera SURTOUT pas de copié-collé, mais, comme d'habitude, on définira une méthode bien choisie, au bon endroit, dont on fera un usage pertinent...

Note : opere_sur() peut tout à fait être const suivant votre conception (est-ce que le fait que l'agent opere_sur() autre chose modifie cet agent ? P.ex. si une particule opère sur une autre particule, est-elle elle-même modifiée ?).

Au niveau des Particule générales, toutes les anciennes méthodes

virtual void ajouteForce(Grain* autre) = 0;
virtual void ajouteForce(Obstacle* autre) = 0;

disparaissent et sont remplacées par une seule et unique méthode virtuelle pure (référence ou pointeur suivant votre choix) :

virtual void ajouteForce(Agent& autre) = 0;

Note: Agent peut être const suivant votre conception (est-ce que opere_sur() modifie l'agent ?).

Ensuite, dans chaque sous-classe spécifique (c.-à-d. concrète) de Particule, on aura EXACTEMENT ceci :

virtual void ajouteForce(Agent& autre) override { autre.opere_sur(*this); }

ATTENTION ICI ! Pour des raisons techniques dépassant le cadre de ce cours, il ne faut pas que cette méthode soit définie dans la classe Particule puis héritée, mais bien que ce même bout de code soit recopié à l'identique (copié-collé, une fois n'est pas coutume !) dans chaque sous-classe de Particule (masquage).
[ C'est le prix à payer du fait qu'en C++ il n'y a pas de ce qu'on appelle « double dispatch ». ]

Répercutez ensuite les modifications nécessaires (s'il y en a) aux différentes classes déjà créées jusqu'ici.

Voilà pour les principes...
Réfléchissez à tout ça et commencez par une modification minimale de votre code : transformez le code que vous avez, en un modèle strictement équivalent (qui fait les mêmes simulations, donne les mêmes résultats de test) que votre modèle précédent. Au final, il n'y a pas beaucoup de code à changer, juste deux classes en plus et déplacer quelques lignes ici ou là. Pour résumer :

Vérifiez bien, à l'aide de vos tests, que vous n'avez rien cassé.

Sauvegardez bien cette étape du projet (tout le répertoire), soit en exerciceP11-revisiteP9, exerciceP11-revisiteP10 suivant la version dont vous partez. Elle devra faire partie du rendu final.

Pour terminer, créez au moins une autre sous-classe de la classe Particule, par exemple ParticuleRoche et amusez vous à changer les interactions (p.ex. ne plus du tout utiliser le modèle de «Lennard-Jones»).
C'est là maintenant l'essentiel: vous avez développé un cadre assez riche, profitez-en à votre guise ! (Mais toujours dans des limites de temps raisonnables !!)

Sauvegardez bien cette étape du projet (tout le répertoire), soit en exerciceP11-v2. Elle devra faire partie du rendu final.


Dernière mise à jour le 13 février 2026
Last modified: Fri Feb 13, 2026