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

#include <list>
#include "ConstMath.h"

    // CONSTRUCTEURS :
    
// constructeur par défaut 
Poly_Lagrange::Poly_Lagrange(string nom) :
 Courbe1D(nom,COURBE_POLY_LAGRANGE)
 ,points(),der_init(0),der_finale(0),indice_precedant(1) 
  {};
        
// fonction d'un tableau de points
Poly_Lagrange::Poly_Lagrange(Tableau <Coordonnee2>& pt,string nom):
 Courbe1D(nom,COURBE_POLY_LAGRANGE)
 ,points(pt),der_init(0),der_finale(0),indice_precedant(1) 
  {  // On vérifie que la dérivée n'est pas infinie c'est-à-dire que 
     // deux abscices ne sont pas identiques 
     // on vérifie également par la même que les absisses sont croissantes
     int taille = points.Taille();
     for (int i=1;i<taille;i++)
       if ((points(i+1)(1)-points(i)(1)) < ConstMath::pasmalpetit)
         { cout << "\n erreur en definition des points pour une COURBE_POLY_LAGRANGE "
                << " la distance entre les abscisses de deux points consecutifs est"
                << " trop faible ";
           cout << " \n points 1 : " << points(i+1) << ", point 2 : " << points(i);    
           cout << "\n Poly_Lagrange::Poly_Lagrange(Tableau <Coordonnee2> pt,string nom) "
                << endl ;
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1); 
           }         
      // calcul de la dérivée initiale et de la dérivée finale
      der_init = (points(2)(2)-points(1)(2)) / (points(2)(1)-points(1)(1));
      der_finale = (points(taille)(2)-points(taille-1)(2)) 
                    / (points(taille)(1)-points(taille-1)(1));
    
  };

    
    // de copie
Poly_Lagrange::Poly_Lagrange(const Poly_Lagrange& Co) :
 Courbe1D(Co)
 ,points(Co.points),der_init(Co.der_init),der_finale(Co.der_finale)
 ,indice_precedant(Co.indice_precedant) 
  {};
    // de copie à partir d'une instance générale
Poly_Lagrange::Poly_Lagrange(const Courbe1D& Coo) :
 Courbe1D(Coo),indice_precedant(1)
  { if (Coo.Type_courbe() != COURBE_POLY_LAGRANGE)
      { cout << "\n erreur dans le constructeur de copie pour une courbe COURBE_POLY_LAGRANGE"
             << " a partir d'une instance generale ";
        cout << "\n Poly_Lagrange::Poly_Lagrange(const Courbe1D& Co) ";
           Sortie(1);          
          };
    // définition des données
    Poly_Lagrange & Co = (Poly_Lagrange&) Coo;
    points = Co.points; der_init = Co.der_init; der_finale = Co.der_finale;      
  };

    // DESTRUCTEUR :
Poly_Lagrange::~Poly_Lagrange() 
  {};
    
    // METHODES PUBLIQUES :
    
    // --------- virtuelles ---------
    
    // affichage de la courbe
void Poly_Lagrange::Affiche() const
  { cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref; // Poly_Lagrange ";
    cout << "\n Debut_des_coordonnees_des_points";
    int taille = points.Taille();
    for (int i=1;i<=taille;i++)
      cout << points(i);
    cout << "\nFin_des_coordonnees_des_points ";
   };

    // vérification que tout est ok, pres à l'emploi
    // ramène true si ok, false sinon
bool Poly_Lagrange::Complet_courbe()const
 { bool ret = Complet_var(); // on regarde du coté de la classe mère tout d'abord
   // puis les variables propres
   if (points.Taille() == 0) ret = false;
   if (!ret && (ParaGlob::NiveauImpression() >0))
      { cout << "\n ***** la courbe n'est pas complete ";
        this->Affiche();
        };
   return ret;
  } ;

    // Lecture des donnees de la classe sur fichier
    // le nom passé en paramètre est le nom de la courbe
    // s'il est vide c-a-d = "", la methode commence par lire le nom sinon
    // ce nom remplace le nom actuel
void Poly_Lagrange::LectDonnParticulieres_courbes(const string& nom,UtilLecture * entreePrinc)
  {  if (nom == "")  { *(entreePrinc->entree) >> nom_ref;}
     else {nom_ref=nom;};
     entreePrinc->NouvelleDonnee();  // lecture d'une nouvelle ligne
     // on regarde s'il n'y a pas un décalage initiale
     double decalx=0; double decaly=0.; 
     if((strstr(entreePrinc->tablcar,"decalageX_=")!=0) 
        || (strstr(entreePrinc->tablcar,"decalageY_=") != 0))    
      { string nom_lu;
        if(strstr(entreePrinc->tablcar,"decalageX_=")!=0)
        // cas ou on veut définir un décalage initiale
         { *(entreePrinc->entree) >> nom_lu >> decalx;
           if (nom_lu != "decalageX_=")
           { cout << "\n erreur en lecture du decalage en x initiale  "
                  << " on attendait la chaine: decalageX_= et on a lue " << nom_lu;
             entreePrinc->MessageBuffer("**erreur1 Poly_Lagrange::LectureDonneesParticulieres**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);          
           };
         };
        if(strstr(entreePrinc->tablcar,"decalageY_=")!=0)
        // cas ou on veut définir un décalage initiale
         { *(entreePrinc->entree) >> nom_lu >> decaly;
           if (nom_lu != "decalageY_=")
            { cout << "\n erreur en lecture du decalage en y initiale  "
                   << " on attendait la chaine: decalageY_= et on a lue " << nom_lu;
              entreePrinc->MessageBuffer("**erreur1 Poly_Lagrange::LectureDonneesParticulieres**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);          
             };
          };
        // si on a lue on passe une nouvelle ligne  
        entreePrinc->NouvelleDonnee();  // lecture d'une nouvelle ligne
      };
     // on définit une liste pour la lecture des coordonnées
     list<Coordonnee2> pointlec;
     // un indicateur pour la fin de la lecture
     int fin_lecture = 0;
     // on lit l'entête
     if(strstr(entreePrinc->tablcar,"Debut_des_coordonnees_des_points")==0)
         { cout << "\n erreur en lecture des points pour une courbe poly lineaire "
                << " la chaine : Debut_des_coordonnees_des_points n'est pas presente ";
           entreePrinc->MessageBuffer(" ");     
           cout << "\n Poly_Lagrange::LectureDonneesParticulieres "
                << "(UtilLecture * entreePrinc) " << endl ;
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);          
          }
     entreePrinc->NouvelleDonnee();  // lecture d'une nouvelle ligne
     // la boucle de lecture des points
     while (fin_lecture == 0)
       { // lecture
//         entreePrinc->NouvelleDonnee();  // lecture d'une nouvelle ligne
         if(strstr(entreePrinc->tablcar,"Fin_des_coordonnees_des_points")==0)
           // cas ou ce n'est pas la fin de la lecture des coordonnées
           { Coordonnee2 M;
             *(entreePrinc->entree) >> M;
             // comme le décalage doit-être soustrait à x, on ajoute le décalage au point
             M(1) += decalx;
             // idem pour y car le décalage est en sortie
             M(2) += decaly;
             pointlec.push_back(M); 
             entreePrinc->NouvelleDonnee();  // lecture d'une nouvelle ligne
            }
         else
           // on est à la fin de la lecture des coordonnées  
           fin_lecture = 1;
        }
     // écriture dans le tableau
     points.Change_taille((int)pointlec.size());
     list<Coordonnee2>::iterator indice,indice_fin;
     indice_fin = pointlec.end();
     int if1;
     for (indice = pointlec.begin(),if1=1; indice!= indice_fin; indice++,if1++)
       points(if1)= *indice;
     // On vérifie que la dérivée n'est pas infinie c'est-à-dire que 
     // deux abscices ne sont pas identiques 
     // on vérifie également par la même que les absisses sont croissantes
     int taille = points.Taille();
     for (int i=1;i<taille;i++)
       if ((points(i+1)(1)-points(i)(1)) < ConstMath::pasmalpetit)
         { cout << "\n erreur en definition des points pour une courbe COURBE_POLY_LAGRANGE "
                << " la distance entre les abscisses de deux points consecutifs est"
                << " trop faible ";
           cout << " \n points 1 : " << points(i+1) << ", point 2 : " << points(i);    
           cout << "\n Poly_Lagrange::LectureDonneesParticulieres "
                << "(UtilLecture * entreePrinc) " << endl ;
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1); 
           }         
      // calcul de la dérivée initiale et de la dérivée finale
      der_init = (points(2)(2)-points(1)(2)) / (points(2)(1)-points(1)(1));
      der_finale = (points(taille)(2)-points(taille-1)(2)) 
                    / (points(taille)(1)-points(taille-1)(1));
   };
    
// def info fichier de commande
void Poly_Lagrange::Info_commande_Courbes1D(UtilLecture & entreePrinc) 
  {  
     ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
     sort << "\n#............................................"
          << "\n# exemple de definition d'une courbe COURBE_POLY_LAGRANGE|" 
          << "\n#"
          << "\n courbe_de_charge    COURBE_POLY_LAGRANGE  # nom de la courbe puis le type de la courbe"
          << "\n      # def des points constituants la courbe "
          << "\n          Debut_des_coordonnees_des_points"
          << "\n           Coordonnee dim= 2 0. 1. # chaque point est defini par le mot cle Coordonnee"
          << "\n           Coordonnee dim= 2 1. 1. # puis la dimension, ici 2 , puis l'absisse et l'ordonnee"
          << "\n          Fin_des_coordonnees_des_points "
          << "\n#   Il est egalement possible d'introduire un decalage en x et y. Le decalage en x "
          << "\n#   est soustrait a la valeur courante de x, tandis que le decalage en y est ajoute "
          << "\n#   a la valeur finale de la fonction. Autre exemple de syntaxe avec decalage "
          << "\n courbe_2    COURBE_POLY_LAGRANGE  # nom de la courbe puis le type de la courbe"
          << "\n      decalageX_= 10. decalageY_= 3. "
          << "\n      # def des points constituants la courbe "
          << "\n          Debut_des_coordonnees_des_points"
          << "\n           Coordonnee dim= 2 0. 0. "
          << "\n           Coordonnee dim= 2 1. 0.5  "
          << "\n          Fin_des_coordonnees_des_points "
        << endl;
   };        
    
    // ramène la valeur 
double Poly_Lagrange::Valeur(double x)  
  { //int taille = points.Taille();
  
  
  
    //tout d'abord on regarde s'il est en dehors des bornes
    if (x < points(1)(1)) 
       {indice_precedant=1;
        return (points(1)(2) + (x-points(1)(1))*der_init);
       };
    int taille = points.Taille();   
    if (x > points(taille)(1))
       {indice_precedant=1; // comme c'est le dernier point on met à 1 car 
        // de toute manière cela ne sert à rien de continuer
        return (points(taille)(2) + (x-points(taille)(1))*der_finale);
       };
    // maintenant on cherche le couple de xi qui encadre le x
    int indice=0;bool trouve=false;
    // on commence tout d'abord à chercher à partir du précédent indice
    // s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
    if (x >= points(indice_precedant)(1))
      for (int indic=indice_precedant;indic<taille;indic++)
       if (x <= points(indic+1)(1)) {trouve=true;indice=indic; break;};
    // sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
    // on repart à partir de 0  !! ***** a optimiser par dichotomie *****  
    if (!trouve)
     { // cas où on n'a pas trouver après l'indice
       for (int indic = 1; indic <indice_precedant;indic++)
       if (x <= points(indic+1)(1)) {trouve=true;indice = indic; break;};
     };
    // gestion d'erreur 
    if (!trouve)
     { cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe COURBE_POLY_LAGRANGE "
            << "\n x demandee: " << x
            << "\n  double Poly_Lagrange::Valeur(double x) ";
       cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref; 
       Sortie(1);           
      };
    // calcul du y
    indice_precedant = indice;
    return (((x-points(indice)(1)) * points(indice+1)(2) 
         + (points(indice+1)(1)-x) * points(indice)(2)) /
         (points(indice+1)(1)-points(indice)(1)));
  };

    // ramène la valeur et la dérivée en paramètre
Courbe1D::ValDer Poly_Lagrange::Valeur_Et_derivee(double x)  
  {  ValDer ret; // def de la valeur de retour
    //tout d'abord on regarde s'il est en dehors des bornes
    if (x < points(1)(1)) 
       { ret.valeur = (points(1)(2) + (x-points(1)(1))*der_init);
         ret.derivee = der_init;
         indice_precedant=1;
         return ret;
        } 
    int taille = points.Taille();   
    if (x > points(taille)(1))
       { ret.valeur = (points(taille)(2) + (x-points(taille)(1))*der_finale);
         ret.derivee = der_finale;
         indice_precedant=1;
         return ret;
        } 
    // maintenant on cherche le couple de xi qui encadre le x
    int indice;bool trouve=false;
    // on commence tout d'abord à chercher à partir du précédent indice
    // s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
    if (x >= points(indice_precedant)(1))
      for (indice=indice_precedant;indice<taille;indice++)
       if (x <= points(indice+1)(1)) {trouve=true;break;};
    // sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
    // on repart à partir de 0  !! ***** a optimiser par dichotomie *****  
    if (!trouve)
     { // cas où on n'a pas trouver après l'indice
       for (indice = 1; indice <indice_precedant;indice++)
       if (x <= points(indice+1)(1)) {trouve=true;break;};
     };
    // gestion d'erreur 
    if (!trouve)
     { cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe COURBE_POLY_LAGRANGE "
            << "\n x demandee: " << x
            << "\n  double Poly_Lagrange::Valeur_Et_derivee(... ";
       cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref; 
       Sortie(1);           
      };
    // calcul du y
    ret.valeur = (((x-points(indice)(1)) * points(indice+1)(2) 
         + (points(indice+1)(1)-x) * points(indice)(2)) /
         (points(indice+1)(1)-points(indice)(1)));
    ret.derivee =  (points(indice+1)(2)-points(indice)(2)) /
                   (points(indice+1)(1)-points(indice)(1));    
    return ret;
   };
    
    // ramène la dérivée 
double Poly_Lagrange::Derivee(double x)  
  { //tout d'abord on regarde s'il est en dehors des bornes
    if (x < points(1)(1)) 
    	{indice_precedant=1;
    	 return der_init;
    	}
    int taille = points.Taille();   
    if (x > points(taille)(1))
        {indice_precedant=1;return der_finale;};
    // maintenant on cherche le couple de xi qui encadre le x
    int indice;bool trouve=false;
    // on commence tout d'abord à chercher à partir du précédent indice
    // s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
    if (x >= points(indice_precedant)(1))
      for (indice=indice_precedant;indice<taille;indice++)
       if (x <= points(indice+1)(1)) {trouve=true;break;};
    // sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
    // on repart à partir de 0  !! ***** a optimiser par dichotomie *****  
    if (!trouve)
     { // cas où on n'a pas trouver après l'indice
       for (indice = 1; indice <indice_precedant;indice++)
       if (x <= points(indice+1)(1)) {trouve=true;break;};
     };
    // gestion d'erreur 
    if (!trouve)
     { cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe COURBE_POLY_LAGRANGE "
            << "\n x demandee: " << x
            << "\n  double Poly_Lagrange::Derivee(double x)  ";
       cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref; 
       Sortie(1);           
      };
    indice_precedant = indice;   
    // calcul du y'
    double derivee =  (points(indice+1)(2)-points(indice)(2)) /
                   (points(indice+1)(1)-points(indice)(1));    
    return derivee;
   };
        
    // ramène la valeur et les dérivées première et seconde en paramètre
Courbe1D::ValDer2 Poly_Lagrange::Valeur_Et_der12(double )
  {  ValDer2 ret; // def de la valeur de retour
     cout << "\n *** erreur pour l'instant pas implantee "
          << "\n Poly_Lagrange::Valeur_Et_der12(double x)";
     Sortie(1);     
    return ret;
   };
        
    // ramène la dérivée seconde
double Poly_Lagrange::Der_sec(double )
  {  cout << "\n *** erreur pour l'instant pas implantee "
          << "\n Poly_Lagrange::Valeur_Et_der12(double x)";
     Sortie(1);     
     return 0.;
   };
    
    // ramène la valeur si dans le domaine strictement de définition
    // si c'est inférieur au x mini, ramène la valeur minimale possible de y
    // si supérieur au x maxi , ramène le valeur maximale possible de y
Courbe1D::Valbool  Poly_Lagrange::Valeur_stricte(double x)  
  { Valbool ret; // def de la valeur de retour
    //tout d'abord on regarde s'il est en dehors des bornes
    if (x < points(1)(1)) 
       { ret.valeur = points(1)(1);
         ret.dedans = false;indice_precedant=1;
         return ret;
        } 
    int taille = points.Taille();   
    if (x > points(taille)(1))
       { ret.valeur = points(taille)(1);
         ret.dedans = false;indice_precedant=1;
         return ret;
        } 
    // maintenant on cherche le couple de xi qui encadre le x
    int indice;bool trouve=false;
    // on commence tout d'abord à chercher à partir du précédent indice
    // s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
    if (x >= points(indice_precedant)(1))
     for (indice=indice_precedant;indice<taille;indice++)
       if (x <= points(indice+1)(1)) {trouve=true;break;};
    // sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
    // on repart à partir de 0  !! ***** a optimiser par dichotomie *****  
    if (!trouve)
     { // cas où on n'a pas trouver après l'indice
       for (indice = 1; indice <indice_precedant;indice++)
       if (x <= points(indice+1)(1)) {trouve=true;break;};
     };
    // gestion d'erreur 
    if (!trouve)
     { cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe COURBE_POLY_LAGRANGE "
            << "\n x demandee: " << x
            << "\n  double Poly_Lagrange::Valeur_stricte(double x)  ";
       cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref; 
       Sortie(1);           
      };
    indice_precedant = indice;
    // calcul du y
    ret.valeur = (((x-points(indice)(1)) * points(indice+1)(2) 
         + (points(indice+1)(1)-x) * points(indice)(2)) /
         (points(indice+1)(1)-points(indice)(1)));
    ret.dedans = true;                  
    return ret;
   };
    
    // ramène la valeur et la dérivée si dans le domaine strictement de définition
    // si c'est inférieur au x mini, ramène la valeur minimale possible de y et Y' correspondant
    // si supérieur au x maxi , ramène le valeur maximale possible de y et Y' correspondant
Courbe1D::ValDerbool  Poly_Lagrange::Valeur_Et_derivee_stricte(double x)  
  { ValDerbool ret; // def de la valeur de retour
    //tout d'abord on regarde s'il est en dehors des bornes
    if (x < points(1)(1)) 
       { ret.valeur = points(1)(1);
         ret.derivee = der_init;
         ret.dedans = false;indice_precedant=1;
         return ret;
        } 
    int taille = points.Taille();   
    if (x > points(taille)(1))
       { ret.valeur = points(taille)(1);
         ret.derivee = der_finale;
         ret.dedans = false;indice_precedant=1;
         return ret;
        } 
    // maintenant on cherche le couple de xi qui encadre le x
    int indice;bool trouve=false;
    // on commence tout d'abord à chercher à partir du précédent indice
    // s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
    if (x >= points(indice_precedant)(1))
     for (indice=indice_precedant;indice<taille;indice++)
       if (x <= points(indice+1)(1)) {trouve=true;break;};
    // sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
    // on repart à partir de 0  !! ***** a optimiser par dichotomie *****  
    if (!trouve)
     { // cas où on n'a pas trouver après l'indice
       for (indice = 1; indice <indice_precedant;indice++)
       if (x <= points(indice+1)(1)) {trouve=true;break;};
     };
    // gestion d'erreur 
    if (!trouve)
     { cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe COURBE_POLY_LAGRANGE "
            << "\n x demandee: " << x
            << "\n  double Poly_Lagrange::Valeur_Et_derivee_stricte(double x)  ";
       cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref; 
       Sortie(1);           
      };
    indice_precedant = indice;
    // calcul du y
    ret.valeur = (((x-points(indice)(1)) * points(indice+1)(2) 
         + (points(indice+1)(1)-x) * points(indice)(2)) /
         (points(indice+1)(1)-points(indice)(1)));
    ret.derivee =  (points(indice+1)(2)-points(indice)(2)) /
                   (points(indice+1)(1)-points(indice)(1)); 
    ret.dedans = true;                  
    return ret;
   };
    
// méthode pour changer le tableau de points associé
void Poly_Lagrange::Change_tabPoints(Tableau <Coordonnee2>& pt)
  {  // changement des points
     points = pt;
     // On vérifie que la dérivée n'est pas infinie c'est-à-dire que 
     // deux abscices ne sont pas identiques 
     // on vérifie également par la même que les absisses sont croissantes
     int taille = points.Taille();
     for (int i=1;i<taille;i++)
       if ((points(i+1)(1)-points(i)(1)) < ConstMath::pasmalpetit)
         { cout << "\n erreur en definition des pointss pour une courbe poly COURBE_POLY_LAGRANGE "
                << " la distance entre les abscisses de deux points consecutifs est"
                << " trop faible ";
           cout << " \n points 1 : " << points(i+1) << ", point 2 : " << points(i);    
           cout << "\n Poly_Lagrange::Poly_Lagrange(Tableau <Coordonnee2> pt,string nom) "
                << endl ;
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1); 
           }         
      // calcul de la dérivée initiale et de la dérivée finale
      der_init = (points(2)(2)-points(1)(2)) / (points(2)(1)-points(1)(1));
      der_finale = (points(taille)(2)-points(taille-1)(2)) 
                    / (points(taille)(1)-points(taille-1)(1));
    
  };
    
    
	//----- lecture écriture de restart -----
	// cas donne le niveau de la récupération
    // = 1 : on récupère tout
    // = 2 : on récupère uniquement les données variables (supposées comme telles)
void Poly_Lagrange::Lecture_base_info(ifstream& ent,const int cas)
  { // on n'a que des grandeurs constantes
    if (cas == 1)
      { string nom;
        ent >> nom;  // "\n <COURBE_POLY_LAGRANGE>  "
 //       string nom1=nom.substr(nom.find(<)+1,nom.find(>)-1);
        // lecture et vérification de l'entête
        string type_courbe_a_lire('<'+Nom_Courbe1D(this->Type_courbe())+'>');
        if (nom != type_courbe_a_lire) //"Poly_Lagrange")
         { cout << "\n erreur dans la verification du type de courbe lue ";
           cout << "\n courbe en lecture: " << type_courbe_a_lire;    
           cout << "\n Poly_Lagrange::Lecture_base_info(... ";
           Sortie(1); 
           } 
        ent >> nom >> nom  >> der_init >> nom;  
        ent >> nom >> nom  >> der_finale >> nom; 
        ent >> nom; // "\n </COURBE_POLY_LAGRANGE>  " 
        // lecture des infos
        ent >> nom >> der_init >> nom >> der_finale;
        ent >> nom >>  points;
       }
   };

    // cas donne le niveau de sauvegarde
    // = 1 : on sauvegarde tout
    // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void Poly_Lagrange::Ecriture_base_info(ofstream& sort,const int cas)
  { // on n'a que des grandeurs constantes
    if (cas == 1)
      { sort << "\n <COURBE_POLY_LAGRANGE>  "
             << "\n <derivee_initiale_  present=\"1\"> " << der_init << "</derivee_initiale_>" 
             <<"    <derivee_finale_  present=\"1\"> " << der_finale <<" </derivee_finale_> ";
        sort << "\n les_points_: " << points;
        sort << "\n </COURBE_POLY_LAGRANGE>  ";
       }
   };
     
    // sortie du schemaXML: en fonction de enu 
void Poly_Lagrange::SchemaXML_Courbes1D(ofstream& sort,const Enum_IO_XML enu)
  {
	switch (enu)
	{ case XML_TYPE_GLOBAUX :
  	   {sort << "\n <!--  *************************** COURBE_POLY_LAGRANGE ***************************  -->"
  	         << "\n <!--  def d'un type contenant une valeur et un boolean  -->"
  	         << "\n    <xs:complexType name=\"valeurPlusBooleen\">"
  	         << "\n       <xs:simpleContent>"
  	         << "\n          <xs:extension base=\"xs:double\">" 
  	         << "\n              <xs:attribute name=\"present\" type=\"xs:boolean\"  />" 
  	         << "\n          </xs:extension>" 
  	         << "\n       </xs:simpleContent> "
  	         << "\n    </xs:complexType>"
  	         << "\n <!--  maintenant le type de la courbe  -->"
  	         << "\n<xs:complexType name=\"COURBE_POLY_LAGRANGE\" >"
  	         << "\n    <xs:annotation>"
  	         << "\n      <xs:documentation> courbe polylineaire 1D constituee de N points </xs:documentation>"
  	         << "\n    </xs:annotation>"
  	         << "\n    <xs:sequence>"
  	         << "\n        <xs:element  name=\"derivee_initiale_\"  type=\"valeurPlusBooleen\" />"
  	         << "\n        <xs:element  name=\"derivee_finale_\" type=\"valeurPlusBooleen\" />"
   	         << "\n        <xs:element  name=\"les_points\" type=\"COORDONNEE_2\"  minOccurs='0' maxOccurs=\"unbounded\" />"
  	         << "\n    </xs:sequence>"
  	         << "\n</xs:complexType>";
		 break;
		}
		case XML_IO_POINT_INFO :
		{
		 break;
		}
		case XML_IO_POINT_BI :
		{
		 break;
		}
		case XML_IO_ELEMENT_FINI :
		{
		 break;
		}
	};		
  };
