Buts:
Doter les organes d'un réseau sanguin (qui permettra plus tard de les irriguer)
La méthode createBloodSystem
Le but maintenant est de faire en sorte que le réseau sanguin irriguant l'organe de chaque hamster soit automatiquement généré et que la vue interne en permette l'affichage. Pour ce faire, il faudra compléter la méthode Organ::createBloodSystem.Vous implémenterez un algorithme assurant un cheminement aléatoire des capillaires.
Le rôle de la méthode createBloodSystem est de marquer certaines cases de la grille comme faisant partie du système sanguin (au moyen de Organ::updateCellsLayer). Pour cela, les contraintes suivantes seront respectées :
Toutes les cases au centre de la grille, sur une largeur SIZE_ARTERY doivent être répertoriées comme faisant partie d'une artère (le CellsLayer correspondant doit pointer sur une BloodCell de type ARTERY). La largeur SIZE_ARTERY se calcule en nombres de cases. Vous prendrez comme valeur le maximum entre le 3% du nombres de cases par ligne et 1 (1 car on veut qu'il y ait au moins une case).
Les capillaires seront générés aléatoirement de part et d'autre de cette "artère".
Génération des points de départ des capillaires
Pour générer des points de départ de capillaires de part et d'autre de l'artère vous respecterez à nouveau des contraintes :
Une distance minimale getAppConfig().blood_capillary_min_dist devra séparer les points de départ de chaque capillaire.
Un capillaire ne pourra pas être généré en dessous de la coordonnée en y START_CREATION_FROM donnée par getAppConfig().blood_creation_start.
Il y aura au plus NB_CAPILLARY capillaires générés de chaque côté où NB_CAPILLARY vaut un tiers du nombre de lignes de la grille auquel on aura soustrait START_CREATION_FROM.
Pour que les capillaires n'aient pas des points de départ trop symétriques, vous ferez en dorte en sorte que chaque point de départ possible ait une chance sur trois d'être sélectionné comme point de départ effectif (vous pouvez utiliser la fonction uniform fournie dans Random.hpp).
Vous pouvez commencer par générer des points de départs de capillaires en les stockant dans des ensembles (un pour la droite et un pour la gauche). Une fois ces ensembles générés, il faudra faire croître un capillaire par point de départ. C'est ce à quoi nous nous intéressons maintenant.
Expansion des capillaires
Voici les contraintes qu'il faudra respecter pour faire "croître" un capillaire depuis un point de départ donné :
Un capillaire devra avoir une longueur maximale LENGTH_CAPILLARY (calculée selon la formule ad'hoc(nbCells_/2) - 4).
La longueur du capillaire correspondra au nombre de BloodCell (de type CAPILLARY) qui le constitue.
Depuis un point de départ donné, un capillaire aura une chance
sur 6 de continuer son
expansion vers le haut, une chance sur 6 de
continuer vers le bas. Dans le reste des cas l'expansion se fera dans
la direction courante (gauche ou droite sans monter ni
descendre). L'expansion se fera selon ces modalités jusqu'à ce que le
capillaire ait atteint la longueur voulue ou qu'il ne soit plus possible de progresser (en prenant à
chaque fois la nouvelle case répertoriée comme une cellules sanguine comme point de départ).
Concrètement, supposons que le point de départ soit la case [4][4] et que nous souhaitions faire croître le
capillaire vers la droite. Il y aura une chance sur 6 de choisir de
faire l'expansion vers [3][4], une chance sur 6 vers [5][4]. Dans le
reste des cas, l'expansion se fera vers [4][5] (avec la cconvention [ligne][colonne]). Une fois la case
choisie, il faudra y créer une BloodCell de type CAPILLARY et prendre
cette case comme nouveau point de départ. On recommence jusqu'à ce que
la longueur voulue soit atteinte ou qu'il ne soit plus possible de progresser.
On ne pourra pas créer deux BloodCell à la même position. Si depuis un point de départ donné on n'arrive à trouver aucune case non occupée faisant encore partie de la vue, on arrêtera l'expansion même si la longueur maximale n'est pas atteinte;
Vous coderez la méthode createBloodSystem en vous aidant :
D'une méthode virtuelle Organ::generateArtery permettant de générer l'artère (vous choisirez ses paramètres et type de retour à votre guise).
D'une méthode virtuelle protégée Organ::generateCapillaryOneStep(CellCoord ¤t_position , const CellCoord& dir, int& nbCells, const int& maxLength) en charge de faire croître un capillaire d'une seule case dans la direction dir. currentPosition sert de point de départ, et doit à la fin de l'exécution de la méthode, contenir les coordoonées de la case qu'occupe le capillaire suite à l'expansion (ce qui pourra servir de point de départ à d'autre expansions). nbCells contient la longueur du capillaire (avant et après l'expansion), et maxLength la longueur maximale du capillaire. Ainsi, si generateCapillaryOneStep est appelée avec un nbCells ayant la même valeur que maxLength, elle ne fera rien et currentPosition et nbCells ne changeront pas de valeur. Dans le cas où le capillaire n'a pas trouvé de place pour croître, currentPosition et nbCells ne changeront pas de valeur non plus, même si la longueur maximale n'est pas encore atteinte. Enfin, si generateCapillaryOneStep a réussi à trouvé une case voisine où croître, currentPosition contiendra les coordonnnées de cette case et nbCells sera augmentée d'une unité.
D'une méthode virtuelle protégée Organ::generateCapillaryFromPosition(CellCoord ¤t_position , CellCoord dir) utilisant la méthode précédente pour générer un capillaire entier.
Vous doterez enfin la méthode createBloodSystem d'un paramètre booléen generateCapillaries valant true comme valeur par défaut. Si ce paramètre vaut false, seule l'artère est générée, sinon c'est l'ensemble du réseau sanguin.
Vous êtes libre de coder les algorithmes comme bon vous semble et en utilisant les structures de données qui vous semblent éventuellement utiles. Ils seront tenus de respecter les contraintes précitées. Vous pouvez créer toute méthode/classe additionnelle vous semblant nécessaire.
Test 23 : Réseau sanguin
Pour tester la génération de l'artère ainsi que votre méthode generateCapillaryOneStep, vous disposer du test graphique Tests/GraphicalTests/BloodSystemTest.cpp (cible bloodSystemTest à décommenter au préalable).
Les points de départs des capillaires peuvent être sélectionné à la souris. Les touches '6' (pour générer vers la droite) et '5' (pour la gauche) permettent d'invoquer generateCapillaryOneStep (une fois à chaque appui de touche) depuis le point choisi avec le curseur. La touche '0' (pas celle du pavé numérique), permet de quitter un capillaire pour en faire «pousser» un nouveau.
Si les touches du pavé numérique semblent ne pas répondre (pour cause de configuration de clavier sur vos portables par exemple ), il est possible de les remplacer par des lettres à choix. Mais attention:
Il est important de choisir des lettres autres que celles utilisée par Application
Vous devez documenter ces modifications dans votre code.
Le comportement de ce test devrait ressembler à ceci:
[Video : croissance des capillaires]
Contrôlez que les touches n'ont plus d'effet une fois la longueur maximale atteinte. Changer les valeurs maximales dans le test pour vérifier que votre la croissance s'arrête lorsque les limites de la vue interne sont atteintes. Contrôler aussi que l'artère bloque l'expansion: un capillaire ne peut pas traverser l'artère pour se retrouver de l'autre côté.
Lancez également la cible application, vous devriez pouvoir basculer sur des vues internes ressemblant à l'exemple donné plus haut :
Contrôlez visuellement que votre algorithme de création du système sanguin respecte bien les contraintes qui vous ont été imposées.
Faites le test pour différents hamsters: un système sanguin différent devrait s'afficher pour chacuun et chaque hamster doit garder le même système sanguin à chaque fois que l'on retourne sur sa vue interne.
"Jouez" sur les paramètres de simulation pour changer par exemple le point de départ des capillaires, la distance minimale entre deux capillaires, ou les caractéristiques de la grille pour voir si votre programme est robuste aux modifications de paramètres et aux changements d'échelle.