// 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_maple.h" #include #include "CharUtil.h" #include "Banniere.h" // CONSTRUCTEURS : // par defaut Animation_maple::Animation_maple () : OrdreVisu("...................................animation_maple" // de 15 à 65=50 caracteres ,"definition de l'animation si necessaire","ani") ,cycleInterval(8) //,loop(false),startTime(1),stopTime(0) // ,debut_auto(false),inter_2pas(2.) ,choix_grandeurs_maple(NULL),choix_mail(NULL),xyanim() {}; // constructeur de copie Animation_maple::Animation_maple (const Animation_maple& 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) // ,choix_grandeurs_maple(ord.choix_grandeurs_maple) // ,choix_mail(ord.choix_mail),xyanim(ord.xyanim) { }; // DESTRUCTEUR : Animation_maple::~Animation_maple () {}; // METHODES PUBLIQUES : // initialisation : permet d'initialiser les différents paramètres de l'ordre // lors d'un premier passage des différents incréments // en virtuelle, a priori est défini si nécessaire dans les classes dérivées // fil_calcul indique si s'est une initialisation lite !! void Animation_maple::Initialisation(ParaGlob * paraGlob,LesMaillages * lesmail,LesReferences* lesRefer ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage,Charge* charge ,LesCondLim* lesCondLim,LesContacts* lesContacts ,Resultats* resultats,EnumTypeIncre type_incre,int incre ,const map < string, const double * , std::less >& listeVarGlob ,const List_io < TypeQuelconque >& listeVecGlob,bool fil_calcul) { // initialisation de la liste List_io >::iterator il,ilfin=xyanim.end(); for (il = xyanim.begin();il!=ilfin;il++) { List_io & ilist = (*il); ilist.erase(ilist.begin(),ilist.end()); }; xyanim.erase(xyanim.begin(),xyanim.end()); //appel de l'ordre d'initialisation de la classe mère OrdreVisu::Initialisation(paraGlob,lesmail,lesRefer,lesLoisDeComp,diversStockage,charge ,lesCondLim,lesContacts,resultats,type_incre,incre ,listeVarGlob,listeVecGlob,fil_calcul); }; // 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_maple::ExeOrdre(ParaGlob * ,const Tableau & ,LesMaillages * ,bool ,LesReferences* ,LesLoisDeComp* ,DiversStockage*,Charge*,LesCondLim* ,LesContacts*,Resultats*,UtilLecture & entreePrinc,OrdreVisu::EnumTypeIncre type_incre,int ,bool animation,const map < string, const double * , std::less >& ,const List_io < TypeQuelconque >& listeVecGlob ) {ostream &sort = entreePrinc.Sort_princ_maple(); // définition de l'animation uniquement si animation est vraie, que c'est le dernier incrément if (actif && animation && (type_incre == DERNIER_INCRE)) { // ----- partie 1 : sortie des données ------------------ // si la liste de valeur à sortir est vide on arrête avec un message int taille_xyanim = xyanim.size(); if (taille_xyanim==0) { cout << "\n warning :: aucun resultats en sortie pour l'animation !!"; return;}; // on écrit successivement les grandeurs int taille_liste = xyanim.front().size(); if (taille_liste == 0) { cout << "\n warning :: aucun resultats en sortie pour le premier temps, pour l'animation !!"; return;}; // on vérifie que toutes les listes ont la même taille List_io >::iterator il,ilfin=xyanim.end(); for (il = xyanim.begin();il!=ilfin;il++) { if (taille_liste != (*il).size()) { cout << "\n erreur: le nombre de point en sortie entre le premier temps et un autre temps est different" << " on ne peut pas traiter -> rien en sortie !! "; return; }; } // maintenant on définit une liste de pointeurs pour chaque temps Tableau ::iterator> tab_ip(taille_xyanim); int i_tab=1; for (il = xyanim.begin();il!=ilfin;il++,i_tab++) { tab_ip(i_tab)= (*il).begin();}; // on écrit les infos sort << "\n"; double xmax=0.;double xmin=0.; double ymax=0.; double ymin=0.; for (i_tab=1;i_tab<= taille_liste;i_tab++) { for (int itemps = 1; itemps <= taille_xyanim; itemps++) { List_io ::iterator & iptl = tab_ip(itemps); double x=(*iptl).un ; double y = (*iptl).deux; sort << setprecision(ParaGlob::NbdigdoGR()) << x << " " << y << " "; iptl++; // calcul des maxi if (xmin > x) xmin = x; if (xmax < x) xmax = x; if (ymin > y) ymin = y; if (ymax < y) ymax = y; } sort << "\n"; }; // et on vide le buffer de sortie sort << endl; // ----- partie 2 : écriture du petit programme gnuplot qui est relue constamment ------------------ float temps_pause = cycleInterval/taille_xyanim; // ouverture du fichier ofstream auxi("plotter"); // on regarde l'utilisation de la sauvegarde de l'ancienne racine if (!auxi) //cas d'une erreur a l'ouverture du fichier { cout << "\n erreur en ouverture du fichier: plotter, on passe ! "; if (ParaGlob::NiveauImpression() >= 4) cout << "Animation_maple::ExeOrdre(...."; } else { cout << "\n creation du fichier: plotter, pour la visualisation avec gnuplot"; auxi << "#fichier au format gnuplot \n"; // le titre auxi << "###############################################################################################\n" << "# Visualisation elements finis : Herezh++ V" << ParaGlob::NbVersion() << " #\n" << "# " << Banniere::CopiPirate() << " #\n" << "# http://www-lg2m.univ-ubs.fr #\n" << "###############################################################################################\n" << "\n\n"; auxi << "\n# fichier gnuplot pour activer le dessin d'une courbe "; auxi << "\n \n "; auxi << "\n c_p = c_p+1 "; auxi << "\n c_p1=c_p +1 "; auxi << "\n plot \"$0\" using c_p:c_p1 "; auxi << "\n pause " << temps_pause; auxi << "\n c_p = c_p + 1 "; auxi << "\n if(c_p < n_p) reread "; auxi.close(); } // ----- partie 3 : écriture du programme principale de pilotage gnuplot ------------------ // ouverture du fichier ofstream auxa("anime.hz"); // on regarde l'utilisation de la sauvegarde de l'ancienne racine if (!auxa) //cas d'une erreur a l'ouverture du fichier { cout << "\n erreur en ouverture du fichier: anime.hz, on passe ! "; if (ParaGlob::NiveauImpression() >= 4) cout << "Animation_maple::ExeOrdre(...."; } else { cout << "\n creation du fichier: anime.hz, pour la visualisation avec gnuplot: " << "\n utilisation: call 'anime.hz' ' _princ.maple' "; auxa << "#fichier au format gnuplot\n"; // le titre auxa << "###############################################################################################\n" << "# Visualisation elements finis : Herezh++ V" << ParaGlob::NbVersion() << " #\n" << "# " << Banniere::CopiPirate() << " #\n" << "# http://www-lg2m.univ-ubs.fr #\n" << "###############################################################################################\n" << "\n\n"; auxa << "\n set xrange [" << xmin <<":" << xmax << "] # amplitude sur x "; auxa << "\n set yrange [" << ymin <<":" << ymax << "] # amplitude sur y "; // auxa << "\n set style data line # on relie les points par des lignes "; auxa << "\n set data style line # on relie les points par des lignes "; auxa << "\n n_p = " << (2*taille_xyanim) << " # def du nombre de courbes (c-a-d de pas de temps) "; auxa << "\n c_p = 0 # initialisation "; auxa << "\n call 'plotter' '$0' # appel du petit programme de boucle "; auxa.close(); } }; }; // choix de l'ordre, cet méthode peut entraîner la demande d'informations // supplémentaires si nécessaire. qui sont ensuite gérer par la classe elle même void Animation_maple::ChoixOrdre() { // on commence par appeler une fonction de Choix_grandeurs_mapple pour déterminer les // deux grandeurs à visualiser (en x et y) // auparavant on vérifie qu'il n'y a qu'un seul maillage a visualiser et on récupère son numéro const list & numeros_maillage = choix_mail->List_choisit() ; if (numeros_maillage.size() != 1) { cout << "\n erreur: le nombre de maillage actuellement enregistre est different de 1, pour l'animation" << " il faut choisir un seul maillage !! "; return; } int num_mail = numeros_maillage.front(); bool resultat = choix_grandeurs_maple->Choix_deux_grandeurs(num_mail); if (resultat) {actif = true;} else {actif = false; return;} // puis demande de précision bool choix_valide = false; string rep; cout << "\n ----> 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(false,"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,"0"); if (rep == "fin_prog") Sortie(1); // sinon int num = ChangeEntier(rep); if (num == 0) choix_valide=true; else if (num == 1) //((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') sinon non (autre reponse) ? "; cin >> rep; if (rep == "o") loop = false; else loop = true; break; } case 3: // début automatique { // bouclage continue cout << "\n debut automatique (oui (rep 'o') sinon non (autre reponse) ? "; cin >> rep; 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; cin >> duree; 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 1 !!, " //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(); }; // écriture des informations d'entête, renseigne sur les infos du fichier, ceci // pour permettre l'exploitation par les programmes graphiques // en entrée : list_mail = la liste des maillages à visualiser void Animation_maple::Entete_fichier_maple(const list& ,ostream & sort) { // le détails des grandeurs sort << "\n # entete des donnees : cas d'un fichier pour une animation"; sort << "\n # les courbes sont classees par colonnes: x(t=1) y(t=1) x(t=2) y(t=2) x(t=3) ...."; }; // lecture des paramètres de l'ordre dans un flux void Animation_maple::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_maple::Lecture_parametres_OrdreVisu(.."; } } }; // écriture des paramètres de l'ordre dans un flux void Animation_maple::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)"; // sort << " rien_pour_l_instant "; // fin sort << "\n fin_animation " << " # un mot cle de fin \n"; };