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

#include <iomanip>
#include <algorithm>
#include "CharUtil.h"
#include "Coordonnee2.h"
#include "ConstMath.h"
#include "MathUtil.h"
#include "Banniere.h"

    // CONSTRUCTEURS :
// par defaut
Isovaleurs_geomview::Isovaleurs_geomview () :
   Isovaleurs_vrml()
     {}; 
     
     // constructeur de copie 
Isovaleurs_geomview::Isovaleurs_geomview (const Isovaleurs_geomview& ord) :
    Isovaleurs_vrml(ord) 
     { };
               
    // DESTRUCTEUR :
Isovaleurs_geomview::~Isovaleurs_geomview () 
     {  };  
    
            
               
// ======================================== méthodes privées =====================================
                           
// sortie du dessin de la légende
void Isovaleurs_geomview::Sortie_dessin_legende(UtilLecture & entreePrinc)
  {ostream &sort = entreePrinc.Sort_legende_geomview();
   // écriture de l'entête
   sort << "#VRML V2.0 utf8\n";
   // le titre
   sort << "WorldInfo {\n"
        << "title \" Légende pour isovaleurs du calcul éléments finis : Herezh++ V" << ParaGlob::NbVersion()
                                                               << " \" \n"
 //       << "info [ \"Copyright (c) 1997-2003, Gérard Rio (gerard.rio@univ-ubs.fr) http://www-lg2m.univ-ubs.fr\" ]\n"
        << "info [ \" " << Banniere::CopiPirate << " \" ]\n"
        << "}\n";
   sort << "NavigationInfo {\n"
        << "type [ \"EXAMINE\", \"ANY\" ] \n"
        << "headlight TRUE \n"
        << "}\n";
   // on définit un rectangle pour chaque niveau d'isovaleur 
   // globalement on définit le rectangle global par les points extrèmes
   Coordonnee2 ptdeb(0.,0.); Coordonnee2 ptfin(10.,200.);
   // on définit le deltax et le delta y
   Coordonnee2 deltax(10.,0.);Coordonnee2 deltay(0.,200./(nb_iso_val-1.));  
   // définition des points de vue avec l'angle adoc
   // l'objectif est de positionner les viewpoints relativement à la legende
   // pour l'instant pb avec maclookat donc on simplifie        
   sort << "\n Viewpoint {"
        << "\n position " << " 5       100      1000 "
        << "\n fieldOfView " << 0.25
        << "\n description \"suivant Z \""
        << "\n }";
   // definition du tableau des points de la legende
   Tableau <Coordonnee2> tab_pt(2*nb_iso_val,ptdeb);
   for (int i=1;i<= nb_iso_val;i++)
     { tab_pt(i) += (i-1) * deltay;
       tab_pt(i+nb_iso_val) = tab_pt(i) + deltax;
      }  
   // on  ecrit la liste des points 
   // def de l'entité forme
   sort << "\n Shape { "
   << "\n  appearance Appearance {}";
   // création des points
   // tout d'abord le nom
   ostrstream tab_out;
   tab_out << "Coordonnees"  << ends;
   string nom_coordinate = tab_out.str() ;  // le nom
   // on utilise une géométrie de face indexée bien qu'aucune face soit définit 
   sort << "\n  geometry IndexedFaceSet {"
        << "\n     coord DEF " << nom_coordinate <<  " Coordinate {"
        << "\n                   point [ \n";
   int deux_nb_iso_val = 2*nb_iso_val;    
   for (int i=1;i<= deux_nb_iso_val;i++)
     { sort <<"\n                        "
                   << setw (4);  
       tab_pt(i).Affiche(sort,16);
       sort << setw (16) << 0 <<" "; // pour etre en 3D
      } 
   // fermeture du groupe point, coordinate, de la géométrie et de la forme
   sort << "\n                     ] } } }";
   // maintenant les facettes:  def de l'entité forme
   sort << "\n Shape { "
        << "\n   appearance Appearance {}";
   // def de la géométrie
   sort << "\n     geometry IndexedFaceSet {"
   // utilisation des points déjà défini
           << "\n     coord USE Coordonnees" ;
   // def des facettes
   sort << "\n                 coordIndex [";
   for (int i=0;i< nb_iso_val-1;i++)
     { // on definit deux triangle pour chaque facette,
       sort << "\n                    "; //début de la face 1
       sort << i << ", " << i+nb_iso_val << ", " << i+1 << ", -1,";
       sort << "\n                    "; //début de la face 2
       sort << i+nb_iso_val << ", " << i+nb_iso_val+1 << ", " << i+1 << ", -1,";
       }
   // fin pour les faces 
   sort << "\n                ]";
   // definition des couleurs aux noeuds 
   // on sauvegarde puis modifie les min max pour les adapter au tracé de la légende
   double legende_min = spectre_coul.Valeur_mini();
   double legende_max = spectre_coul.Valeur_maxi();
   spectre_coul.Change_min_max(ptdeb(2),ptfin(2)) ;
   sort << "\n                 color Color {"
        << "\n                     color [";
   for (int i=1;i<= nb_iso_val;i++)
     { // récup de la couleur
       Rgb rgb = spectre_coul.CouleurVal(tab_pt(i)(2));
       sort << "\n                     " <<  rgb << ", ";
      } 
   for (int i=1;i<= nb_iso_val;i++)
     { // récup de la couleur
       Rgb rgb = spectre_coul.CouleurVal(tab_pt(i+nb_iso_val)(2));
       sort << "\n                     " <<  rgb << " , ";
      } 
    sort    << "\n                     ]"
            << "\n                 }";
    // remise normale du min max du spectre
    spectre_coul.Change_min_max(legende_min,legende_max) ;
            
    // on signal que l'on utilise une couleur par noeud (vertex)
    sort    << "\n                 colorPerVertex  TRUE";
    // on signal que l'on peut voir des deux cotés des facettes
    sort    << "\n                 solid FALSE";
   sort << "\n            }";
    // fin: on ferme l'entité forme
    sort << "\n         }";
    
    // maintenant on définit les valeurs de la légende
    // def d'un décalage suivant x de la légende couleur
    double decax = (ptfin(1) - ptdeb(1))/ 5.;        
    // on boucle sur les isovals
    double delta_val_y=(legende_max-legende_min)/(nb_iso_val-1);
    double val_iso=legende_min;
    for (int i=1;i<= nb_iso_val;i++)
     { // creation de la chaine de caractère qui contient la valeur de l'isovaleur
       ostrstream tab_out;
       #ifndef ENLINUX_STREAM
            tab_out.setf(ios_base::scientific);
       #else  
            tab_out.setf(ios::scientific); 
       #endif
       tab_out << setprecision(6) << val_iso << ends;
       // on définit une entité déplacé qui permet de ce positionner
       // aux coordonnées que l'on veut 
       sort << "\n        Transform {  #           X                   Y                 Z ";
       sort <<"\n              translation "
            << setw (16) << (tab_pt(i+nb_iso_val)(1) + decax) << " " 
            << setw (16) << tab_pt(i+nb_iso_val)(2) << " " 
            << setw (16) << 0 << " "; 
       // écrit la valeur
       sort   << "\n                children [";
       // def de l'entité forme
       sort << "\n          Shape { "
            << "\n                appearance Appearance {"
            << "\n                  material Material { }"
            << "\n                             }"
            << "\n             geometry Text {"
            << "\n             string \"" << tab_out.str() <<"\""
            << "\n               fontStyle FontStyle {size 10} "
            << "\n                 }} ] }";
       val_iso += delta_val_y;     
      }
   // définition du titre du travail
   sort << "\n        Transform {  #           X                   Y                 Z ";
   sort <<"\n              translation "
            << setw (16) << -10 << " " 
            << setw (16) << -10<< " " 
            << setw (16) << 0 << " "; 
   // écrit le texte
   sort   << "\n                children [";
   // def de l'entité forme
   sort << "\n          Shape { "
            << "\n                appearance Appearance {"
            << "\n                  material Material { }"
            << "\n                             }"
            << "\n             geometry Text {"
            << "\n             string \"" << "Herezh++  V" << ParaGlob::NbVersion()<<" \""
            << "\n               fontStyle FontStyle {size 10} "
            << "\n                 }} ] }";
    // définition du nom del'isovaleur
   sort << "\n        Transform {  #           X                   Y                 Z ";
   sort <<"\n              translation "
            << setw (16) << -28 << " " 
            << setw (16) << -18<< " " 
            << setw (16) << 0 << " "; 
   // écrit le texte
   sort   << "\n                children [";
   // def de l'entité forme
   sort << "\n          Shape { "
            << "\n                appearance Appearance {"
            << "\n                  material Material { }"
            << "\n                             }"
            << "\n             geometry Text {"
            << "\n             string \"" << "isovaleur de " ;
    if (type_ddl_retenu.Taille() != 0) 
             sort << type_ddl_retenu(1); //.Nom();            
    sort    << " \""
            << "\n               fontStyle FontStyle {size 10} "
            << "\n                 }} ] }";
       
  // et on vide le buffer de sortie
  sort << endl; 
  };
  
  
