
// 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-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 <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.

#include "Deformees_Gid.h"
#include "CharUtil.h"
#include "ConstMath.h"

#include <iomanip>

    // CONSTRUCTEURS :
// par defaut
Deformees_Gid::Deformees_Gid () :
   OrdreVisu("..........................................deformee"
             ,"visualisation des deformee","de")
   ,isovaleurs_Gid(NULL)
   ,num_mail_incr(),noms_matiere(),choix_mail(NULL)
   ,noms_couleurs()
   ,li_bornes(),li_nom_bornes()
     {}; 
     
     // constructeur de copie 
Deformees_Gid::Deformees_Gid (const Deformees_Gid& ord) :
    OrdreVisu(ord)
   ,isovaleurs_Gid(ord.isovaleurs_Gid)
   ,num_mail_incr(ord.num_mail_incr)
   ,noms_matiere(),choix_mail(ord.choix_mail)
   ,noms_couleurs(ord.noms_couleurs)
   ,li_bornes(ord.li_bornes),li_nom_bornes(ord.li_nom_bornes)
      {}; 
               
    // DESTRUCTEUR :
Deformees_Gid::~Deformees_Gid ()   
     {};  
    
    // 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 Deformees_Gid::ExeOrdre(ParaGlob * paraGlob,const Tableau <int>& tab_mail,LesMaillages * lesMail,bool ,LesReferences*
                      ,LesLoisDeComp* ,DiversStockage*,Charge*,LesCondLim*
                      ,LesContacts*,Resultats*,UtilLecture & entreePrinc,OrdreVisu::EnumTypeIncre ,int incre
//                      ,LesContacts*,Resultats*,UtilLecture & entreePrinc,OrdreVisu::EnumTypeIncre type_incre,int incre
                      ,bool ,const map < string, const double * , std::less <string> >&
                      ,const List_io < TypeQuelconque >& listeVecGlob)
 {// visualisation du maillage pointé si actif
  if (actif)
  {ostream &sort = entreePrinc.Sort_resultat_Gid();
   // pour  boucler sur les maillages
   int nbmail = tab_mail.Taille();
   if (incre == 0)
    { // dans le cas du premier incrément on sort la table d'alertes
      if (li_nom_bornes.size() != 0)
       {sort << "\n #  --- definition de la table d'alertes ---- ";
        sort << "\n ResultRangesTable \"table_alertes_deformees\" ";
        list <DeuxDoubles>::iterator idd_n,idd_fin=li_bornes.end();
        list <string>::iterator ili,ili_fin=li_nom_bornes.end();
        ili=li_nom_bornes.begin();int num=1;
        for (idd_n=li_bornes.begin();idd_n!=idd_fin;idd_fin++,num++)
        { sort << "\n";
          if ((*idd_n).un != -ConstMath::trespetit) 
             {sort << (*idd_n).un << " ";}
          else {sort << "       ";};
          sort << " - ";
          if ((*idd_n).deux != ConstMath::tresgrand) {sort << (*idd_n).deux << " : ";};
          sort << " \"" << *ili << "\" ";
         };
        sort << "\n End ResultRangesTable \n";
        };
     };
   
   // dans le cas où c'est l'incrément 0, c'est-à-dire le maillage initial, on ne sort rien
   // au niveau des déplacements sinon on y va
   if (incre != 0)
    { // on sort l'entête
      sort << "\n Result \"deplacement_maillage\" \"calcul_mecanique\" "
           << incre << " Vector OnNodes \n";
      if (li_nom_bornes.size() != 0) // sortie que si il y a des éléments dans la table
          sort << "\n    ResultRangesTable \"table_alertes_deformees\" ";
      sort << "\n    ComponentNames \"delta_X\", \"delta_Y\", \"delta_Z\" ";
      sort << "\n Values ";
      for (int im=1;im<=nbmail;im++)
         { int numMail=tab_mail(im);
           // on sort les déplacements pour les différents noeuds
           int nbmaxinoeud = lesMail->Nombre_noeud(numMail);
           // on balaie tous les noeuds du maillage
              // on récupère le décalage de numéros
           int decal_noe=mailInitial->DecalNumNoeud(numMail); // pour simplifier
           for (int numNoeud=1; numNoeud<= nbmaxinoeud;numNoeud++) 
              { // recup du noeud
                Noeud & noe = lesMail->Noeud_LesMaille(numMail,numNoeud);
                Coordonnee dep(paraGlob->Dimension()); // init à zero par defaut
                if (noe.ExisteCoord1()) 
                  {dep = (noe.Coord1() - noe.Coord0() );
                   sort << "\n" << noe.Num_noeud() + decal_noe << " " ;
                   dep.Affiche(sort,ParaGlob::NbdigdoGR());
                   switch (ParaGlob::Dimension()) // dans le cas d'une dimension diff de 3, on complète avec des 0
                    { case 1: sort << "  0.   ";
                      case 2: sort << "  0.   ";
                     };             
                   };
                };
           };//-- fin de la boucle sur les maillages
         sort << "\n End Values ";
        };
   // et on vide le buffer de sortie
   sort << endl; 
  }; //-- fin du if actif
 };  

 // 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 Deformees_Gid::ChoixOrdre()
   { // demande de précision
     bool choix_valide = false;
     cout << "\n ----> preparation de la visualisation des deformees"
          << "\n  parametre par defaut ? : pas de limites d'alerte sur les deplacements ,"
          << "   (rep 'o') pour accepter ces parametres sinon autre ";
     string rep;
     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) nouvelle definition de limites d'alerte?   "               
               << "\n (2) effacer une limites d'alerte existante ?   ";               
          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<=2)) 
           { choix_valide=false;
             switch (num)
              { case 1:  // definition des limites d'alerte 
                { cout << "\n donnez une borne inferieur "
                       << "\n (rep un reel ou 'no' pour utiliser le minimum total des valeurs ";
                  string numinf;DeuxDoubles dd; string nom_bornes;
                  numinf= lect_chaine();
                  if (numinf == "no")  
                    {dd.un= -ConstMath::trespetit;}
                  else
                    {dd.un=ChangeReel(numinf);};  
                  if ( numinf == "no") 
                    { // il faut absolument donner une borne supérieur
                      cout << "\n donnez une borne superieur (rep un reel) ";
                      numinf= lect_chaine();
                      dd.deux=ChangeReel(numinf);
                     }
                  else
                    {cout << "\n donnez une borne superieur "
                          << "\n (rep un reel ou 'no' pour utiliser le maximum total des valeurs ";
                     numinf= lect_chaine();
                     if (numinf == "no")  
                      {dd.deux= ConstMath::tresgrand;}
                     else
                      {dd.deux=ChangeReel(numinf);};
                     }; 
                  // définition du nom
                  cout << "\n donnez le nom que vous voulez donner a ces limites: ";
                  numinf= lect_chaine();
                  // maintenant on valide
                  li_bornes.push_back(dd); li_nom_bornes.push_back(numinf);
                  break;
                  }
                case 2:  // "effacer une limites d'alerte existante")
                { cout << "\n liste actuelle des alertes enregistrees ";
                  list <DeuxDoubles>::iterator idd_n,idd_fin=li_bornes.end();
                  list <string>::iterator ili,ili_fin=li_nom_bornes.end();
                  ili=li_nom_bornes.begin();int num=1;
                  for (idd_n=li_bornes.begin();idd_n!=idd_fin;idd_fin++,num++)
                    { cout << "\n(" << num << ") " << *ili << (*idd_n).un << " " << (*idd_n).deux <<" ";};
                  cout << "\n donnez le numero d'alerte a supprimer ";
                  string num_choix;
                  num_choix= lect_chaine(); int num_c=ChangeEntier(num_choix);
                  if ((num_c >=1)&&(num_c<=num))
                   {ili=li_nom_bornes.begin();int num=1;
                    for (idd_n=li_bornes.begin();idd_n!=idd_fin;idd_fin++,num++)
                      if (num==num_c)
                        {li_nom_bornes.erase(ili_fin);li_bornes.erase(idd_n);};                                     
                    };
                  break;
                 }
              };
             } 
          else { cout << "\n Erreur on attendait un entier entre 0 et 2 !!, "
                      << "\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 cles proposés !!, "
                      << "\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 
      // appel de la méthode de la classe mère
      OrdreVisu::ChoixOrdre();    
     };                 
           
    
// lecture des paramètres de l'ordre dans un flux
void Deformees_Gid::Lecture_parametres_OrdreVisu(UtilLecture & entreePrinc)
 { // si dans le flot il existe l'identificateur adoc on lit sinon on passe
   if (strstr(entreePrinc.tablcarCVisu,"debut_deformee")!=NULL)
     {// sauvegarde des paramètres  actuelles
      list <DeuxDoubles> li_bornes_sauve = li_bornes; // min max des alertes
      list <string> li_nom_bornes_sauve = li_nom_bornes;  // nom des alertes
      // essaie de lecture
      try 
        { string nom; 
          (*entreePrinc.entCVisu) >> nom ;
          if (nom != "debut_deformee")
            { cout << "\n Erreur en lecture des parametres de deformee a partir d'un fichier .CVisu,"
                   << " le premier enregistrement doit etre le mot clef: debut_deformee "
                   << " 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 (strstr(entreePrinc.tablcarCVisu,"fin_deformee")==NULL)
              {// lecture  des alertes
               if (strstr(entreePrinc.tablcarCVisu,"deb_list_alerte")!=NULL)
                 { // lecture de la liste des alertes
                   entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement 
                   // on efface éventuellement les listes actuelles s'il y a quelque chose à lire
                   if (strstr(entreePrinc.tablcarCVisu,"fin_list_alerte")==NULL)
                    {li_nom_bornes.erase(li_nom_bornes.begin(),li_nom_bornes.end());
                     li_bornes.erase(li_bornes.begin(),li_bornes.end());
                     // lecture des  listes demandées
                     int compteur=0; // pour éviter une boucle infinie
                     DeuxDoubles dd_n; string nom_alerte,nom2;
                     while (compteur < 1000000)
                       { (*entreePrinc.entCVisu) >> nom >> nom2 >> nom_alerte; compteur++;
                         if (nom != "fin_list_alerte")
                           { dd_n.un=ChangeReel(nom); dd_n.deux=ChangeReel(nom2);
                             // on vérifie que le nom lu est acceptable
                             if (find(li_nom_bornes.begin(),li_nom_bornes.end(),nom_alerte) != li_nom_bornes.end())
                                {li_nom_bornes.push_back(nom_alerte);li_bornes.push_back(dd_n);}
                             else
                                cout << "\n lecture d'une alerte ( "<< nom << " ) errone ! on n'en tiens pas compte";   
                             entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
                            }
                         else break;                           
                        }
                     };
                  entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement   
                 }; //-- on sort du cas où il y avait une liste d'alerte
              } //-- on sort des paramètres de déformée 
             // on passe un enregistrement pour le prochain ordrevisu  
             entreePrinc.NouvelleDonneeCVisu();    
           }; // fin du cas d'une lecture de paramètre de dérivées
          }    
      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 deformee a partir d'un fichier .CVisu,"
               << " on ne tiens pas compte  des parametres fournies !! ";
          // récup des infos  sauvées
          li_bornes = li_bornes_sauve; // min max des alertes
          li_nom_bornes = li_nom_bornes_sauve;  // nom des alertes
          if (ParaGlob::NiveauImpression() >= 4)     
             cout  << "\n Deformees_Gid::Lecture_parametres_OrdreVisu(..";
        }
      } 
  };

// écriture des paramètres de l'ordre dans un flux
void Deformees_Gid::Ecriture_parametres_OrdreVisu(UtilLecture & entreePrinc)
 { // récup du flot  
   ostream & sort = (*(entreePrinc.Sort_CommandeVisu()));
   // on commente le fonctionnement
   sort << "\n #  ----------------------------- definition des parametres de deformee: ---------------- "
        << "\n debut_deformee  #  un mot cle de debut de liste";
   // appel de l'ordre de la classe mère
   OrdreVisu::Ecrit_para_OrdreVisu_general(entreePrinc);
   // on sort l'entête des paramètres
   sort << "\n # definition des alertes: deb_list_alerte "
        << "\n # un mot clef de debut "
        << "\n # puis deux nombres: un mini et un maxi, et un nom "
        << "\n # un mot clef de fin: fin_list_alerte ";   
   // puis la liste des alertes
   sort << "\n deb_list_alerte ";            
   list <DeuxDoubles>::iterator idd_n,idd_fin=li_bornes.end();
   list <string>::iterator ili,ili_fin=li_nom_bornes.end();
   ili=li_nom_bornes.begin();int num=1;
   for (idd_n=li_bornes.begin();idd_n!=idd_fin;idd_fin++,num++)
      { sort << "\n" << (*idd_n).un << " " << (*idd_n).deux << " " << *ili << " ";};
   sort << "\n fin_list_alerte  ";
   // fin      
   sort << "\n fin_deformee " << " #   un mot cle de fin  \n";    
  };
    
                            
                            
                            
