
// 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 "Animation_geomview.h"

#include <iomanip>

    // CONSTRUCTEURS :
// par defaut
Animation_geomview::Animation_geomview () :
   OrdreVisu(".........................................animation"
             ,"definition de l'animation si necessaire","ani")
   ,cycleInterval(8),loop(false),startTime(1),stopTime(0)
   ,isovaleurs_geomview(NULL),choix_mail(NULL)
   ,choix_deformee(NULL)          
     {}; 
     
     // constructeur  de copie 
Animation_geomview::Animation_geomview (const Animation_geomview& ord) :
    OrdreVisu(ord)
    ,cycleInterval(ord.cycleInterval),loop(ord.loop)
    ,startTime(ord.startTime),stopTime(ord.stopTime)
    ,isovaleurs_geomview(ord.isovaleurs_geomview)
    ,choix_mail(ord.choix_mail),choix_deformee(ord.choix_deformee)
      {};
               
    // DESTRUCTEUR :
Animation_geomview::~Animation_geomview () 
     {};  
    
    // 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_geomview::ExeOrdre(ParaGlob * ,const Tableau <int>&  ,LesMaillages * ,bool ,LesReferences*
//void Animation_geomview::ExeOrdre(ParaGlob * paraGlob,int  ,LesMaillages * ,LesReferences*
                      ,LesLoisDeComp* ,DiversStockage*,Charge*,LesCondLim*
                      ,LesContacts*,Resultats*,UtilLecture & entreePrinc,OrdreVisu::EnumTypeIncre ,int 
//                      ,bool animation)
                      ,bool,const map < string, const double * , std::less <string> >&
                      ,const List_io < TypeQuelconque >& listeVecGlob )
{//ostream &sort = entreePrinc.Sort_princ_geomview();
 cout << "\n *** la methode Animation_geomview::ExeOrdre( n'est pas implantee !  "
      << " le resultat sera inconnue !! ";
 // définition de l'animation uniquement si animation est vraie
/* en commentaire pour geomview pour l'instant 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 executee !! "
           << "\n recommencee en definissant la deformee ";
      }
   else        
  { // on défini le trigger qui permet le démarrage de l'animation
    sort << "\n #  Trigger things on touch"
         << "\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                       }";    
         
    // ------ on défini l' interpolateur de points ---- 
    // récup du nombre de maillage qui sont visualisé
    const list <int> & 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);
    // def de l'interpolateur de coordonnées
    sort << "\n DEF InterpolDePoints 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 <list <Coordonnee > >::iterator il,ilfin = list_coordinate.end();
    list <Coordonnee >::iterator ik,ikfin;
    int compte;
    for (il=list_coordinate.begin(),compte=1;il!=ilfin;il++)
      { 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";
              }
           }
       }             
    sort << "\n     ] } ";  en commentaire pour geomview pour l'instant */
    // ------ on défini l' interpolateur de couleur éventuellement ---- 
    // pour l'instant ne sert pas car  il faut un script !!
/*    if (isovaleurs_geomview->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_geomview->List_couleur();

    // on écrit les couleurs
    sort << "\n     keyValue [ \n";
    list <Tableau <Rgb > >::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
     
/*  en commentaire pour geomview pour l'instant if (isovaleurs_geomview->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"<<ist<<" ScalarInterpolator {"
             << "\n   key [ ";
        // on décompose en temps de base 
        if (ist==1)
         {// cas du premier interpolateur
          sort << "0.0 "<<(step_time-dex)<<" "; // monté
          for (int i=2; i<= nb_step-1; i++)
            sort << " " << step_time*(i-1); 
          }
        else if (ist==nb_step)
         {// cas du dernier interpolateur
          for (int i=1; i<= nb_step-1; i++)
            sort << " " << step_time*(i-1);  // descente
          sort << " "<<(1.-dex)<<" ";
          }
        else // cas courant
         {for (int i=1; i<= nb_step-1; i++)
           { if(i==ist) // cas de la monté
               sort <<" " << step_time*(ist-1) - dex // monté
                    <<" " << step_time*(ist-1)
                    <<" " << step_time*ist - dex; // descente
             // cas courant  
             else sort << " " << step_time*(i-1);
            }   
          }
        // fin      
        sort << " " << 1 << "] ";
        // on écrit les valeurs de transparence
        sort << "\n     keyValue [ ";
        // on décompose en temps de base 
        if (ist==1)
         {// cas du premier interpolateur
          sort << "0.0, 0.0,  "; // validité
          for (int i=2; i<= nb_step-1; i++)
            sort << " 1.0, "; 
          sort << " 1.0, "; 
          }
        else if (ist==nb_step)
         {// cas du dernier interpolateur
          for (int i=1; i<= nb_step-1; i++)
            sort << "1.0, " ;  
          sort << " 1.0, 0.0, "; // descente
          }
        else // cas courant
         {for (int i=1; i<= nb_step-1; i++)
           { if(i==ist) // cas de la monté
               sort <<" 1.0, "  // monté
                    <<" 0.0, " 
                    <<" 0.0, " ; // descente
             // cas courant  
             else sort << " 1.0, " ;
            }
            sort << " 1.0, ";   
          }
        sort << "] ";
        sort << "\n    } ";
        }     
      }
    
    // on définit maintenant le routage pour le déplacement
    sort << "\n \n # ------ definition de l'horloge ----- ";
    sort << "\n ROUTE Touch.touchTime TO Clock.set_startTime";
    sort << "\n \n # ------ definition du routage pour la deformee de base ----- ";
    sort << "\n ROUTE Clock.fraction_changed TO InterpolDePoints.set_fraction";
    sort << "\n ROUTE InterpolDePoints.value_changed TO " << *(list_nom_coordinate.begin())
         << ".set_point";
    // si l'on a des isovaleurs on route également sur tous les incréments
    if (isovaleurs_geomview->Actif())
     {sort << "\n \n # ------ cas des isovaleurs, definition des routages pour toutes les deformees ----- ";
      list <string>::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.set_fraction";
           sort << "\n ROUTE InterpolDePoints.value_changed TO " << *(ino)
                << ".set_point";
           }
      }
    // si l'on a des isovaleurs on définit les routeurs de gestion de la transparence
    // de chaque incrément
    if (isovaleurs_geomview->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 <string> & noms_matiere = choix_deformee->Noms_matiere();
      list <string>::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"<<ic<<".set_fraction";
           sort << "\n ROUTE inter_intense"<<ic<<".value_changed TO " << *(inom)
                << ".set_transparency";
           }
     }
     // et on vide le buffer de sortie
     sort << endl; 
    };   */                       

   };

// 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_geomview::ChoixOrdre()
   { // demande de précision
/* pour l'instant en commentaire pour geomview     bool choix_valide = false;
     while (!choix_valide)
      { // tout d'abord on met le choix valide a priori
        choix_valide = true;
        cout << "\n ----> changement des parametres de l'animation "
             << "\n  parametres actuels ?   : duree de l'animation : " << cycleInterval
             << "\n                        bouclage de l'animation : " ; 
             if (loop) cout << "oui"; else cout << "non";
        cout << "   (rep 'o') pour accepter ces parametres sinon autre ";
        string rep;
        cout << "\n reponse ? "; cin >>  rep;
        if (rep != "o") 
          { // cas de la durée du cycle 
            cout << "\n duree du cycle (un reel strictement positif)  ? ";
            double duree; 
            cin >>  duree;
            if (duree > 0)
              {  choix_valide = choix_valide && true;
                 cycleInterval = duree;
               }
            else 
              { cout << "erreur le cycle doit etre positif!,  on garde la valeur precedente "
                     << cycleInterval;
                choix_valide = choix_valide && true;
               }
            // bouclage continue
            cout << "\n bouclage non continu (oui (rep 'o') sinon non (autre reponse)  ? ";
            cin >> rep;
            if (rep == "o")
              { choix_valide = choix_valide && true;
                loop = false;
               } 
            else
              { choix_valide = choix_valide && true;
                loop = true;
               } 
            }
         }      
       // 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_geomview::Init_liste_coordonnee() 
       {OrdreVisu::Mise_zero_coordo(); } ; 
       
// lecture des paramètres de l'ordre dans un flux
void Animation_geomview::Lecture_parametres_OrdreVisu(UtilLecture & )
 { 
  };

// écriture des paramètres de l'ordre dans un flux
void Animation_geomview::Ecriture_parametres_OrdreVisu(UtilLecture & )
 { // récup du flot 
   cout << "\n pour l'instant pas de sauvegarde des parametres d'animation pour le format geomview";
  };
     
