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

#include "ParaGlob.h"
#include <list>
#include "MathUtil.h"
#include "CharUtil.h"

    // par défaut
    MvtSolide::MvtSolide() :
      tab_tcr(), tab_indic(),lis_centre_noeud()
        {};
    // de copie
   	MvtSolide::MvtSolide (const MvtSolide& mvt):
      tab_tcr(mvt.tab_tcr), tab_indic(mvt.tab_indic)
      ,lis_centre_noeud(mvt.lis_centre_noeud)
        {};
    // DESTRUCTEUR : 
	   MvtSolide::~MvtSolide ()
	      	{};
		
// Affiche les donnees 
void MvtSolide::Affiche () const 
	{ cout << " mouvement_solide_ ";
      int taille = tab_tcr.Taille();
      list <String_et_entier>::const_iterator il = lis_centre_noeud.begin();
      for (int it=1; it<= taille; it++)
       	{ switch (tab_indic(it))
       	   { case 1: // cas d'une translation
       	      { cout << " translation_= " <<  tab_tcr(it);
       	        break;
       	      }
       	     case 2: // cas d'une nouvelle définition du centre
       	      { cout << " centre_= " <<  tab_tcr(it);
       	        break;
       	      }
       	     case 3: // cas d'une rotation
       	      { cout << " rotation_= " <<  tab_tcr(it);
       	        break;
       	      }
       	     case 4: // cas d'une rotation
       	      { cout << " centre_a_un_noeud=_nom_maille " << (*il).nom 
       	             << " numnoeud= " << (*il).n;
       	        il++;     
       	        break;
       	      }
       	     case 5: // cas d'une homothétie
       	      { cout << " homothetie_= " << tab_tcr(it);
       	        break;
       	      }
       	   }; // fin du switch: switch (tab_indic)
       	};
      cout << " "; 	
	};

	
// Realise l'egalite 		
MvtSolide& MvtSolide::operator= (const MvtSolide& mvt)
  { tab_tcr = mvt.tab_tcr; 
    tab_indic = mvt.tab_indic;
    lis_centre_noeud = mvt.lis_centre_noeud;
    return *this;
  };
  	
//Surcharge d'operateur logique
bool MvtSolide::operator == (const MvtSolide& mvt) const
  { return ((tab_tcr == mvt.tab_tcr) && (tab_indic == mvt.tab_indic)
            && (lis_centre_noeud == mvt.lis_centre_noeud));
  };	 
               
// lecture des mouvements solides si nécessaire
void MvtSolide::Lecture_mouvements_solides(UtilLecture * entreePrinc)
 { if (strstr(entreePrinc->tablcar,MotCleMvtSolide().c_str())!=NULL)
    // si on change le mot clé ne pas oublier de changer la fonction MotCleMvtSolide() 
   { if (ParaGlob::NiveauImpression() >= 6) 
        cout << " lecture des mouvements solides  " << endl ;   
     entreePrinc->NouvelleDonnee();
     string nom;
     int dima = ParaGlob::Dimension();
     
     list <Coordonnee> list_tcr; // liste des translations, centres et rotation
     list <int> list_indic;  // indic le type de transformation lue: 1 pour translation
                             // 2 pour centre et 3 pour rotation
     while (strstr(entreePrinc->tablcar,"fin_mouvement_solide_")==NULL)
       {*(entreePrinc->entree) >> nom;
        if (nom == "translation_=")
          { Coordonnee trans(dima); 
            trans.Lecture(*entreePrinc);
            list_tcr.push_back(trans); 
            list_indic.push_back(1);
        	};
        if (nom == "centre_=")
          { Coordonnee centre(dima); 
            centre.Lecture(*entreePrinc);
            list_tcr.push_back(centre); 
            list_indic.push_back(2);
        	};
        if (nom == "rotation_=")
          { Coordonnee rot(3); // le vecteur rotation est systématiquement en 3D
            rot.Lecture(*entreePrinc);
            if (strstr(entreePrinc->tablcar,"en_degre_")!=0)
              // on transforme en radian
              { rot *= ConstMath::Pi / 180.;};
            list_tcr.push_back(rot); 
            list_indic.push_back(3);
            // on regarde s'il s'agit de degré éventuellement
          };//-- fin du cas de la rotation
        if (nom == "centre_noeud_=")
          { // cas d'un centre donné par un numero de noeud
            String_et_entier nu;
            string nom_mail;
            *(entreePrinc->entree) >> nom_mail;
            if (nom_mail == "nom_mail=")
                { // cas où il y a un nom de maillage
                  *(entreePrinc->entree) >> nu.nom; // lecture du nom
                  *(entreePrinc->entree) >> nu.n; // lecture du numero de noeud
                }
            else 
            	{ // sinon cela veut dire que l'on vient de lire un numéro de noeud du premier maillage
            	  nu.nom = "";
            	  nu.n = ChangeEntier(nom_mail); 	
            	}; 
            lis_centre_noeud.push_back(nu);	   
            list_tcr.push_back(Coordonnee());  // un centre par défaut 
            list_indic.push_back(4);
        	 };
        if (nom == "homothetie_=")
          { Coordonnee homothetie(3); // le vecteur homothetie est systématiquement en 3D
            // ainsi on peut avoir une dilatation différentielle suivant les 3 axes
            homothetie.Lecture(*entreePrinc);
            list_tcr.push_back(homothetie);
            list_indic.push_back(5);
          };//-- fin du cas d'une homothetie
        entreePrinc->NouvelleDonnee();
       }; //-- fin du while
     // on passe le mot clé de fin
     *(entreePrinc->entree) >> nom;     
//     entreePrinc->NouvelleDonnee();  
     // enregistrement des mouvements solides
     int taille = list_tcr.size();
     tab_tcr.Change_taille(taille);
     tab_indic.Change_taille(taille);
     list <Coordonnee>::iterator il,ilfin=list_tcr.end();
     list <int>::iterator ii,iifin=list_indic.end();
     int i =1; ii=list_indic.begin(); // init pour la boucle qui suit
     
     for (il=list_tcr.begin();il != ilfin; il++,i++,ii++)
     	{tab_tcr(i)=(*il);
     	 tab_indic(i)=(*ii);
     	};
   }; //-- fin du if indiquant le cas ou il y a des mouvements solides
   
 };
 
// retour de la première rotation: en fait l'axe de rotation
const Coordonnee& MvtSolide::Premiere_rotation()const
	{  Coordonnee axe; // le vecteur de retour
       int taille = tab_tcr.Taille();
       int dima = ParaGlob::Dimension();
       for (int it=1; it<= taille; it++)
       	{ switch (tab_indic(it))
       	   { case 3: // cas d'une rotation
       	      { switch (dima)
                 {case 1:  
                   	{cout << "\n erreur : pas de rotation en 1D !! "
                   	      << "\n MvtSolide::Premiere_rotation(..";
                   	 Sortie(1); break;    
                   	}
                  case 2 : case 3:    return tab_tcr(it);
                 }
       	        break;
       	      } // fin du cas 3
       	   }; // fin du switch: switch (tab_indic)
       	}; // fin de la boucle sur tab_indic : for (int it=1; it<= taille; it++) 
       // normalement on ne passe pas ici sauf s'il n'y a pas d'axe
       return tab_tcr(1); // pour faire taire le compilateur
     };
// indique s'il existe seulement une seule rotation
bool MvtSolide::ExisteUneSeuleRotation()const
	{  int nb_rot=0;
       int taille = tab_tcr.Taille();
       int dima = ParaGlob::Dimension();
       for (int it=1; it<= taille; it++)
       	{ switch (tab_indic(it))
       	   { case 3: // cas d'une rotation
       	      { switch (dima)
                 {case 1: break; // on ne fait rien
                  case 2 : case 3:  nb_rot++;
                 }
       	        break;
       	      } // fin du cas 3
       	   }; // fin du switch: switch (tab_indic)
       	}; // fin de la boucle sur tab_indic : for (int it=1; it<= taille; it++) 
       // retour
       return (nb_rot == 1);
     };

// application des mouvements solides aux points transmis et retour du point
// transformé
Coordonnee & MvtSolide::AppliqueMvtSolide (Coordonnee & M) const 
     { // on passe en revue l'ensemble des transformations
       int taille = tab_tcr.Taille();
       int dima = ParaGlob::Dimension();
       #ifdef MISE_AU_POINT
         if (list_coor_centre_noeud.size() != lis_centre_noeud.size())
         	{ cout << "\n erreur : le nombre de centre noeud disponible " 
         	       << list_coor_centre_noeud.size() << " est inferieur au nombre defini par la condition"
         	       << " lineaire qui est " << lis_centre_noeud.size() << endl;
         	  Sortie(1);     
         	};
       #endif
       list <Coordonnee>::const_iterator icoor_centre = list_coor_centre_noeud.begin();
       Coordonnee centre(dima); // par défaut le centre 
       for (int it=1; it<= taille; it++)
       	{ switch (tab_indic(it))
       	   { case 1: // cas d'une translation
       	      { M += tab_tcr(it);
       	        break;
       	      }
       	     case 2: // cas d'une nouvelle définition du centre
       	      { centre += tab_tcr(it);
       	        break;
       	      }
       	     case 3: // cas d'une rotation
       	      { switch (dima)
                 {case 1: break; // on ne fait rien
                  case 2: // on tourne autour de z
            	      { double theta = tab_tcr(it)(3); 
            	        double costheta = cos(theta);
            	        double sintheta = sin(theta);
            	        // le point initial : M , le centre de rotation C
            	        // le point final : Mnew = rotation de CM + les coordonnées du centre
                     Coordonnee CM(M-centre); // création de CM
                  	  M(1)=CM(1)*costheta + CM(2)*sintheta + centre(1);
                  	  M(2)=-CM(1)*sintheta + CM(2)*costheta + centre(2);
                     break;
            	      }
                  case 3: // on a trois rotation qui sont successivement suivant x puis y puis z
             	     { Coordonnee& rot = tab_tcr(it); // pour simplifier
            	        // le point initial : M , le centre de rotation C
            	        // le point final : Mnew = rotation de CM + les coordonnées du centre
             	       for (int i=1;i<=3;i++) // on boucle sur les trois directions
             	        // une rotation autour de xi si l'angle est non nulle
             	        if (!(Dabs(rot(i)) <= ConstMath::trespetit))
            	          { // on définit 3 index fonctions du i
               	         int ix=1; int iy=2; int iz=3;
               	         switch (i) // uniquement pour 2 et 3, le cas 1 étant celui de l'initialisation 
               	                 // précédente
               	      	   { case 2: ix = 2; iy = 1; iz = 3; break;
               	      	     case 3: ix = 3; iy = 1; iz = 2; break;
                          };
                         Coordonnee CM(M-centre); // création de CM
               	         double theta = rot(i); 
               	         double costheta = cos(theta);
               	         double sintheta = sin(theta);
               	         // transformation
                     	   M(iy)=CM(iy)*costheta + CM(iz)*sintheta + centre(iy);
                     	   M(iz)=-CM(iy)*sintheta + CM(iz)*costheta + centre(iz);
                     	   M(ix)=CM(ix) + centre(ix);
            	          };
                     break;
                   }
                 }; //-- fin du case sur la dimension: switch (dima)
       	        break;
       	      } // fin du cas 3
       	     case 4: // cas d'un  centre définie par une position de noeud
       	      { centre = (*icoor_centre);
       	        break;
       	      }
             case 5: // on fait une homothétie
            	 { // on se sert du centre pour le centre de l'homothétie
                Coordonnee& scale = tab_tcr(it); // pour simplifier
                Coordonnee CM(M-centre); // création de CM
                switch (dima)
                 {case 3: M(3) = centre(3) + CM(3) * scale(3);
                  case 2: M(2) = centre(2) + CM(2) * scale(2);
                  case 1: M(1) = centre(1) + CM(1) * scale(1);
            	    };
       	        break;
              }
       	   }; // fin du switch: switch (tab_indic)
       	}; // fin de la boucle sur tab_indic : for (int it=1; it<= taille; it++) 
       // retour du point transformé
       return M;
     };
     
// idem que précédemment, mais avec un coefficient d'intensité
// dans le cas d'une translation, celle-ci est multiplié par le coef
// dans le cas d'un nouveau centre, sa position n'est pas affectée par le coef
// dans le cas d'une rotation, celle-ci est multiplié par le coef
// dans le cas d'une homothétie: celle-ci est multiplié par le coef
Coordonnee & MvtSolide::AppliqueMvtSolide (Coordonnee & M, const double& coef) const 
     { // on passe en revue l'ensemble des transformations
       int taille = tab_tcr.Taille();
       int dima = ParaGlob::Dimension();
       #ifdef MISE_AU_POINT
         if (list_coor_centre_noeud.size() != lis_centre_noeud.size())
         	{ cout << "\n erreur : le nombre de centre noeud disponible " 
         	       << list_coor_centre_noeud.size() << " est inferieur au nombre defini par la condition"
         	       << " lineaire qui est " << lis_centre_noeud.size() << endl;
         	  Sortie(1);     
         	};
       #endif
       list <Coordonnee>::const_iterator icoor_centre = list_coor_centre_noeud.begin();
       Coordonnee centre(dima); // par défaut le centre 
       for (int it=1; it<= taille; it++)
       	{ switch (tab_indic(it))
       	   { case 1: // cas d'une translation
       	      { M += coef * tab_tcr(it) ;
       	        break;
       	      }
       	     case 2: // cas d'une nouvelle définition du centre
       	      { centre += tab_tcr(it);
       	        break;
       	      }
       	     case 3: // cas d'une rotation
       	      { switch (dima)
                 {case 1: break; // on ne fait rien
                  case 2: // on tourne autour de z
            	      { double theta = coef * tab_tcr(it)(3); 
            	        double costheta = cos(theta);
            	        double sintheta = sin(theta);
            	        // le point initial : M , le centre de rotation C
            	        // le point final : Mnew = rotation de CM + les coordonnées du centre
                     Coordonnee CM(M-centre); // création de CM
                  	  M(1)=CM(1)*costheta + CM(2)*sintheta + centre(1);
                  	  M(2)=-CM(1)*sintheta + CM(2)*costheta + centre(2);
                     break;
            	      }
                  case 3: // on a trois rotation qui sont successivement suivant x puis y puis z
             	     { Coordonnee rot = coef * tab_tcr(it); // pour simplifier
            	        // le point initial : M , le centre de rotation C
            	        // le point final : Mnew = rotation de CM + les coordonnées du centre
             	       for (int i=1;i<=3;i++) // on boucle sur les trois directions
             	        // une rotation autour de xi si l'angle est non nulle
             	        if (!(Dabs(rot(i)) <= ConstMath::trespetit))
            	          { // on définit 3 index fonctions du i
               	         int ix=1; int iy=2; int iz=3;
               	         switch (i) // uniquement pour 2 et 3, le cas 1 étant celui de l'initialisation 
               	                 // précédente
               	      	   { case 2: ix = 2; iy = 1; iz = 3; break;
               	      	     case 3: ix = 3; iy = 1; iz = 2; break;
               	      	   };
                         Coordonnee CM(M-centre); // création de CM
// double rayon0 = CM.Norme();                        
               	         double theta = rot(i); 
               	         double costheta = cos(theta);
               	         double sintheta = sin(theta);
               	         // transformation
                     	   M(iy)=CM(iy)*costheta + CM(iz)*sintheta + centre(iy);
                     	   M(iz)=-CM(iy)*sintheta + CM(iz)*costheta + centre(iz);
                     	   M(ix)=CM(ix) + centre(ix);
// CM = M-centre;                    	 
// double rayon1 = CM.Norme();
// if (Dabs(rayon1-rayon0)>= ConstMath::pasmalpetit)
//   cout << "\n rayon1= " << rayon1 << " rayon0= " << rayon0;                    	 
            	          };
                     break;
             	     }
                 }; //-- fin du case sur la dimension: switch (dima)
       	        break;
       	      } // fin du cas 3
       	     case 4: // cas d'un  centre définie par une position de noeud
       	      { centre = (*icoor_centre);
       	        break;
       	      }
             case 5: // on fait une homothétie
            	 { // on se sert du centre pour le centre de l'homothétie
                Coordonnee scale = coef * tab_tcr(it); // pour simplifier
                Coordonnee CM(M-centre); // création de CM
                switch (dima)
                 {case 3: M(3) = centre(3) + CM(3) * scale(3);
                  case 2: M(2) = centre(2) + CM(2) * scale(2);
                  case 1: M(1) = centre(1) + CM(1) * scale(1);
            	    };
       	        break;
              }
       			
       	   }; // fin du switch: switch (tab_indic)
       	}; // fin de la boucle sur tab_indic : for (int it=1; it<= taille; it++) 
       // retour du point transformé
       return M;
     };

// affichage et definition interactive des commandes
void MvtSolide::Info_commande_MvtSolide(ostream & sort)
{  // ---------- définition de rotations et translation solide ----------

   //On va proposer un menu
   string rep=" ";
   sort << "    mouvement_solide_        ";
   while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0"))
      {
       try 
        { 
        cout 
           << "\n (0 ou f)  (fin)               "
           << "\n (1)  translation     "
           << "\n (2)  rotation "
           << "\n (3)  nouveau centre absolu "
           << "\n (4)  centre avec un noeud " 
           << "\n (5)  homothetie "
           << "\n (6 ou ? ) informations  "
           << "\n  ";
        rep = lect_return_defaut(false,"f");
        if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe
          break;
        int num = ChangeEntier(rep);
        if (Minuscules(rep) == "?")
          num = 6;
        bool choix_valide=false;
        if ((num >= 0)&&(num<=6))
             { choix_valide=true; }
        else { cout << "\n Erreur on attendait un entier entre 0 et 6 !!, "
                    << "\n redonnez une bonne valeur"
                    << "\n ou taper f ou 0 pour arreter le programme"; 
               choix_valide=false;
             }
        switch (num)
         { case 0:  // sortie
             { break;} // normalement cela a déjà été filtré avant
           case 1:  // translation
             { int dim = ParaGlob::Dimension();
               Coordonnee trans(dim);
               cout << "\n lecture du vecteur deplacement ("<<dim<<" reels) ? ";
               trans.Lecture();
               sort << "\n      translation_=  ";
               trans.Affiche(sort,dim);
               break;
              }
           case 2:  // rotation
             { int dim = 3; // la dimension est systématiquement 3 ParaGlob::Dimension();
               Coordonnee trans(dim);
               cout << "\n rotation en radian par defaut, \n voulez vous des degres (rep o ou n) ";
               string rop = lect_return_defaut(true,"n");
               bool deg = false;
               if (rop == "o") deg = true;
               // on sépare en fonction de la dimension de l'espace
               switch (ParaGlob::Dimension())
                { case 1: {cout << "\n pas de rotation possible en dimension 1 ! "; break;}
                  case 2: // la rotation est uniquement autour de z
                   { cout << "\n lecture de l'angle de rotation autour de z: 1 reels) ? ";
                     trans(3)=lect_double();
                     break;
                   }
                  case 3:
                   {cout << "\n lecture du vecteur rotation ("<<dim<<" reels) ? ";
                    trans.Lecture();
                    sort << "\n      rotation_=  ";
                    trans.Affiche(sort,dim);
                    break;
                   }
                  default: break; // a priori il n'y a pas d'autre cas
                };
               // affichage
               sort << "\n      rotation_=  ";
               trans.Affiche(sort,dim);
               if (deg)
                 sort << " en_degre_ ";
               break;
              }
           case 3:  // nouveau centre absolu
             { int dim = ParaGlob::Dimension();
               Coordonnee trans(dim);
               cout << "\n lecture du nouveau centre absolu ("<<dim<<" reels) ? ";
               trans.Lecture();
               sort << "\n      centre_=  ";
               trans.Affiche(sort,dim);
               break;
              }
           case 4:  // centre avec un noeud
             { cout << "\n lecture du nouveau noeud centre (un numero de noeud) ? ";
               int num_noeud=0;
               num_noeud=(int)lect_double();
               cout << "\n un nom de maillage (si aucune rep: \"_\" ) ? ";
               string nom_mail="_";
               nom_mail=lect_chaine();
               sort << "\n      centre_noeud_=  ";
               if (nom_mail != "_")
                 sort << " nom_mail= "<< nom_mail<< "  ";
               sort << num_noeud << " ";
               break;
              }
           case 5:  // homothétie
             { int dim = ParaGlob::Dimension();
               Coordonnee scale(dim);
               cout << "\n lecture du vecteur homothetie ("<<dim<<" reels) ? ";
               scale.Lecture();
               sort << "\n      homothetie_=  ";
               scale.Affiche(sort,dim);
               break;
              }
           case 6:  // information
             { cout << "\n informations sur les mouvements solides";
   	           cout << "\n#     --- definition optionnelle de mouvements sodides appliquees au solide ---"
                    << "\n    mouvement_solide_              #  mot cle pour definir le debut des mouvements solides "
                    << "\n      translation_=  1.   0.  0.   # exemple d'une translation sur x  "
                    << "\n      rotation_=     0.1  0.  0.3  # rotation selon x de 0.1 radian, puis selon z (selon y nulle) "
                    << "\n      rotation_=     0.1  0.  0.3  en_degre_  # idem mais en degre "
                    << "\n      centre_=      0.1  0.1  0.2  # def d'un nouveau centre de rotation pour les rotations a suivre "
                    << "\n      centre_noeud_=   3  # idem mais ici le centre de rotation sera le noeud 3 "
                    << "\n      centre_noeud_= nom_mail= trap  3  # idem avec un nom de maillage (trap) "
                    << "\n      homothetie_=  0.8  1.  1.1   # dilatation -20% sur x, rien sur y, +10% en z "
                    << "\n    fin_mouvement_solide_          # mot de fin  de mouvement solide \n\n"
                    << "\n#   -- il est possible d'enchainer plusieurs mouvements solides a suivre qui sont dans ce cas execute dans le"
                    << "\n#   le meme ordre que la declaration\n" 
                    << "\n#   -- concernant les rotations: "
                    << "\n#   si l'espace est 1D ==> aucune modification du maillage  "
                    << "\n#   si l'espace est 2D ==> la rotation prise en compte est uniquement autour de z "
                    << "\n#   si l'espace est 3D ==> rotation (si l'angle est non nulle) suivant x puis suivant y puis suivant z ";
               break;
              }
           default:
             cout << "\n le cas "<<rep<<" n'est pas  traite !!, bizarre, il faut se plaindre !! ";
          };
        }    
       catch (ErrSortieFinale)
            // cas d'une direction voulue vers la sortie
            // on relance l'interuption pour le niveau supérieur
          { ErrSortieFinale toto;
            throw (toto);
          }
       catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
        {  cout << "\n Erreur on attendait un des mots cles proposes !!, "
                << "\n redonnez une bonne valeur"
                << "\n ou taper f ou 0 pour sortir "; 
        };
      }; //-- fin du while
   sort << "\n    fin_mouvement_solide_    ";

};
    
// effacement du mouvement solide actuel
void MvtSolide::EffaceMvtSolide()
	{ tab_tcr.Libere(); tab_indic.Libere();
	  lis_centre_noeud.erase(lis_centre_noeud.begin(),lis_centre_noeud.end());
	  list_coor_centre_noeud.erase(list_coor_centre_noeud.begin(),list_coor_centre_noeud.end());
	};
    
		 
// surcharge de l'operateur de lecture typée
istream & operator >> (istream & entree, MvtSolide & mvt)
  { // vérification du type
    int taille = 0;
    string type;
    entree >> type;
    if (type != "MvtSolide_") 
      { cout << "\n erreur en lecture d'un mouvement solide, on a lue " << type 
             << " au lieu de MvtSolide_ ";
        Sortie(1);
      };
    // lecture de la taille, on se sert de type pour passer la chaine Taille:
    entree >> type >> taille;
    mvt.tab_tcr.Change_taille(taille);
    mvt.tab_indic.Change_taille(taille);
    for (int it=1; it<= taille; it++)
      { entree >> mvt.tab_indic(it) >> mvt.tab_tcr(it);};
    return entree;      
  };
  
// surcharge de l'operateur d'ecriture typée
ostream & operator << ( ostream & sort,const  MvtSolide & mvt)
  { // tout d'abord un indicateur donnant le type
    int taille = mvt.tab_tcr.Taille();
    sort << " MvtSolide_  taille: " << taille ; 
    for (int it=1; it<= taille; it++)
      { sort << " " << mvt.tab_indic(it) << " " << mvt.tab_tcr(it) << " ";};
    return sort;      
  };
    
