404 lines
20 KiB
C++
404 lines
20 KiB
C++
|
|
||
|
// 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) <https://www.irdl.fr/>.
|
||
|
//
|
||
|
// 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 <https://www.gnu.org/licenses/>.
|
||
|
//
|
||
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
||
|
|
||
|
#include "Animation_maple.h"
|
||
|
|
||
|
#include <iomanip>
|
||
|
#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 <string> >& listeVarGlob
|
||
|
,const List_io < TypeQuelconque >& listeVecGlob,bool fil_calcul)
|
||
|
{ // initialisation de la liste
|
||
|
List_io <List_io <DeuxDoubles> >::iterator il,ilfin=xyanim.end();
|
||
|
for (il = xyanim.begin();il!=ilfin;il++)
|
||
|
{ List_io <DeuxDoubles> & 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 <int>& ,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 <string> >&
|
||
|
,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 <List_io <DeuxDoubles> >::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 <List_io <DeuxDoubles>::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 <DeuxDoubles>::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' ' <nom>_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 <int>& 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<int>& ,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 <un reel> (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 <un reel> (temps de démarrage de l'animation en absolu depuis 1970)"
|
||
|
// << "\n stopTime " << stopTime << " # stopTime <un réel> (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 <un réel> (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";
|
||
|
};
|
||
|
|
||
|
|