// 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-2022 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 "Animation_vrml.h" #include #include "CharUtil.h" // CONSTRUCTEURS : // par defaut Animation_vrml::Animation_vrml () : OrdreVisu(".........................................animation" ,"definition de l'animation si necessaire","ani") ,cycleInterval(8),loop(false),startTime(1),stopTime(0) ,debut_auto(false),inter_2pas(2.) ,isovaleurs_vrml(NULL),choix_mail(NULL) ,choix_deformee(NULL) {}; // constructeur de copie Animation_vrml::Animation_vrml (const Animation_vrml& ord) : OrdreVisu(ord) ,cycleInterval(ord.cycleInterval),loop(ord.loop) ,startTime(ord.startTime),stopTime(ord.stopTime) ,debut_auto(ord.debut_auto),inter_2pas(ord.inter_2pas) ,isovaleurs_vrml(ord.isovaleurs_vrml) ,choix_mail(ord.choix_mail),choix_deformee(ord.choix_deformee) { }; // DESTRUCTEUR : Animation_vrml::~Animation_vrml () {}; // METHODES PUBLIQUES : // execution de l'ordre // tab_mail : donne les numéros de maillage concerné // incre : numéro d'incrément qui en cours // type_incre : indique si c'est le premier le dernier ou l'incrément courant a visualiser ou pas // animation : indique si l'on est en animation ou pas // unseul_incre : indique si oui ou non il y a un seul increment à visualiser void Animation_vrml::ExeOrdre(ParaGlob * paraGlob,const Tableau & ,LesMaillages * ,bool ,LesReferences* ,LesLoisDeComp* ,DiversStockage*,Charge*,LesCondLim* ,LesContacts*,Resultats*,UtilLecture & entreePrinc,OrdreVisu::EnumTypeIncre ,int ,bool animation,const map < string, const double * , std::less >& ,const List_io < TypeQuelconque >& listeVecGlob) {ostream &sort = entreePrinc.Sort_princ_vrml(); // définition de l'animation uniquement si animation est vraie if (actif && animation) {if (list_nom_coordinate.size() == 0) // cas ou on n'a pas définit les coordonnées c'est-a-dire que l'ordre déformée // n'a pas été exécutée, on ne peut rien faire sinon prévenir de définir la déformée { cout << "\n les parametres de deformee ne sont pas definit, l'animation ne " << " peut-être exécutee !! " << "\n recommencee en définissant la deformee "; } else { // on défini le trigger qui permet le démarrage de l'animation // dans le cas d'un démarrage non automatique if (!debut_auto) // cas d'un début non automatique sort << "\n # Trigger things on touch: cas d'un demarrage non automatique" << "\n DEF Touch TouchSensor { } "; // on défini le timer sort << "\n DEF Clock TimeSensor {" << "\n cycleInterval " << cycleInterval << "\n loop " ; if (loop) sort << "TRUE"; else sort << "FALSE"; sort << "\n startTime " << startTime << "\n stopTime " << stopTime << "\n } \n"; // ------ on défini l' interpolateur de points ---- // récup du nombre de maillage qui sont visualisé const list & lis_mail_choisit = choix_mail->List_choisit(); int nb_maillage= lis_mail_choisit.size(); // on fractionne régulièrement le temps int nb_step = (int) (list_nom_coordinate.size()/nb_maillage); // nb_step donne le nombre d'incrément double step_time = 1./(nb_step-1); // boucle sur les maillages for (int imail=1;imail<=nb_maillage;imail++) {// def de l'interpolateur de coordonnées sort << "\n DEF InterpolDePoints" << imail << " CoordinateInterpolator { " << "\n key [ "; for (int i=1; i<= nb_step-1; i++) sort << " " << step_time*(i-1); sort << " " << 1 << "] "; // on écrit les coordonnées sort << "\n keyValue [ \n"; list >::iterator il,ilfin = list_coordinate.end(); list ::iterator ik,ikfin; int compte; // on décale le début de il en fonction du maillage traité il=list_coordinate.begin();for (int ib=2;ib<=imail;ib++) {il++;if(il==ilfin) {cout << "\n erreur de sortie d'animation vrml";Sortie(1);}}; for (compte=1;il!=ilfin;) // l'incrémentation de il est multiple donc traitée dans la boucle { ikfin = il->end(); for (ik=il->begin();ik!=ikfin;ik++,compte++) { sort << " " << setw (16); (*ik).Affiche(sort,16); // si l'on n'est pas en dimension 3 on complete avec des zeros if (paraGlob->Dimension () == 2) { sort << setw (16) << 0 <<" ";} else if (paraGlob->Dimension () == 1) { sort << setw (16) << 0 <<" " << setw (16) << 0 <<" ";} sort << " , "; if (compte == 2) { compte = 1; sort << "\n";} } // on s'occupe d'incrémenter il for (int ib=1;ib<=nb_maillage;ib++) {il++; if (il== ilfin) break;}; } sort << "\n ] } "; } // ------ on défini l' interpolateur de couleur éventuellement ---- // pour l'instant ne sert pas car il faut un script !! /* if (isovaleurs_vrml->Actif()) { sort << "\n DEF InterpolDeCouleurs ColorInterpolator { " << "\n key [ "; // on fractionne régulièrement le temps int nb_step = (int) list_nom_coordinate.size(); double step_time = 1./(nb_step-1); for (int i=1; i<= nb_step-1; i++) sort << " " << step_time*(i-1); sort << " " << 1 << "] "; // def d'un conteneur intermédiaire pour simplifier const list < Tableau < Rgb > > & list_couleur = isovaleurs_vrml->List_couleur(); // on écrit les couleurs sort << "\n keyValue [ \n"; list >::const_iterator il,ilfin = list_couleur.end(); int compte; for (il=list_couleur.begin(),compte=1;il!=ilfin;il++) { int taill=(*il).Taille(); for (int ik=1;ik<=taill;ik++,compte++) { sort << " " << setw (16) << (*il)(ik); sort << " , "; if (compte == 2) { compte = 1; sort << "\n"; } } } sort << "\n ] } "; } */ // on définit les interpolateurs scalaires qui permettent de gérer la transparence de chaque // incrément. L'idée est que la transparence d'un incrément est active uniquement sur un // pas de temps, tout le reste du temps l'incrément est tout transparent if (isovaleurs_vrml->Actif()) { sort << "\n \n # ------ cas des isovaleurs, definition des interpolateurs scalaires pour la transparence " << " des matieres ----- "; // on a autant d'interpolateur que de step double dex=step_time/10; for (int ist=1;ist<= nb_step;ist++) {sort << "\n DEF inter_intense"<::iterator ilc = list_nom_coordinate.begin(); list ::iterator ilcfin = list_nom_coordinate.end(); for (int ib=2;ib<=imail;ib++) {ilc++;if(ilc==ilcfin) {cout << "\n erreur de sortie 2 d'animation vrml";Sortie(1);}}; // fin de la sortie des infos sort << *(ilc) << ".set_point"; } //*** le cas des isovaleurs avec plusieurs maillage est à traiter !!!!!!!!!!!!!! // si l'on a des isovaleurs on route également sur tous les incréments if (isovaleurs_vrml->Actif()) {sort << "\n \n # ------ cas des isovaleurs, definition des routages pour toutes les deformees ----- "; list ::iterator ino=list_nom_coordinate.begin(); ino++; // le premier est déjà fait // on boucle sur le nombre d'incrément puis sur le nombre de maillage for (int ic=2;ic<= nb_step;ic++) // on commence à deux cas 1 est déjà fait for (int im=1;im<=nb_maillage;im++,ino++) {sort << "\n ROUTE Clock.fraction_changed TO InterpolDePoints"<Actif()) { sort << "\n \n # ------ cas des isovaleurs, definition des routages pour la transparence " << " des matieres ----- "; // récup de la liste des noms de matière const list & noms_matiere = choix_deformee->Noms_matiere(); list ::const_iterator inom=noms_matiere.begin(); // on boucle sur le nombre d'incrément puis sur le nombre de maillage for (int ic=1;ic<= nb_step;ic++) for (int im=1;im<=nb_maillage;im++,inom++) {sort << "\n ROUTE Clock.fraction_changed TO inter_intense"< choix des parametre de l'animation " << "\n parametres actuels ? : duree de l'animation : " << cycleInterval << "\n bouclage de l'animation : " ; if (loop) cout << "oui"; else cout << "non"; cout << "\n debut automatique "; if (debut_auto) cout << "oui"; else cout << "non"; cout << "\n duree entre deux passages automatiques: " << inter_2pas << "\n (valable si l'on a un debut automatique);"; cout << " \n (rep 'o') pour accepter ces parametres sinon autre "; cout << "\n reponse ? "; rep = lect_return_defaut(true,"o");; if (rep != "o") {// cas d'un choix autre que standart while (!choix_valide) { try { cout << "\n (0) fin modif" << "\n (1) duree du cycle? (2)bouclage de l'animation ? " << "\n (3) debut automatique ? (4)duree entre deux passages auto? "; cout << "\n \n reponse ? "; rep = lect_return_defaut(false,"f"); if (rep == "fin_prog") Sortie(1); // sinon int num = ChangeEntier(rep); if (num == 0) choix_valide=true; else if ((num >= 1)&&(num<=4)) { choix_valide=false; switch (num) { case 1: //durée du cycle { // cas de la durée du cycle cout << "\n duree du cycle (un reel strictement positif) ? "; double duree; duree=lect_double(); if (duree > 0) cycleInterval = duree; else { cout << "erreur le cycle doit être positif!, on garde la valeur precedente " << cycleInterval; } break; } case 2: // bouclage de l'animation { // bouclage continue cout << "\n bouclage non continu (oui (rep 'o'(defaut)) sinon non (autre reponse) ? "; rep = lect_return_defaut(false,"o"); if (rep == "o") loop = false; else loop = true; break; } case 3: // début automatique { // bouclage continue cout << "\n debut automatique (oui (rep 'o'(defaut)) sinon non (autre reponse) ? "; rep = lect_return_defaut(false,"o"); if (rep == "o") debut_auto = true; else debut_auto = false; break; } case 4: // durée entre deux passage automatique { cout << "\n duree entre deux passages, dans le cas d'un demarrage automatique" << "\n (un reel strictement positif) ? "; double duree; duree=lect_double(); if (duree > 0) inter_2pas = duree; else { cout << "erreur la duree doit être positive!, on garde la valeur precedente " << inter_2pas; } break; } } } else { cout << "\n Erreur on attendait un entier entre 0 et 4 !!, " << "\n redonnez une bonne valeur" << "\n ou taper fin_prog pour arreter le programme"; choix_valide=false; } } 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 on attendait un des mots clés proposes !!, " << "\n redonnez une bonne valeur" << "\n ou taper fin_prog pour arreter le programme"; choix_valide=false; } } //-- fin du while } //-- fin du if (rep != "o") du départ c'est-à-dire du cas non standart // on prévient qu'il faut absolument renseigner l'ordre "déformée" cout << "\n n'oubliez pas de definir les parametres de deformees pour que l'animation fonctionne\n"; // appel de la méthode de la classe mère OrdreVisu::ChoixOrdre(); }; // initialisation des listes de coordonnées void Animation_vrml::Init_liste_coordonnee() {OrdreVisu::Mise_zero_coordo(); } ; // lecture des paramètres de l'ordre dans un flux void Animation_vrml::Lecture_parametres_OrdreVisu(UtilLecture & entreePrinc) { // si dans le flot il existe l'identificateur adoc on lit sinon on passe if (strstr(entreePrinc.tablcarCVisu,"debut_animation")!=NULL) {// sauvegarde des paramètres actuelles bool loop_s=loop; bool debut_auto_s=debut_auto; double cycleInterval_s = cycleInterval; double startTime_s=startTime; double stopTime_s=stopTime; double inter_2pas_s = inter_2pas; // essaie de lecture try { string nom; (*entreePrinc.entCVisu) >> nom ; if (nom != "debut_animation") { cout << "\n Erreur en lecture des parametres de l'animation a partir d'un fichier .CVisu," << " le premier enregistrement doit etre le mot clef: debut_animation " << " on ne tiens pas compte des parametres fournies !! "; } else { // appel de l'ordre de la classe mère OrdreVisu::Lect_para_OrdreVisu_general(entreePrinc); while (nom != "fin_animation") { (*entreePrinc.entCVisu) >> nom; if (nom == "cycleInterval") (*entreePrinc.entCVisu) >> cycleInterval; if (nom == "loop") (*entreePrinc.entCVisu) >> loop; if (nom == "startTime") (*entreePrinc.entCVisu) >> startTime; if (nom == "stopTime") (*entreePrinc.entCVisu) >> stopTime ; if (nom == "debut_auto") (*entreePrinc.entCVisu) >> debut_auto ; if (nom == "inter_2pas") (*entreePrinc.entCVisu) >> inter_2pas ; entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement } } } 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 des parametres de l'animation a partir d'un fichier .CVisu," << " on ne tiens pas compte des parametres fournies !! "; // récup des infos sauvées cycleInterval=cycleInterval_s; loop=loop_s; startTime = startTime_s; stopTime=stopTime_s; debut_auto=debut_auto_s; inter_2pas=inter_2pas_s; if (ParaGlob::NiveauImpression() >= 4) cout << "\n Animation_vrml::Lecture_parametres_OrdreVisu(.."; } } }; // écriture des paramètres de l'ordre dans un flux void Animation_vrml::Ecriture_parametres_OrdreVisu(UtilLecture & entreePrinc) { // récup du flot ostream & sort = (*(entreePrinc.Sort_CommandeVisu())); // on commente le fonctionnement sort << "\n # ----------------------------- definition des parametres d'animation: ---------------- "; sort << "\n debut_animation # un mot cle de debut de liste (debut_animation)"; // appel de l'ordre de la classe mère OrdreVisu::Ecrit_para_OrdreVisu_general(entreePrinc); sort << "\n # des parametres avec des valeurs: (sur une meme ligne) "; // la liste des paramètres sort << "\n cycleInterval " << cycleInterval << " # cycleInterval (indique le temps en seconde du cycle de l'animation)" << "\n loop " << loop << " # loop <0 ou 1> (indique si l'on veut une animation en boucle continue ou non)" << "\n startTime " << startTime << " # startTime (temps de démarrage de l'animation en absolu depuis 1970)" << "\n stopTime " << stopTime << " # stopTime (temps de fin en absolu depuis 1970, si < a starttime on n'en tiend pas compte)" << "\n debut_auto " << debut_auto << " # debut_auto <0 ou 1> (indique si l'on veut ou non un debut automatique de l'animation)" << "\n inter_2pas " << inter_2pas << " # inter_2pas (temps entre deux cycle d'animation, si loop est actif)"; // fin sort << "\n fin_animation " << " # un mot cle de fin \n"; };