// This file is part of the Herezh++ application. // // The finite element software Herezh++ is dedicated to the field // of mechanics for large transformations of solid structures. // It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) // INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . // // Herezh++ is distributed under GPL 3 license ou ultérieure. // // Copyright (C) 1997-2021 Université Bretagne Sud (France) // AUTHOR : Gérard Rio // E-MAIL : gerardrio56@free.fr // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // For more information, please consult: . #include "Visualisation.h" #include #include // les ordres possibles #include "Mail_initiale_vrml.h" #include "Deformees_vrml.h" #include "Fin_vrml.h" #include "Visuali_vrml.h" #include "Increment_vrml.h" #include "ChoixDesMaillages_vrml.h" #include "Animation_vrml.h" #include "Isovaleurs_vrml.h" #include "Banniere.h" // CONSTRUCTEURS : Visualisation::Visualisation () // par defaut { cout << "\n ce constructeur ne doit pas etre utilise !! \n" ; cout << " Visualisation::Visualisation () // par defaut " << endl; }; // le bon constructeur Visualisation::Visualisation (UtilLecture* ent) : lesValVecPropres(),ordre_possible(),entreePrinc(ent) ,fin_o(NULL),visuali(NULL),choix_inc(NULL) ,list_incre(),list_balaie(NULL),boite() ,animation(false) ,activ_sort_vrml(false) { // définition des ordres possibles list ::iterator it; OrdreVisu* ptordre; // maillage initial ptordre = new Mail_initiale_vrml(); ordre_possible.push_back(ptordre); // Choix de la visualisation des isovaleurs //NB: il faut que l'isovaleur soit avant la déformée !! pour que la déformée puisse // utiliser les couleurs définis dans isovaleurs ptordre = new Isovaleurs_vrml(); ordre_possible.push_back(ptordre); choix_isovaleur = ptordre; // récup de l'ordre // déformée ptordre = new Deformees_vrml(); ordre_possible.push_back(ptordre); ptdeformee = ptordre; // récup de l'ordre // Choix du ou des incréments à visualiser. ptordre = new Increment_vrml(); ordre_possible.push_back(ptordre); choix_inc = ptordre; // récup de l'ordre // Choix du ou des maillages à visualiser. ptordre = new ChoixDesMaillages_vrml(); ordre_possible.push_back(ptordre); choix_mail = ptordre; // récup de l'ordre // gestion de l'animation si nécessaire (doit être à la fin) dans la liste. // juste avant les 2 arrêts possibles ptordre = new Animation_vrml(); ordre_possible.push_back(ptordre); anim = ptordre; // récup de l'ordre // transmission de la position à la déformée et à l'animation qui en ont besoin pour les couleurs ((Deformees_vrml*) ptdeformee)->Jonction_isovaleur((Isovaleurs_vrml*)choix_isovaleur); ((Animation_vrml*) anim)->Jonction_isovaleur((Isovaleurs_vrml*)choix_isovaleur); // transmission du choix des maillages à l'animation et à la déformée qui en ont besoin ((Animation_vrml*) anim)->Jonction_ChoixDesMaillages((ChoixDesMaillages_vrml*)choix_mail); ((Deformees_vrml*) ptdeformee)->Jonction_ChoixDesMaillages((ChoixDesMaillages_vrml*)choix_mail); // transmission de la deformée à l'animation qui en a besoin ((Animation_vrml*) anim)->Jonction_Deformees_vrml((Deformees_vrml*)ptdeformee); // ordre de visualisation ptordre = new Visuali_vrml(); ordre_possible.push_back(ptordre); visuali = ptordre; // récup de l'ordre // fin de la visualisation ptordre = new Fin_vrml(); ordre_possible.push_back(ptordre); fin_o = ptordre; // récup de l'ordre fin /* string ordre,comment; comment = "évolution force/déplacement : "; ordre = "evolFD"; commentaires_ordres.push_back(comment); ordre_possible.push_back(ordre);*/ }; // DESTRUCTEUR : Visualisation::~Visualisation () { // destruction de la liste d'ordre list ::iterator il,ifin; ifin = ordre_possible.end(); for (il=ordre_possible.begin();il!=ifin;il++) delete (*il); }; // METHODES PUBLIQUES : // affichage des différentes possibilités (ordres possibles) // ramène un numéro qui renseigne le programme appelant // =-1 : signifie que l'on veut stopper la visualisation // = 0 : signifie que l'on demande la visualisation effective int Visualisation::OrdresPossible() { // si l'on passe ici cela signifie que la visualisation vrml est active activ_sort_vrml= true; string reponse; // réponse utilisateur // on commence par inactiver les ordres de visualisation et de fin fin_o->Inactive_ordre(); visuali->Inactive_ordre(); // on boucle while ( !(fin_o->Actif()) && !(visuali->Actif())) { while ((reponse.length () == 0) || (Existe(reponse)==NULL)) { // affichage des options possibles Affiche_options(); // lecture de la commande voulu reponse = lect_chaine(); OrdreVisu* ord = Existe(reponse); if (ord == NULL) { // dans le cas d'un ordre non connu cout << "\n ordre non connu !!, verifiez votre demande \n"; } else // demande d'activation de l'ordre ord->ChoixOrdre(); } // on vide la réponse pour une autre boucle éventuelle reponse =""; } // récupération de la liste des incréments à visualiser list_balaie = &((Increment_vrml*)choix_inc)->List_choisit(); // def du retour if (fin_o->Actif()) return -1; else return 0; }; // information de l'instance de la liste d'incrément disponible pour la visualisation void Visualisation::List_increment_disponible(list & list_incr) { list_incre = list_incr; // stockage interne // puis passage à l'instance d'ordre qui gère les incréments ((Increment_vrml*)choix_inc)->Init_list_inc(list_incre); } ; // indique le choix de la liste d'incrément à utiliser pour l'initialisation // des fonctions d'initialisation // si interactif = -1 : initialisation à 0 et au dernier incrément par défaut // si interactif = 0 : le choix de la liste s'effectue via une lecture dans le fichier de commande // si interactif = 1 : initialisation interactive const list & Visualisation::List_balaie_init(int interactif) { switch (interactif) { case -1 : // cas où l'on impose 0 et le dernier incrément { ((Increment_vrml*)choix_inc)->Init_list_inc_DebuEtFin(); // récupération de la liste des incréments à visualiser // c'est ici que list_balaie est initialisée et non dans OrdresPossibles qui peut ne pas être appelé list_balaie = &((Increment_vrml*)choix_inc)->List_choisit(); return *list_balaie; break; } case 0 : // cas d'une lecture via le fichier de commande { ((Increment_vrml*)choix_inc)->Lecture_parametres_OrdreVisu(*entreePrinc); // récupération de la liste des incréments à visualiser list_balaie = &((Increment_vrml*)choix_inc)->List_choisit(); return *list_balaie; break; } case 1 : // cas interactif {// cas interactif // choix entre tous les incréments : option par défaut // ou une liste plus restreinte d'incrément, utile lorsqu'il y a vraiment // beaucoup d'incrément bool choix_valide = false; string rep; while (!choix_valide) { cout << "\n === choix des increments utilises pour l'initialisation de la visualisation ====" << "\n option par defaut : tous les increments (rep 1)" << "\n choix d'un nombre plus petit d'increment (rep 2)"; cout << "\n reponse ? "; rep = lect_return_defaut(true,"1");cout << "\n"; if ((rep == "1") || (rep == "2")) // cas d'un choix valide choix_valide = true; else cout << "\n la reponse : " << rep << " n'est pas utilisable, recommencez !"; } // exécution if (rep == "1") { // cas de tous les incréments ((Increment_vrml*)choix_inc)->Impos_list(list_incre); // récupération de la liste des incréments à visualiser list_balaie = &((Increment_vrml*)choix_inc)->List_choisit(); return *list_balaie; } else if (rep == "2") // cas d'un choix d'incrément, appel du choix d'incrément { ((Increment_vrml*)choix_inc)->ChoixOrdre(); // récupération de la liste des incréments à visualiser list_balaie = &((Increment_vrml*)choix_inc)->List_choisit(); return *list_balaie; } break; } } //-- fin du switch // pour éviter un warning, car normalement on ne passe jamais ici return list_incre; }; // impose une liste d'incrément à utiliser void Visualisation::List_balaie_init(const list & ) //void Visualisation::List_balaie_init(const list & list_init) { ((Increment_vrml*)choix_inc)->Impos_list(list_incre); // récupération de la liste des incréments à visualiser list_balaie = &((Increment_vrml*)choix_inc)->List_choisit(); }; // information de l'instance du nombre de maillages disponibles pour la visualisation // par défaut tous les maillages seront visualisés, ceci est descidé aussi ici void Visualisation::List_maillage_disponible(int nombre_maillage_dispo) { nb_maillage_dispo = nombre_maillage_dispo; // on défini la liste de tous les maillages par défaut ((ChoixDesMaillages_vrml*)choix_mail)->Init_nb_maill(nb_maillage_dispo); }; // initialisation des ordres disponibles // par exemple pour les isovaleurs on définit la liste des isovaleurs disponibles et les extrémas void Visualisation::Initialisation(ParaGlob * paraGlob,LesMaillages * lesMaillages ,LesReferences* lesReferences ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts ,Resultats* resultats,OrdreVisu::EnumTypeIncre type_incre,int incre ,const map < string, const double * , std::less >& listeVarGlob ,const List_io < TypeQuelconque >& listeVecGlob ,bool fil_calcul) { // on passe en revue l'ensemble des ordres possibles list ::iterator s_or,s_or_fin; s_or_fin = ordre_possible.end(); for (s_or = ordre_possible.begin();s_or != s_or_fin; s_or++) (*s_or)->Initialisation(paraGlob,lesMaillages,lesReferences ,lesLoisDeComp ,diversStockage ,charge,lesCondLim,lesContacts,resultats,type_incre,incre,listeVarGlob ,listeVecGlob,fil_calcul); }; // méthode principale pour activer la visualisation void Visualisation::Visu(ParaGlob * paraGlob,LesMaillages * lesMaillages,LesReferences* lesReferences ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts ,Resultats* resultats,OrdreVisu::EnumTypeIncre type_incre,int incre ,const map < string, const double * , std::less >& listeVarGlob ,const List_io < TypeQuelconque >& listeVecGlob ) { // récup de la liste de maillage const list & li_mail = ((ChoixDesMaillages_vrml*)choix_mail)->List_choisit(); list ::const_iterator ik,ikfin; ikfin = li_mail.end(); // on définit un tableau des maillages à sortir, plus pratique pour les itérations // dans les routines internes (et plus rapide) Tableau tab_mail(li_mail.size()); int iidd = 1; for (ik= li_mail.begin();ik!=ikfin;ik++,iidd++) tab_mail(iidd)=*ik; // initialisation de l'animation : // s'il y a plus d'un seul incrément différent de zéro on est en animation if (type_incre==OrdreVisu::PREMIER_INCRE) { list ::const_iterator il,ilfin=list_balaie->end(); if (*(list_balaie->begin())==0) // cas du premier incrément = maillage initial if(list_balaie->size() > 2) animation = true; else animation = false; else // il n'y a que des incrément différent de l'initial if(list_balaie->size() > 1) animation = true; else animation = false; } // ici on passe en revue l'ensemble des ordres possibles list ::iterator s_or,s_or_fin; s_or_fin = ordre_possible.end(); // s'il n'y a qu'un seul incrément à visualisé on le signale bool unseul_incre = true; if (list_balaie->size() > 1) unseul_incre = false; // s'il s'agit du premier incrément visualisé et que l'on est en animation // on le signale for (s_or = ordre_possible.begin();s_or != s_or_fin; s_or++) { if ((*s_or) != anim) // l'animation n'est appelé qu'à la fin (*s_or)->ExeOrdre(paraGlob,tab_mail,lesMaillages,unseul_incre,lesReferences ,lesLoisDeComp ,diversStockage ,charge,lesCondLim,lesContacts,resultats,*entreePrinc ,type_incre,incre,animation,listeVarGlob,listeVecGlob); }; // cas de l'ordre d'animation qui est appelé à la fin // au dernier incrément // le numéro de maillage n'a pas d'importance // if ((*(--(list_balaie->end())) == incre) && animation) if ((type_incre==OrdreVisu::DERNIER_INCRE) && animation) { // dans le cas où l'on doit faire de l'animation et que celle-ci // n'est pas activée on l'active et la renseigne if (!(anim->Actif())) anim->ChoixOrdre(); anim->ExeOrdre(paraGlob,1,lesMaillages,unseul_incre,lesReferences ,lesLoisDeComp ,diversStockage ,charge,lesCondLim,lesContacts,resultats,*entreePrinc ,type_incre,incre,animation,listeVarGlob,listeVecGlob); }; // calcul de la boite maxi d'encombrement // utilisé à la fin pour définir les # points de vue // on balaie les différents maillages for (ik= li_mail.begin();ik!=ikfin;ik++) { int numMail = *ik; // pour chaque maillage on définit la boite maxi Tableau boite_inter = lesMaillages->Taille_boite(numMail); // calcul de la plus grande boite Calcul_maxi_boite ( boite_inter); }; // on vide le buffer au cas ou entreePrinc->Sort_princ_vrml() << endl; entreePrinc->Sort_princ_vrml() << flush; }; // == définition des paramètres de visualisation // titre, navigation, éclairage // et initialisation des paramètres de la classe void Visualisation::Contexte_debut_visualisation() {ostream &sort = entreePrinc->Sort_princ_vrml(); // écriture de l'entête sort << "#VRML V2.0 utf8\n"; // le titre sort << "WorldInfo {\n" << "title \" Visualisation elements finis : Herezh++ V" << ParaGlob::NbVersion() << " \" \n" // << "info [ \"Copyright (c) 1997-2003, Gérard Rio (gerard.rio@univ-ubs.fr) http://www-lg2m.univ-ubs.fr\" ]\n" << "info [ \" "; sort << Banniere::CopiPirate() << " \" ]\n" << "}\n"; sort << "NavigationInfo {\n" << "type [ \"EXAMINE\", \"ANY\" ] \n" << "headlight TRUE \n" << "}\n"; animation = false; ((Animation_vrml*)anim)->Init_liste_coordonnee(); }; // (points de vue) et enchainement si nécessaire void Visualisation::Contexte_fin_visualisation() {// définition des points de vue avec l'angle adoc DefinitionViewPoint(); }; // lecture des paramètres de l'ordre dans un flux void Visualisation::Lecture_parametres_OrdreVisu(UtilLecture & entreePrinc) { // si dans le flot il existe l'identificateur adoc on lit sinon on passe if (strstr(entreePrinc.tablcarCVisu,"debut_visualisation_vrml")!=NULL) {// essaie de lecture try { string nom; (*entreePrinc.entCVisu) >> nom ; if (nom != "debut_visualisation_vrml") { cout << "\n Erreur en lecture de la visualisation vrml a partir d'un fichier .CVisu," << " le premier enregistrement doit etre le mot clef: debut_visualisation_vrml " << " la visualisation vrml n'est pas validee !! "; } else { // on valide la visualisation activ_sort_vrml=true; entreePrinc.NouvelleDonneeCVisu(); // on passe en revue tous les ordres disponibles while (strstr(entreePrinc.tablcarCVisu,"fin_visualisation_vrml")==NULL) { list ::iterator s_or,s_or_fin; s_or_fin = ordre_possible.end(); for (s_or = ordre_possible.begin();s_or != s_or_fin; s_or++) (*s_or)->Lecture_parametres_OrdreVisu(entreePrinc); } } } catch (ErrSortieFinale) // cas d'une direction voulue vers la sortie // on relance l'interuption pour le niveau supérieur { ErrSortieFinale toto; throw (toto); } catch (...)// erreur de lecture { cout << "\n Erreur en lecture de la visualisation vrml a partir d'un fichier .CVisu," << " la visualisation vrml n'est pas validee !! "; activ_sort_vrml=false; if (ParaGlob::NiveauImpression() >= 4) cout << "\n Visualisation::Lecture_parametres_OrdreVisu(.."; } // on passe à un nouvel enregistrement entreePrinc.NouvelleDonneeCVisu(); } }; // écriture des paramètres de l'ordre dans un flux void Visualisation::Ecriture_parametres_OrdreVisu(UtilLecture & entreePrinc) { // récup du flot ostream & sort = (*(entreePrinc.Sort_CommandeVisu())); // on s'occupe des ordres spécifiques à la visualisation vrml // il n'y a écriture que si la visualisation vrml est active if(activ_sort_vrml) {// tout d'abord l'activation du type vrml // on commente le fonctionnement sort << "\n # ================================================================================="; sort << "\n # || ***** demande d'une visualisation vrml: ***** || " << "\n # =================================================================================" << "\n # un mot cle de debut (debut_visualisation_vrml)" << "\n # un mot cle de fin ( fin_visualisation_vrml) apres tous les ordres particuliers" << "\n # la seule presence du premier mots cle suffit a activer la visualisation vrml" << "\n # la presence du second permet une meilleur lisibilite du fichier, mais n'est pas indispensable" ; // on sort les mots clés d'activation du type vrml sort << "\n debut_visualisation_vrml \n" ; // on passe en revue tous les ordres disponibles list ::iterator s_or,s_or_fin; s_or_fin = ordre_possible.end(); for (s_or = ordre_possible.begin();s_or != s_or_fin; s_or++) (*s_or)->Ecriture_parametres_OrdreVisu(entreePrinc); // fin de l'activation vrml sort << "\n fin_visualisation_vrml" << "\n # =================================================================================" << "\n # || fin de la visualisation vrml || " << "\n # ================================================================================= \n \n"; } }; // écriture de l'entête du fichier de commande de visualisation void Visualisation::EcritDebut_fichier_OrdreVisu(UtilLecture & entreePrinc) { // récup du flot ostream & sort = (*(entreePrinc.Sort_CommandeVisu())); // on écrit tout d'abord l'entête générale du fichier commande sort << "###############################################################################################\n" << "# Fichier de commande pour la visualisation elements finis #\n" << "# Herezh++ V" << ParaGlob::NbVersion() << " #\n" << "# " << Banniere::CopiPirate() << " #\n" << "# http://www-lg2m.univ-ubs.fr #\n" << "###############################################################################################\n" << "\n\n"; // on écrit le mot clé de début du fichier commande sort << "\n debut_fichier_commande_visu # >>>>>> le mot cle: " << "\n # permet au programme de se positionner au debut du fichier, il est indispensable \n\n "; // on écrit les incréments a balayer // ((Increment_vrml*)choix_inc)->Ecriture_parametres_OrdreVisu(entreePrinc); }; // écriture de la fin du fichier de commande de visualisation void Visualisation::EcritFin_fichier_OrdreVisu(UtilLecture & entreePrinc) { // récup du flot ostream & sort = (*(entreePrinc.Sort_CommandeVisu())); // on écrit le mot clé de fin du fichier commande sort << "\n\n\n" << "\n fin_fichier_commande_visu # <<<<<< le mot cle permet" << "\n # l'arret de la lecture des commandes, apres ce mot cle, aucune commande n'est lu, de plus " << "\n # sans le mot cle de fin de fichier, le fichier n'est pas valide \n\n " << "###############################################################################################\n" << "\n\n"; }; //============================== méthodes privées ===================== // test si la réponse fait partie des ordres possibles // si l'on trouve un ordre ok on ramène un pointeur sur l'ordre // sinon on ramène un pointeur null OrdreVisu* Visualisation::Existe(string& reponse) { // on passe en revue la liste d'ordre list ::iterator s_or,s_or_fin; s_or_fin = ordre_possible.end(); for (s_or = ordre_possible.begin();s_or != s_or_fin; s_or++) if ((*s_or)->OrdreVrai(reponse)) return (*s_or); // cas d'un ordre correcte return NULL; // pas d'ordre correcte trouvé }; // affichage des options possibles void Visualisation::Affiche_options() { // écriture d'une ligne de transition cout << setw(60) << setfill('-') << "\n " << setfill(' '); list ::iterator s_or,s_or_fin; s_or_fin = ordre_possible.end(); for (s_or = ordre_possible.begin();s_or != s_or_fin; s_or++) (*s_or)->Affiche_ordre(); cout << "\n reponse ? "; }; // calcul de la plus grande boite void Visualisation::Calcul_maxi_boite (Tableau & boite_inter) { // tout d'abord le cas particulier de la boite non initialisé if (boite.Taille() == 0) { boite = boite_inter; return; } // cas d'une boite déjà existante // différent tests int dima = boite(1).Taille(); for (int it=1;it<=dima;it++) { if (boite(1)(it) > boite_inter(1)(it)) boite(1)(it) = boite_inter(1)(it); if (boite(2)(it) < boite_inter(2)(it)) boite(2)(it) = boite_inter(2)(it); } }; // définition des points de vue avec l'angle adoc void Visualisation::DefinitionViewPoint() { // l'objectif est de positionner les viewpoints relativement à la boite Vecteur diag = boite(2)-boite(1); double lmax = diag.Norme(); Vecteur centre = (boite(1) + boite(2))/2.; // si la dimension est différente de 3 on force à 3 // d'où les autres coordonnées sont nulles centre.Change_taille(3); // def de la distance d'observation grande pour minimiser la déformation double dist = 20.*lmax; // calcul de l'angle du cone de vue double angle = atan(lmax/dist); ostream &sort = entreePrinc->Sort_princ_vrml(); sort << "\n Viewpoint {" << "\n position " <