Herezh_dev/Resultats/VRML/Isovaleurs_vrml.cc
2023-05-03 17:23:49 +02:00

973 lines
48 KiB
C++

// 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_vrml.h"
#include <iomanip>
#include <algorithm>
#include "CharUtil.h"
#include "Coordonnee2.h"
#include "ConstMath.h"
#include "MathUtil.h"
#include "Banniere.h"
#include <limits>
// CONSTRUCTEURS :
// par defaut
Isovaleurs_vrml::Isovaleurs_vrml () :
OrdreVisu("........................................isovaleurs"
,"visualisation des isovaleurs","iso")
,choix_peau(true),choix_legende(true),choix_min_max(1)
,pour_legende_min(0),pour_legende_max(100)
,valMini(0.),valMaxi(0.)
,tabnoeud_type_ddl(),type_ddl_retenu(),choix_var_ddl()
,tabelement_type_ddl()
,spectre_coul(),nb_iso_val()
,couleurs_noeud(),val_noeud(),num_mail_incr()
,absolue(true)
{// par défaut le nombre d'isovaleur vaut le nombre de couleur du spectre
nb_iso_val=spectre_coul.NbCouleurBaseSpectre();
};
// constructeur de copie
Isovaleurs_vrml::Isovaleurs_vrml (const Isovaleurs_vrml& ord) :
OrdreVisu(ord)
,choix_peau(ord.choix_peau),choix_legende(ord.choix_legende)
,choix_min_max(ord.choix_min_max)
,pour_legende_min(ord.pour_legende_min),pour_legende_max(ord.pour_legende_max)
,valMini(ord.valMini),valMaxi(ord.valMaxi)
,tabnoeud_type_ddl(ord.tabnoeud_type_ddl)
,type_ddl_retenu(ord.type_ddl_retenu),choix_var_ddl(ord.choix_var_ddl)
,tabelement_type_ddl(ord.tabelement_type_ddl)
,spectre_coul(ord.spectre_coul),nb_iso_val(ord.nb_iso_val)
,couleurs_noeud(ord.couleurs_noeud),val_noeud(ord.val_noeud)
,num_mail_incr(ord.num_mail_incr)
,absolue(ord.absolue)
{ };
// DESTRUCTEUR :
Isovaleurs_vrml::~Isovaleurs_vrml ()
{ };
// 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 Isovaleurs_vrml::ExeOrdre(ParaGlob * ,const Tableau <int>& tab_mail,LesMaillages * lesMail,bool ,LesReferences*
,LesLoisDeComp* ,DiversStockage*,Charge*,LesCondLim*
,LesContacts*,Resultats*,UtilLecture & entreePrinc,OrdreVisu::EnumTypeIncre type_incre,int incre
,bool animation,const map < string, const double * , std::less <string> >&
,const List_io < TypeQuelconque >& listeVecGlob)
{// visualisation du maillage pointé si actif
if (actif)
{// on boucle sur les maillages
int nbmail = tab_mail.Taille();
for (int im=1;im<=nbmail;im++)
{ int numMail=tab_mail(im);
// dans le cas où il n'y a aucun type de ddl retenu on arrête tout de suite
if (type_ddl_retenu.Taille() == 0)
{ cout << "\n *** aucun type de ddl n'est defini en sortie, on ne fait rien \n";
}
else // cas où il y a des ddl défini
{// en fait on se contente de définir les couleurs aux noeuds par rapport à l'échelle
// actuelle des couleurs
// actualisation du conteneur du résultat
if (type_incre==PREMIER_INCRE)
{ // au premier increment on commence par ré-initialiser les conteneurs
couleurs_noeud.erase(couleurs_noeud.begin(),couleurs_noeud.end());
num_mail_incr.erase(num_mail_incr.begin(),num_mail_incr.end());
val_noeud.erase(val_noeud.begin(),val_noeud.end());
// dans le cas d'un calcul de mini max automatique on initialise
if ((choix_min_max == 1)||(choix_min_max==3)) // cas d'un seul min max
{ valMini=0.;valMaxi=0.;};
};
// on définit deux variables intermédiaires
// qui serviront ensuite à complèter les deux listes
int nbmaxinoeud = lesMail->Nombre_noeud(numMail);
Tableau < double > v_noeuds(nbmaxinoeud);
Deuxentiers deuxi; deuxi.mail = numMail; deuxi.incr=incre;
// on balaie tous les noeuds du maillage
list <Coordonnee > listcoor; // une liste intermédiaire
for (int numNoeud=1; numNoeud<= nbmaxinoeud;numNoeud++)
{ // recup du noeud
Noeud & noe = lesMail->Noeud_LesMaille(numMail,numNoeud);
// recup de la valeur du ddl
double val_ddl = noe.Valeur_tdt(type_ddl_retenu(numMail).Enum());
if (!choix_var_ddl(numMail))
val_ddl -= noe.Valeur_0(type_ddl_retenu(numMail).Enum());
// enregistrement de la valeur
v_noeuds(numNoeud)=val_ddl;
// dans le cas on l'on utilise un mini max global automatique
// on le met à jour
if ((choix_min_max == 1)||(choix_min_max==3)) // cas d'un seul min max
{ if (val_ddl > valMaxi) valMaxi = val_ddl;
if (val_ddl < valMini) valMini = val_ddl;
};
};
// on sauvegarde les grandeurs intermédiaires
num_mail_incr.push_back(deuxi);
val_noeud.push_back(v_noeuds);
// cas du dernier incrément ou du premier sans animation, se qui signifie que c'est également le dernier
if ((type_incre==DERNIER_INCRE)||( (type_incre==PREMIER_INCRE) && (!animation) ))
{ // dans le cas du dernier incrément on met les valeurs à la bonne échelle
// si c'est une échelle automatique
if ((choix_min_max == 1) || (choix_min_max==3))
{ //on regarde si l'échelle n'est pas nulle si oui on la met à une valeur arbitraire de 1
if ( Dabs(valMaxi - valMini) <= ConstMath::petit)
{ cout << "\n *** attention la valeur mini "<< valMini <<" et maxi " << valMaxi
<< " sont trop rapprochees pour le calcul de la plage d'isovaleur"
<< "\n le mini et le maxi sont mis arbitrairement a 0 et 1";
valMaxi = 1.; valMini= 0.;
}
if (choix_min_max == 1) // cas d'un min max normal automatique
{spectre_coul.Change_min_max(valMini,valMaxi) ;}
else if (choix_min_max == 3) // cas d'un min max automatique en %
{// on applique les %
double leg_min=valMini + (valMaxi-valMini) * pour_legende_min/100.;
double leg_max=valMini + (valMaxi-valMini) * pour_legende_max/100.;
spectre_coul.Change_min_max(leg_min,leg_max) ;
}
}
// maintenant on défini les couleurs
// on passe en revue toutes les valeurs enregistrées
list < Tableau < double > >::iterator it,itfin=val_noeud.end();
for (it=val_noeud.begin();it!= itfin;it++)
{ int taimax=(*it).Taille();
Tableau < Rgb > coul_noeuds(taimax);
Tableau < double > & tab = (*it); // par facilité
// dans le cas ou le min max varie à chaque incrément il faut d'abord le calculer
if (choix_min_max==2)
{ valMini = 0.; valMaxi = 0.; // init
double val_ddl;
for (int j=1;j<=taimax;j++)
{ val_ddl=tab(j);
if (val_ddl > valMaxi) valMaxi = val_ddl;
if (val_ddl < valMini) valMini = val_ddl;
}
//on regarde si l'échelle n'est pas nulle si oui on la met à une valeur arbitraire de 1
if ( Dabs(valMaxi - valMini) <= ConstMath::petit)
{ cout << "\n *** attention (2) la valeur mini "<< valMini <<" et maxi " << valMaxi
<< " sont trop rapprochees pour le calcul de la plage d'isovaleur"
<< "\n le mini et le maxi sont mis arbitrairement a 0 et 1";
valMaxi = 1.; valMini= 0.;
}
// maintenant on applique les %
double leg_min=valMini + (valMaxi-valMini) * pour_legende_min/100.;
double leg_max=valMini + (valMaxi-valMini) * pour_legende_max/100.;
spectre_coul.Change_min_max(leg_min,leg_max) ;
};
// maintenant on calcul les couleurs
for (int i=1;i<=taimax;i++)
coul_noeuds(i)=spectre_coul.CouleurVal(tab(i));
couleurs_noeud.push_back(coul_noeuds);
}
// on dessine la légende au dernier passage
// car c'est seulement à la fin que l'on connait exactement l'échelle (dans le cas d'un
// calcul automatique de l'échelle)
// dans les autres cas la légende ne concerne que le dernier cas
Sortie_dessin_legende(entreePrinc);
if (choix_min_max==2)
{ cout << "\n *** attention ici la legende ne concerne que le dernier increment !!";};
}
}; //-- fin du choix où il y a ou pas des ddl actifs definis
}; //-- fin de la boucle sur les maillages
};//-- fin du choix actf ou pas
};
// 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 Isovaleurs_vrml::ChoixOrdre()
{ bool choix_valide = false;
cout << "\n ---- isovaleurs ---- ";
string rep;
while (!choix_valide)
{
try
{
cout
<< "\n (0 ou f ou fin) fin modif"
<< "\n (1) definition des parametres generaux "
<< "\n (2) choix de l'isovaleur "
<< "\n (3) transferts aux noeuds de grandeurs existantes aux points d'integration";
cout << "\n \n reponse ? ";
rep = lect_return_defaut(false,"f");
if (rep == "fin_prog") Sortie(1);
// sinon
int num = ChangeEntier(rep);
if ((rep == "0")||(rep == "f")||(rep == "fin"))
{ choix_valide=true; }
else if ((num >= 1)&&(num<=3))
{ choix_valide=false;
switch (num)
{ case 1: //"definition des parametres generaux"
{ ParametresGeneraux(); break;}
case 2: // "choix de l'isovaleur"
{ChoixIsovaleur(); break;}
case 3: // "transferts aux noeuds de grandeurs existantes aux points d'integration"
{ TransfertGrandeursPtIntegAuNoeud(); break;}
}
}
else { cout << "\n Erreur on attendait un entier entre 0 et 3 !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper fin_prog pour arreter le programme";
choix_valide=false;
}
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch (...)// erreur de lecture
{ cout << "\n Erreur on attendait un des mots cles proposés !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper fin_prog pour arreter le programme";
choix_valide=false;
}
} //-- fin du while
// appel de la méthode de la classe mère
OrdreVisu::ChoixOrdre();
};
// initialisation : permet d'initialiser les différents paramètres de l'ordre
// lors d'un premier passage des différents incréments
// en virtuelle, a priori est défini si nécessaire dans les classes dérivées
void Isovaleurs_vrml::Initialisation(ParaGlob * paraGlob,LesMaillages * lesmail,LesReferences* lesRef
,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage,Charge* charge
,LesCondLim* lesCondLim,LesContacts* lesContacts
,Resultats* resultats,EnumTypeIncre type_incre,int incre
,const map < string, const double * , std::less <string> >& listeVarGlob
,const List_io < TypeQuelconque >& listeVecGlob
,bool fil_calcul)
{ // initialisation de la liste des différentes isovaleurs possibles
// uniquement lors du premier et du dernier passage pour économiser
if ((type_incre == OrdreVisu::DERNIER_INCRE) || (type_incre == OrdreVisu::PREMIER_INCRE))
{Init_liste_isovaleur(lesmail,lesContacts);}
//appel de l'ordre d'initialisation de la classe mère
OrdreVisu::Initialisation(paraGlob,lesmail,lesRef,lesLoisDeComp,diversStockage,charge
,lesCondLim,lesContacts,resultats,type_incre,incre
,listeVarGlob,listeVecGlob,fil_calcul);
choix_var_ddl.Change_taille(lesmail->NbMaillage());
};
// initialisation de la liste des différentes isovaleurs possibles
void Isovaleurs_vrml::Init_liste_isovaleur(LesMaillages * lesMail,LesContacts* lesContacts)
{ // récupération des ddl présents dans les maillages aux noeuds
tabnoeud_type_ddl = lesMail->Les_type_de_ddl_par_noeud(absolue);
tabelement_type_ddl = lesMail->Les_type_de_ddl_par_element(absolue);
};
// lecture des paramètres de l'ordre dans un flux
void Isovaleurs_vrml::Lecture_parametres_OrdreVisu(UtilLecture & entreePrinc)
{ // si dans le flot il existe l'identificateur adoc on lit sinon on passe
if (strstr(entreePrinc.tablcarCVisu,"debut_isovaleur_vrml")!=NULL)
{// sauvegarde des parametres actuels
bool choix_peau_s=choix_peau; bool choix_legende_s=choix_legende; int choix_min_max_s=choix_min_max;
double valMini_s=valMini; double valMaxi_s=valMaxi; int nb_iso_val_s=nb_iso_val;
Tableau < Ddl_enum_etendu> type_ddl_retenu_s(type_ddl_retenu);
// essaie de lecture
try
{ string nom,nom1;
(*entreePrinc.entCVisu) >> nom ;
if (nom != "debut_isovaleur_vrml")
{ cout << "\n Erreur en lecture des parametres pour les isovaleurs a partir d'un fichier .CVisu,"
<< " le premier enregistrement doit etre le mot clef: debut_isovaleur_vrml "
<< " on ne tiens pas compte des parametres fournis !! ";
}
else
{ // appel de l'ordre de la classe mère
OrdreVisu::Lect_para_OrdreVisu_general(entreePrinc);
// puis lecture des parametres propres
// lecture du type de sortie des tenseurs
if (strstr(entreePrinc.tablcarCVisu,"tenseur_en_absolue_")!=NULL)
{(*entreePrinc.entCVisu) >> nom >> absolue;
if (nom != "tenseur_en_absolue_")
{ cout << "\n lecture de l'indicateur de type de tensue, on a lue ( "<< nom
<< " ) et on attendait tenseur_en_absolue_"
<< " la suite de la lecture du .CVisu risque d'etre completement fausse, on arrete !!" ;
cout << "\n Isovaleurs_Gmsh::Lecture_parametres_OrdreVisu(... ";
UtilLecture::ErrNouvelEnregCVisu sortie(-1) ; throw (sortie);
}
else // sinon c'est ok
{entreePrinc.NouvelleDonneeCVisu();}; // on passe un enregistrement
};
int nb_maillage = tabnoeud_type_ddl.Taille();
while (strstr(entreePrinc.tablcarCVisu,"fin_isovaleur_vrml")==NULL)
{ (*entreePrinc.entCVisu) >> nom; // lecture du numero de maillage
if (nom == "choix_peau") (*entreePrinc.entCVisu) >> choix_peau;
if (nom == "choix_legende") (*entreePrinc.entCVisu) >> choix_legende;
if (nom == "choix_min_max") (*entreePrinc.entCVisu) >> choix_min_max;
if (nom == "valMini") (*entreePrinc.entCVisu) >> valMini;
if (nom == "valMaxi") (*entreePrinc.entCVisu) >> valMaxi;
if (nom == "pour_legende_min") (*entreePrinc.entCVisu) >> pour_legende_min;
if (nom == "pour_legende_max") (*entreePrinc.entCVisu) >> pour_legende_max;
if (nom == "nb_iso_val") (*entreePrinc.entCVisu) >> nb_iso_val;
if (nom == "debut_tableau_ddl")
{ (*entreePrinc.entCVisu) >> nom1;
if (nom1 != "fin_tableau_ddl")
{ type_ddl_retenu.Change_taille(nb_maillage);
choix_var_ddl.Change_taille(nb_maillage);
type_ddl_retenu(1) = Ddl_enum_etendu(nom1);
for (int i=2;i<= nb_maillage; i++)
{ (*entreePrinc.entCVisu) >> type_ddl_retenu(i);
(*entreePrinc.entCVisu) >> choix_var_ddl(i);
}
}
}
entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
}
entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
} // -- fin du if then else sur "debut_isovaleur_vrml"
} // -- fin du try
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch (...)// erreur de lecture
{ cout << "\n Erreur en lecture des parametres pour les isovaleurs a partir d'un fichier .CVisu,"
<< " on ne tiens pas compte des parametres fournis !! ";
// récup des parametres sauvées
choix_peau=choix_peau_s; choix_legende=choix_legende_s; choix_min_max=choix_min_max_s;
valMini=valMini_s; valMaxi=valMaxi_s; nb_iso_val=nb_iso_val_s;
type_ddl_retenu = type_ddl_retenu_s;
if (ParaGlob::NiveauImpression() >= 4)
cout << "\n Isovaleurs_vrml::Lecture_parametres_OrdreVisu(..";
}
}
};
// écriture des paramètres de l'ordre dans un flux
void Isovaleurs_vrml::Ecriture_parametres_OrdreVisu(UtilLecture & entreePrinc)
{ // récup du flot
ostream & sort = (*(entreePrinc.Sort_CommandeVisu()));
// on commente le fonctionnement
sort << "\n # ----------------------------- definition des parametres pour les isovaleurs : ---------------- ";
// mot clé de démarrage
sort << "\n debut_isovaleur_vrml # mot cle de debut des parametres pour les isovaleurs";
// appel de l'ordre de la classe mère
OrdreVisu::Ecrit_para_OrdreVisu_general(entreePrinc);
// le type de sortie des tenseurs
sort << "\n# un parametre indiquant si les tenseurs sont en absolue (rep 1) ou suivant un repere ad hoc"
<< "\n# (tangent pour les coques, suivant la fibre moyenne pour les element 1D ) ";
sort << "\n tenseur_en_absolue_ " << absolue;
// puis les paramètres
sort << "\n choix_peau " << choix_peau << " # <0 ou 1> si 1 visualisation uniquement de la peau";
sort << "\n choix_legende " << choix_legende << " # <0 ou 1> si 1 affichage de la legende";
sort << "\n choix_min_max " << choix_min_max << " # <0 ou 1 ou 2> si 1 min max calcule automatiquement, 2 auto en % par incre";
sort << "\n valMini " << valMini << " # mini <un reel> utilises si choix_min_max = 0";
sort << "\n valMaxi " << valMaxi << " # maxi <un reel> utilises si choix_min_max = 0";
sort << "\n pour_legende_min " << pour_legende_min << " # mini <un reel> utilises si choix_min_max = 2";
sort << "\n pour_legende_max " << pour_legende_max << " # maxi <un reel> utilises si choix_min_max = 2";
sort << "\n nb_iso_val " << nb_iso_val << " # <un entier> nombre d'isovaleurs dans la legende";
// ---- les ddl a visualiser
sort << "\n # tableau de ddl a visualiser, un par maillage";
int nb_mail = type_ddl_retenu.Taille();
sort << "\n debut_tableau_ddl " ;
for (int i=1;i<= nb_mail;i++)
{ sort << type_ddl_retenu(i) << " " << choix_var_ddl(i) << " ";};
sort << " fin_tableau_ddl " ;
// mot clé de fin
sort << "\n fin_isovaleur_vrml # mot cle de fin des parametres pour les isovaleurs \n";
};
// ======================================== méthodes privées =====================================
// sortie du dessin de la légende
void Isovaleurs_vrml::Sortie_dessin_legende(UtilLecture & entreePrinc)
{ostream &sort = entreePrinc.Sort_legende_vrml();
// é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
/* Vecteur diag = ptfin - ptdeb;
double lmax = diag.Norme();
Vecteur centre = (ptfin + ptdeb)/2.;
// si la dimension est différente de 3 on force à 3
// d'où les autres coordonnées sont nulles
centre.Change_taille(3);
// def de la distance d'observation grande pour minimiser la déformation
double dist = 5.*lmax;
// calcul de l'angle du cone de vue
double angle = 1.25*atan(lmax/dist);
int i1= std::abs( centre(1));
int i2= std::abs( centre(2));
int i3= std::abs( centre(3)+ dist);
sort << "\n Viewpoint {"
<< "\n position " << i1 <<" "<< i2 <<" "<< i3
<< "\n fieldOfView " << angle
<< "\n description \"suivant Z \""
<< "\n }";
*/
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;
};
// définition interactives des paramètres généraux des isovaleurs
void Isovaleurs_vrml::ParametresGeneraux()
{ bool choix_valide = false;
cout << "\n ----> preparation de la visualisation des isovaleurs"
<< "\n parametre par defaut ? : affichage de la peau par facettes triangulaires,"
<< "\n ajout de la legende avec min_max automatique,"
<< "\n spectre standart, "
<< " (rep 'o') pour accepter ces parametres sinon autre ";
string rep;
cout << "\n reponse ? "; rep = lect_return_defaut(true,"o");
if (rep != "o")
{// cas d'un choix autre que standart
while (!choix_valide)
{
try
{
cout
<< "\n (0) fin modif"
<< "\n (1) plus visualisation interne (2) calcul NON automatique des min max de la legende "
<< "\n (3) visualisation que des peaux (4) calcul auto global des min max de la legende"
<< "\n (5) autres spectres (6) % auto sur l'incr des min max de la legende"
<< "\n (7) spectre standart (8) % auto sur tous les incr des min max de la legende"
<< "\n (9) nombre isovaleurs "
<< "\n (10) sortie des tenseurs dans le repere absolu (par defaut) "
<< "\n (11) sortie des tenseurs dans un repere ad hoc, qui depend du type d'element ";
cout << "\n \n reponse ? ";
rep = lect_return_defaut(false,"0");
if (rep == "fin_prog") Sortie(1);
// if ((rep == "0")||(rep == "f")||(rep == "fin")) return;
// sinon
int num = ChangeEntier(rep);
if (num == 0) choix_valide=true;
else if ((num >= 1)&&(num<=11))
{ choix_valide=false;
switch (num)
{ case 1: //"visualisation interne")
{ choix_peau = true; break;}
case 2: // "calcul NON automatique des min max de la légende")
{bool choixvalideLoc = false;
while (!choixvalideLoc)
{// on récupère les mini et maxi de la légende
cout << "\n actuellement les mini/maxi sont: "
<< " mini= " << spectre_coul.Valeur_mini()
<< " maxi= " << spectre_coul.Valeur_maxi();
cout << "\n differentes methodes pour modifier les extremes: "
<< "\n donnez les valeurs explicitements des extremes (rep 1)"
<< "\n donnez en % de la plage actuelle des mini et maxi (rep 2)"
<< "\n (dans ce dernier cas, modif a chaque increment) "
<< "\n laisser tel quel (rep f ou 0 ou fin)";
cout << "\n \n reponse ? ";
string reploc; reploc = lect_return_defaut(false,"f");
if (reploc == "1")
{cout << "\n donner le mini et le maxi de la legende (2 reels) ";
double legende_min,legende_max; // min max de la légende
cin >> legende_min >> legende_max;
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
if ( legende_max < legende_min)
{cout << "\n donnees non valides, le maxi doit etre superieur au mini !! ";
choixvalideLoc=false;
}
else
{choix_min_max = 0;
spectre_coul.Change_min_max(legende_min,legende_max) ;
choixvalideLoc = true;
};
}
else if (reploc == "2")
{cout << "\n donner le mini et le maxi en % de la plage (2 reels) ";
double pr_legende_min,pr_legende_max; // min max de la légende
cin >> pr_legende_min >> pr_legende_max;
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
if ( pr_legende_max < pr_legende_min)
{cout << "\n donnees non valides, le maxi doit etre superieur au mini !! ";
choixvalideLoc=false;
}
else
{choix_min_max = 0;
double leg_min=spectre_coul.Valeur_mini() +
(spectre_coul.Valeur_maxi()-spectre_coul.Valeur_mini())
* pr_legende_min/100.;
double leg_max=spectre_coul.Valeur_mini() +
(spectre_coul.Valeur_maxi()-spectre_coul.Valeur_mini())
* pr_legende_max/100.;
spectre_coul.Change_min_max(leg_min,leg_max) ;
cout << "\n nouvelles valeurs: mini= " <<leg_min << " maxi= " <<leg_max <<" ";
choixvalideLoc=true;
};
}
else if ((reploc == "f")||(reploc == "0")||(reploc == "fin"))
{ choixvalideLoc=true;}
else
{ cout << "\n erreur d'entree, recommencez ";
choixvalideLoc=false;
};
};
break;
}
case 3: // "visualisation que des peaux")
{ choix_peau = false; break;}
case 4: // "calcul automatique des min max de la légende")
{ choix_min_max = 1; break;}
case 5: // "autres spectres")
{ // on récupère les différents spectres
const Tableau <string> & tab_spectre = Spectre::Description_spectres_disponibles();
int nb_spectre= tab_spectre.Taille();
bool choix_val = false;
cout << "\n donner un choix de spectre";
while (!choix_val)
{
try
{ cout << "\n (0) fin modif spectre";
for (int i=1;i<=nb_spectre;i++)
cout << "\n ("<<i<<") " << tab_spectre(i);
cout << "\n \n reponse ? ";
rep = lect_return_defaut(false,"0");
if (rep == "fin_prog") Sortie(1);
// sinon
int nim = ChangeEntier(rep);
if (nim == 0) choix_val=true;
else if ((nim >= 1)&&(nim<=nb_spectre))
{ choix_val=false;
spectre_coul.Change_spectre_courant(Spectre::EnumType_spectre(nim));
}
else
{ cout << "\n ERREUR *** choix non valide :on attendait un nombre entre 0 et "<< nb_spectre
<< "\n redonnez une bonne valeur ****** \n \n ";
choix_val=false;
}
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch (...)// erreur en lecture
{ cout << "\n Erreur on attendait un des mots cles proposes !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper fin_prog pour arreter le programme";
choix_val=false;
}
} //-- fin du while
break;}
case 6: // "calcul automatique en % pour chaque incre des min max de la légende")
{ cout << "\n donner le mini et le maxi en % de la plage de l'increment (2 reels) ";
double pr_legende_min,pr_legende_max; // min max de la légende
cin >> pr_legende_min >> pr_legende_max;
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
if ( pr_legende_max < pr_legende_min)
{cout << "\n donnees non valides, le maxi doit etre superieur au mini !! ";}
else
{choix_min_max = 2;
pour_legende_min=pr_legende_min;pour_legende_max=pr_legende_max;
cout << "\n %lu (util pour chaque incr): mini= " <<pour_legende_min
<< " maxi= " <<pour_legende_max <<" ";
};
break;
}
case 7: // "spectre standart")
{ spectre_coul.Change_spectre_courant(Spectre::EnumType_spectre(1));
break;}
case 8: // "calcul automatique en % global des min max de la légende")
{ cout << "\n donner le mini et le maxi en % de la plage de l'increment (2 reels) ";
double pr_legende_min,pr_legende_max; // min max de la légende
cin >> pr_legende_min >> pr_legende_max;
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
if ( pr_legende_max < pr_legende_min)
{cout << "\n donnees non valides, le maxi doit etre superieur au mini !! ";}
else
{choix_min_max = 3;
pour_legende_min=pr_legende_min;pour_legende_max=pr_legende_max;
cout << "\n %lu (util pour tous les incr): mini= " <<pour_legende_min
<< " maxi= " <<pour_legende_max <<" ";
};
break;
}
case 9: // "nombre d'isovaleurs")
{ bool choix_val = false;
int inter_int;
cout << "\n le nombre actuel est : " << nb_iso_val;
while (!choix_val)
{
try
{ cout << "\n donnez une nouvelle valeur entre 2 et 100 ou 0 pour laisser en l'etat";
cout << "\n \n valeur ? ";
inter_int=(int)lect_double();
if (inter_int == 0) choix_val = true;
// sinon
else if ((inter_int <= 2) || (inter_int > 100))
cout << "\n le nombre d'isovaleur doit etre strictement superieur a 2 et"
<< "inferieur ou egal a 100";
else {nb_iso_val = inter_int;choix_val = true;}
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch (...)// erreur en lecture
{ cout << "\n Erreur on attendait soit 0 pour garder la valeur precedente"
<< " ou un nombre entre 2 et 100 !!, "
<< "\n redonnez une bonne valeur";
choix_val=false;
}
} //-- fin du while
break;}
case 10: { absolue = true; break;}
case 11: { absolue = false; break;}
}
}
else { cout << "\n Erreur on attendait un entier entre 0 et 9 !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper fin_prog pour arreter le programme";
choix_valide=false;
}
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch (...)// erreur de lecture
{ cout << "\n Erreur on attendait un des mots cles proposés !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper fin_prog pour arreter le programme";
choix_valide=false;
}
} //-- fin du while
}
};
// choix de l'isovaleur à visualiser
void Isovaleurs_vrml::ChoixIsovaleur()
{ bool choix_valide = false;
string rep;
cout << "\n choix de l'isovaleur a visualiser, on choisit une isovaleur maxi par maillage";
int nbmail = tabnoeud_type_ddl.Taille();
// update du tableau de ddl à visualiser si nécessaire
if (type_ddl_retenu.Taille() != nbmail)
type_ddl_retenu.Change_taille(nbmail);
for (int imail = 1;imail<=nbmail;imail++)
{choix_valide=false;
while (!choix_valide) // premier while
{
try
{
cout << "\n (0 ou f ou fin) fin choix ddl ";
cout << "\n listes de type de ddl a visualiser ";
cout << "\n Maillage nb: " << imail << " liste des types de ddl disponibles "
<< "\n" << tabnoeud_type_ddl(imail);
cout << "\n donner le ddl a visulaliser "
<< "\n reponse ? ";
rep = lect_return_defaut(false,"f");
if (rep == "fin_prog") Sortie(1);
// sinon
if ((rep == "0") || (rep == "f") || (rep == "fin"))
choix_valide=true;
else if (ExisteEnum_ddl(rep.c_str())) // test pour savoir si c'est vraiment un ddl
{ Enum_ddl enum_d = Id_nom_ddl(rep.c_str());
Ddl_enum_etendu ddl_enu_etendue(enum_d);
// on vérifie si le ddl existe dans la liste proposée
if (Ddl_enum_etendu::Existe_dans_la_liste(tabnoeud_type_ddl(imail),ddl_enu_etendue))
{type_ddl_retenu(imail) = ddl_enu_etendue;}
else
{cout << "\n ddl inexistant dans la liste proposee, recommencez";
choix_valide=false;
}
}
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch (...)// erreur en lecture
{ cout << "\n Erreur dans la lecture de ddl !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper fin_prog pour arreter le programme";
choix_valide=false;
}
} //-- fin du premier while
choix_valide=false;
while (!choix_valide)
{
try
{ cout << "\n valeur du ddl ou variation entre t=0 et t (rep 1 ou 0 ) ? \n"
<< "\n reponse ? ";
rep = lect_1_0(false);
if (rep == "1") {choix_var_ddl(imail)=true;choix_valide=true;}
else if (rep == "0") {choix_var_ddl(imail)=false;choix_valide=true;}
else
{cout << "\n mauvais choix, recommencez";choix_valide=false;}
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch (...)// erreur en lecture
{ cout << "\n Erreur dans le choix de la variation ou non des ddl !!, "
<< "\n redonnez une bonne valeur";
choix_valide=false;
}
} //-- fin du second while
}//-- fin de la boucle sur les maillages
};
// choix de grandeur existantes aux points d'intégrations et à ramener aux noeuds
// pour préparer une visualisation d'isovaleurs
void Isovaleurs_vrml::TransfertGrandeursPtIntegAuNoeud()
{ /*bool choix_valide = false;
string rep;
while (!choix_valide)
{try
{ cout
<< "\n (0 ou f ou fin) fin modif"
<< "\n (1) definition des parametres generaux "
<< "\n (2) choix de l'isovaleur "
<< "\n (3) transferts aux noeuds de grandeurs existantes aux points d'integration";
cout << "\n \n reponse ? ";
cin >> rep;
if (rep == "fin_prog") Sortie(1);
// sinon
int num = ChangeEntier(rep);
if ((rep == "0")||(rep == "f")||(rep == "fin"))
{ choix_valide=true; }
else if ((num >= 1)&&(num<=3))
{ choix_valide=false;
switch (num)
{ case 1: //"definition des parametres generaux"
{ ParametresGeneraux(); break;}
case 2: // "choix de l'isovaleur"
{ChoixIsovaleur(); break;}
case 3: // "transferts aux noeuds de grandeurs existantes aux points d'integration"
{ choix_peau = false; break;}
case 4: // "calcul automatique des min max de la légende")
{ TransfertGrandeursPtIntegAuNoeud(); break;}
}
}
else { cout << "\n Erreur on attendait un entier entre 0 et 3 !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper fin_prog pour arreter le programme";
choix_valide=false;
}
}
catch (...)// erreur de lecture
{ cout << "\n Erreur on attendait un des mots cles proposés !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper fin_prog pour arreter le programme";
choix_valide=false;
}
} //-- fin du while*/
};