
// 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/>.

/************************************************************************
 *     DATE:        23/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:  definir un element de stockage de frontiere relatif à un   *
 *          éléments finis.														                               *
 *          Ce conteneur est utilisé en dehors d'un élément, par exemple*
 *          pour le contact                                             *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef FRONT_H
#define FRONT_H

#include "Element.h"
#include "ElemMeca.h"
#include "ElFrontiere.h"
         
/// @addtogroup Les_Elements_de_frontiere
///  @{
///


//  la classe Front stock un pointeur d'element frontiere, le nb de 
// l'element finis auquel il se rapporte
class Front 
 { public :
    // constructeur
        //par defaut
    Front(); 
        // normal  
    Front ( const ElFrontiere& el,  Element * pt, int num_front,int angle_mort=0) ;
        // de copie
    Front ( const Front& a);
      // destructeur
    ~Front() ;
        
 // =============     METHODES    ==========        
          
    // affichage à l'écran des informations liées au contact
    // cas = 0 : affichage en fonction du niveau de commentaire voulu
    // cas = 1 : affichage minimal nécessaire pour repérer l'élément
    void Affiche(int cas=0) const ;
     
    // operator
    // affectation de toute les donnees
    Front& operator = ( const Front& a);
    
    // test d'egalite total
    inline bool operator == ( const Front& a) const 
      { if ((*(this->elem) == *(a.elem)) 
              && (this->ptEl == a.ptEl) && (this->tabmitoyen == a.tabmitoyen)
				          && (num_frontiere == a.num_frontiere)
              && (angle_mort == a.angle_mort)
           )
           return true;
         else
           return false;
       };
    // test d'egalite sur les éléments originaux :
    // l'élément elem,  ptEI, et num_frontiere, mais qui ne comprend pas tabmitoyen
    // Important**: ne comprend pas angle_mort contrairement à la méthode de même nom dans Contact
    inline bool MemeOrigine( const Front& a) const
      { if (   (*(this->elem) == *(a.elem)) && (this->ptEl == a.ptEl)
		           && (num_frontiere == a.num_frontiere))
           return true;
         else
           return false;
       };
     
     inline bool operator != ( const Front& a) const 
       { if (*this == a) return false; else return true;};
       
    // definition des elements mitoyens
    void DefMitoyen(const Tableau <Front*>& tabmitoyen);
    // ajout d'un élément mitoyens (l'ajout est effectif uniquement s'il n'existe pas déjà)
    void AjoutMitoyen(Front * mitoyen);
    
    // retourne les donnees
    inline const Tableau <Front*>* TabMitoyen() const { return tabmitoyen;};
      
    // ramène l'encombrement de l'élément frontière sous forme du point 
    //ayant les coordonnées mini et le point ayant les coordonnées les maxi
    const Coordonnee& Encom_mini_FR() {return boite_Front.Premier();};   
    const Coordonnee& Encom_maxi_FR() {return boite_Front.Second();};  
    // test si le point passé en argument appartient à la boite d'encombrement de la frontière
    // tous les points sont supposées avoir la même dimension
    bool In_boite_emcombrement_front(const Coordonnee& M) const; 
    // test si le point passé en argument appartient à la boite d'encombrement de la frontière
    // tous les points sont supposées avoir la même dimension
    // ici la boite est augmentée de extra dans tous les sens
    bool In_boite_emcombrement_front(const Coordonnee& M,double extra) const;

    // mise à jour de la boite d'encombrement de la frontière
    // dep_max : déplacement maxi des noeuds du maillage
    // dans le cas d'un dep_max != 0., on agrandit la boite (défavorable !!)
    //           , sert pour def des boites d'encombrement maxi des frontières
    void Boite_encombrement_frontiere(Enum_dure temps,double dep_max=0.);
    
	 
	 //----- lecture écriture de restart -----
    // définition d'un conteneur signature permettant de définir les grandeurs internes de front
    class Signature_Front  { public: int numelem; int numMail;};
    // la lecture s'effectue uniquement au niveau de la signature
    // 1) lecture et retour de la signature
    Signature_Front Lecture_base_info_Signature_Front(ifstream& ent); 
    // ici la lecture n'est pas complète il faut ensuite mettre à jour l'élément
    // frontière en fonction de son numéro qui est déjà stocké dans l'élément, et le pointeur de l'élément
    // -> utilisation de : Change_elem_frontiere, Change_PtEI
    void Lecture_base_info_front(ifstream& ent);
	   void Ecriture_base_info_front(ofstream& sort);
     
    // changement d'élément frontière, il faut également le numéro de l'élément fini associé
    void Change_elem_frontiere(const ElFrontiere& el, int num_front)
	    { if (elem != NULL) {*elem = el;} else { elem = el.NevezElemFront();}; num_frontiere= num_front;}; 
	   // ici il faut faire attention, car il faut que le numéro de frontière soit cohérent avec l'élément
	   // donc normalement Change_PtEI doit s'utiliser avec Change_elem_frontiere
    void Change_PtEI(Element * ptei) { ptEl = ptei;};
     
    // routine de récupération d'informations
    // récup de l'element frontiere en modification éventuelle
	   // si le retour est NULL, c'est que l'élément frontière n'est pas définit
    ElFrontiere* Eleme() const {return elem;}
	   // idem mais en constant
    const ElFrontiere*  Eleme_const() const {return elem;}
	  
    // récup du numero du maillage  rattache  
    int NumMail() {return ptEl->Num_maillage();}; 
    // récup du pointeur sur l'element fini qui a cree elem
    Element * PtEI() const { return ptEl;};
	   // récup du numéro de frontière associé à l'élément fini
	   int Num_frontiere() const {return num_frontiere;};
    
    // récupération de l'indicateur d'angle mort
    int Angle_mort() const {return angle_mort;};
    // changement de l'indicateur d'angle mort
    void Change_angle_mort(int new_angle_mort) {angle_mort= new_angle_mort;};
     
    // test si la position d'un point est du bon cote ( c-a-d hors matiere) ou non
    // si le point est sur la surface, ramène false
    // ramene true si hors matiere, sinon false
    // le test  sur a est executer uniquement dans les cas suivants :
    // dimension 3D et  frontiere 2D
    // dimension 3D axi et frontière 1D
    // dimension 2D et frontiere 1D
    // ->>> dimension 3D et frontiere 1D, pas de verif
    // ->>> autre cas ne doivent pas arriver normalement !!
    // ..... fonctions identique à celles définit dans ElFrontiere sauf pour le cas 1D
    // où la fonction de ElFrontiere ne fonctionne pas, il faut utiliser celle_ci
	   //!!! il n'y a pas de vérification que l'élément frontière existe !!
    // retour de r = distance du point à la surface, ligne
    bool BonCote_t( const Coordonnee& a,double& r) const  // cas ou on utilise la frontiere a t
     { if (ParaGlob::Dimension() != 1) return elem->BonCote_t(a,r);
       else { r=ConstMath::grand; return (!((ElemMeca *)ptEl)->Interne_t(a));}};
    bool BonCote_tdt( const Coordonnee& a,double& r)  const // cas ou on utilise la frontiere a tdt
     { if (ParaGlob::Dimension() != 1) return elem->BonCote_tdt(a,r); 
       else { r=ConstMath::grand; return (!((ElemMeca *)ptEl)->Interne_tdt(a));}};
          
  // variables
   protected:   
    ElFrontiere* elem; // un pointeur d'élement frontiere:
		        // on est obligé d'avoir un pointeur car l'élément frontière est virtuel pur
				
    Element * ptEl; // pointeur sur l'element fini qui a cree elem
		  int num_frontiere; // le numéro de la frontière relatif à l'élément finis associé
    // def d'une boite d'encombrement pour les noeuds de la frontière
    DeuxCoordonnees boite_Front; // le premier le min, le second le max
    
    Tableau <Front*>* tabmitoyen; // tableau des elements mitoyens
    
    int angle_mort; // indicateur par défaut = 0, ==1 s'il s'agit d'un front
    // qui est construit pour représenter un angle mort
      
    // fonctions internes
    static double prop_mini; // mini proportion à ajouter à l'encombrement
                                  
 }; 
 /// @}  // end of group

#endif      
