// FICHIER : CoordonneeB.cp // CLASSE : CoordonneeB // 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 "Debug.h" # include <iostream> using namespace std; //introduces namespace std #include <stdlib.h> #include "Sortie.h" #include "ConstMath.h" #include "MathUtil.h" #include <iomanip> #include "ParaGlob.h" #include "Coordonnee.h" #ifndef COORDONNEE_H_deja_inclus // Constructeur par defaut // avant ->// N.B. : la dimension est affectee a 3 et les valeurs a 0 #ifndef MISE_AU_POINT inline #endif CoordonneeB::CoordonneeB () : dim (0) , coord (NULL),memoire(true) {}; // Constructeur utile si le nombre de coordonnees est connue // N.B. : les valeurs sont affectees a 0.0 #ifndef MISE_AU_POINT inline #endif CoordonneeB::CoordonneeB (int dimension) : dim ((short)dimension),memoire(true) { #ifdef MISE_AU_POINT if ( (dimension<1) || (dimension>3) ) { cout << "\nErreur de dimension !\n"; cout << "CoordonneeB::CoordonneeB (int ) \n"; Sortie(1); }; #endif coord=new double [dim]; for (int i=0;i<dim;i++) coord[i]=0.0; }; // Constructeur pour un point a une dimension #ifndef MISE_AU_POINT inline #endif CoordonneeB::CoordonneeB (double x) : dim (1),memoire(true) { coord=new double; coord[0]=x; }; // Constructeur pour un point a deux dimensions #ifndef MISE_AU_POINT inline #endif CoordonneeB::CoordonneeB (double x,double y) : dim (2),memoire(true) { coord=new double [2]; coord[0]=x; coord[1]=y; }; // Constructeur pour un point a trois dimensions #ifndef MISE_AU_POINT inline #endif CoordonneeB::CoordonneeB (double x,double y,double z) : dim (3) ,memoire(true) { coord=new double [3]; coord[0]=x; coord[1]=y; coord[2]=z; }; // constructeur fonction d'une adresse memoire ou sont stockee les coordonnees // et d'une dimension ( l'existance de la place mémoire est a la charge // de l'utilisateur. #ifndef MISE_AU_POINT inline #endif CoordonneeB::CoordonneeB (int dimension,double* t) : dim ((short)dimension),coord (t),memoire(false) {}; // Constructeur de copie #ifndef MISE_AU_POINT inline #endif CoordonneeB::CoordonneeB (const CoordonneeB& c) : dim (c.dim),memoire(true) { if ( dim==0 ) coord=NULL; else { coord=new double [dim]; for (int i=0;i<dim;i++) // copie des coordonnees coord[i]=c.coord[i]; }; }; // Destructeur // Desallocation de la place memoire allouee #ifndef MISE_AU_POINT inline #endif CoordonneeB::~CoordonneeB () { if (memoire) { if (dim > 0) { delete [] coord; coord=NULL; dim=0; } #ifdef MISE_AU_POINT else {if ( coord!=NULL ) { cout << "\nErreur de liberation de la place memoire\n"; cout << "CoordonneeB::LIBERE () \n"; Sortie(1); } } #endif } }; // construction "explicite" à partir d'une instance de CoordonneeB // intéressant si this est initialement construit par defaut (donc vide) // cela permet de créer un CoordonneeH à partir d'un B, mais de manière explicite, // donc activé quand on le veux (et non pas par le compilo au gré de conversion pas toujours clair!!) #ifndef MISE_AU_POINT inline #endif void CoordonneeB::ConstructionAPartirDe_H(const CoordonneeH& aH) { if (dim != aH.dim) Change_dim(aH.dim); memoire = true; dim = aH.dim; switch (dim) { case 3 : coord[2] = aH.coord[2]; case 2 : coord[1] = aH.coord[1]; case 1 : coord[0] = aH.coord[0]; case 0 : ; // on ne fait rien }; }; #ifndef MISE_AU_POINT inline #endif // change les valeurs en fonction d'un point sans variance void CoordonneeB::Change_val(const Coordonnee& c) { int c_dim = c.Dimension(); if (dim != c_dim) Change_dim(c_dim); memoire = true; dim = c_dim; switch (dim) { case 3 : coord[2] = c(3); case 2 : coord[1] = c(2); case 1 : coord[0] = c(1); case 0 : ; // on ne fait rien }; }; // Renvoie le nombre de coordonnees #ifndef MISE_AU_POINT inline #endif int CoordonneeB::Dimension () const { return dim; }; // Desallocation de la place memoire allouee #ifndef MISE_AU_POINT inline #endif void CoordonneeB::Libere () { if ( dim>0 ) delete [] coord; else {if ( coord!=NULL ) { cout << "\nErreur de liberation de la place memoire\n"; cout << "CoordonneeB::LIBERE () \n"; Sortie(1); } } coord=NULL; dim=0; }; // Renvoie la ieme coordonnee #ifndef MISE_AU_POINT inline #endif double& CoordonneeB::operator() (int i) { #ifdef MISE_AU_POINT if ( (i<1) || (i>dim) ) { cout << "\nErreur de dimension !\n"; cout << "CoordonneeB::OPERATOR() (int ) \n"; Sortie(1); }; #endif return coord[i-1]; }; // Renvoie une copie de la ieme coordonnee #ifndef MISE_AU_POINT inline #endif double CoordonneeB::operator() (int i) const { #ifdef MISE_AU_POINT if ( (i<1) || (i>dim) ) { cout << "\nErreur de dimension !\n"; cout << "CoordonneeB::OPERATOR() (int ) \n"; Sortie(1); }; #endif return coord[i-1]; }; // changement de la dimension // dans le cas d'une nouvelle dimension inferieur on supprime les dernieres coord // dans le cas d'une dimension superieur, on ajoute des coord initialisees a zero` #ifndef MISE_AU_POINT inline #endif void CoordonneeB::Change_dim(int dimen) { #ifdef MISE_AU_POINT if ((dimen<1) || (dimen>3)) { cout << "\n erreur, la nouvelle dimension doit etre comprise entre 1 et 3 ! "; cout << "\n dim voulue = " << dimen ; cout << "\nCoordonneeB::Change_dim(int dim) " << endl; Sortie(1); } #endif double * sauve = coord; if (dim < dimen) { coord = new double [dimen]; for (int i=0;i<dim;i++) coord[i] = sauve[i]; if (dim != 0) delete [] sauve; for (int i=dim;i<dimen;i++) coord[i] = 0.; dim = (short) dimen; } else if (dim > dimen) { coord = new double [dimen]; for (int i=0;i<dimen;i++) coord[i] = sauve[i]; dim = (short) dimen; delete [] sauve; } // dans le cas ou dim = dimen on ne fait rien }; // Surcharge de l'operateur = : realise l'affectation entre deux points #ifndef MISE_AU_POINT inline #endif CoordonneeB& CoordonneeB::operator= (const CoordonneeB& c) { if (dim==c.dim) { for (int i=0;i<dim;i++) coord[i]=c.coord[i]; return (*this); } else if ( c.dim==0 ) { Libere();} else { #ifdef MISE_AU_POINT if (dim != 0) { cout << "\n attention, on change la dimension du point !!!" << " de "<<dim<<" a "<<c.dim << endl; } #endif Libere(); dim=c.dim; coord=new double [dim]; for (int i=0;i<dim;i++) coord[i]=c.coord[i]; }; return (*this); }; // Surcharge de l'operateur - : renvoie l'oppose d'un point #ifndef MISE_AU_POINT inline #endif CoordonneeB CoordonneeB::operator- () const { CoordonneeB result(dim); for (int i=0;i<dim;i++) result.coord[i]=-coord[i]; return result; }; // Surcharge de l'operateur - : realise la soustraction des // coordonnees de deux points #ifndef MISE_AU_POINT inline #endif CoordonneeB CoordonneeB::operator- (const CoordonneeB& c) const { #ifdef MISE_AU_POINT if ( dim!=c.dim ) { cout << "\nErreur : dimensions non egales !\n"; cout << "CoordonneeB::OPERATOR- (CoordonneeB ) \n"; Sortie(1); }; #endif CoordonneeB result(dim); for (int i=0;i<dim;i++) result.coord[i]=coord[i]-c.coord[i]; return result; }; // Surcharge de l'operateur + : realise l'addition des // coordonnees de deux points #ifndef MISE_AU_POINT inline #endif CoordonneeB CoordonneeB::operator+ (const CoordonneeB& c) const { #ifdef MISE_AU_POINT if ( dim!=c.dim ) { cout << "\nErreur : dimensions non egales !\n"; cout << "CoordonneeB::OPERATOR+ (CoordonneeB ) \n"; Sortie(1); }; #endif CoordonneeB result(dim); for (int i=0;i<dim;i++) result.coord[i]=coord[i]+c.coord[i]; return result; }; // Surcharge de l'operateur += #ifndef MISE_AU_POINT inline #endif void CoordonneeB::operator+= (const CoordonneeB& c) { #ifdef MISE_AU_POINT if ( dim!=c.dim ) { cout << "\nErreur : dimensions non egales !\n"; cout << "CoordonneeB::OPERATOR+= (CoordonneeB ) \n"; Sortie(1); }; #endif for (int i=0;i<dim;i++) coord[i]+=c.coord[i]; }; // Surcharge de l'operateur -= #ifndef MISE_AU_POINT inline #endif void CoordonneeB::operator-= (const CoordonneeB& c) { #ifdef MISE_AU_POINT if ( dim!=c.dim ) { cout << "\nErreur : dimensions non egales !\n"; cout << "CoordonneeB::OPERATOR-= (CoordonneeB ) \n"; Sortie(1); }; #endif for (int i=0;i<dim;i++) coord[i]-=c.coord[i]; }; // Surcharge de l'operateur *= #ifndef MISE_AU_POINT inline #endif void CoordonneeB::operator*= (double val) { for (int i=0;i<dim;i++) coord[i]*=val; }; // Surcharge de l'operateur * : multiplication de coordonnees par un scalaire #ifndef MISE_AU_POINT inline #endif CoordonneeB CoordonneeB::operator* (double val) const { CoordonneeB result(dim); for (int i=0;i<dim;i++) result.coord[i]=val*coord[i]; return result; }; // Surcharge de l'operateur * : produit scalaire entre coordonnees #ifndef MISE_AU_POINT inline #endif double CoordonneeB::operator* (const CoordonneeH& c) const { double res=0.0; for (int i=0;i<dim;i++) // somme des produits res+= coord[i] * c(i+1); return res; }; // produit scalaire entre coordonnees covariantes et covariantes #ifndef MISE_AU_POINT inline #endif double CoordonneeB::ScalBB(const CoordonneeB& c) const { double res=0.0; for (int i=0;i<dim;i++) // somme des produits res+= coord[i] * c(i+1); return res; }; // Surcharge de l'operateur / : division de coordonnees par un scalaire #ifndef MISE_AU_POINT inline #endif CoordonneeB CoordonneeB::operator/ (double val) const { #ifdef MISE_AU_POINT if(Dabs(val) <= ConstMath::trespetit) { cout << "\n erreur, division par zero "; cout << "\nCoordonneeB::operator/ (double val) " << endl; Sortie (1); } #endif CoordonneeB result(dim); for (int i=0;i<dim;i++) result.coord[i] = coord[i] / val; return result; }; // Surcharge de l'operateur /= : division de coordonnees par un scalaire #ifndef MISE_AU_POINT inline #endif void CoordonneeB::operator/= (double val) { #ifdef MISE_AU_POINT if(Dabs(val) <= ConstMath::trespetit) { cout << "\n erreur, division par zero "; cout << "\nCoordonneeB::operator/= (double val) " << endl; Sortie (1); } #endif for (int i=0;i<dim;i++) coord[i]/=val; }; // Surcharge de l'operateur == : test d'egalite // Renvoie 1 si les deux positions sont identiques // Renvoie 0 sinon #ifndef MISE_AU_POINT inline #endif int CoordonneeB::operator== (const CoordonneeB& c) const { if ( c.dim!=dim ) return 0; else { for (int i=0;i<dim;i++) { if ( c.coord[i]!=coord[i] ) return 0; }; return 1; }; }; // Surcharge de l'operateur != // Renvoie 1 si les deux positions ne sont pas identiques // Renvoie 0 sinon #ifndef MISE_AU_POINT inline #endif int CoordonneeB::operator!= (const CoordonneeB& c) const { if ( (*this)==c ) return 0; else return 1; }; // Affiche les coordonnees du point à l'écran #ifndef MISE_AU_POINT inline #endif void CoordonneeB::Affiche () const { cout << "\t{ "; for (int i=1;i<=dim;i++) cout << (*this)(i) << " "; cout << "}\n"; }; // Affiche les coordonnees du point dans sort #ifndef MISE_AU_POINT inline #endif void CoordonneeB::Affiche (ostream& sort) const { sort << "\t{ " ; for (int i=1;i<=dim;i++) sort << (*this)(i) << " " ; sort << "}\n" ; }; // Affiche les coordonnees du point dans sort sur nb digit plus un blanc // et rien d'autre #ifndef MISE_AU_POINT inline #endif void CoordonneeB::Affiche (ostream& sort,int nb) const { for (int i = 0; i<= this->dim-1; i++) sort << setw (nb) << this->coord[i] << " "; }; // conversion explicite en coordonnées sans variance #ifndef MISE_AU_POINT inline #endif Coordonnee CoordonneeB::Coor()const // ici on pourrait optimiser en créant un coordonnée const, avec la mémoire au même endroit // non !!! car this pourrait ne plus exister alors que le retour continue à exister !! donc pas bon { switch (dim) { case 1: {return Coordonnee(coord[0]); break;} case 2: {return Coordonnee(coord[0],coord[1]); break;} case 3: {return Coordonnee(coord[0],coord[1],coord[2]); break;} default: { cout << "\n erreur de dimension: dim= " << dim << " il n'est pas possible de transformer en Coordonnee !" << "\n CoordonneeB::Coor()const" ; Sortie(1); }; }; return Coordonnee(0.); // pour éviter le warning }; // création explicite en coordonnées sans variance // mais le vecteur est à la même place pour un coût de construction minimum, // il est accessible en lecture uniquement #ifndef MISE_AU_POINT inline #endif const Coordonnee CoordonneeB::Coor_const()const { return Coordonnee(dim,coord); }; // conversion explicite de B en H #ifndef MISE_AU_POINT inline #endif CoordonneeH CoordonneeB::Bas_haut()const // ici on pourrait optimiser en créant un coordonnée const, avec la mémoire au même endroit // non !!! car this pourrait ne plus exister alors que le retour continue à exister !! donc pas bon { switch (dim) { case 1: {return CoordonneeH(coord[0]); break;} case 2: {return CoordonneeH(coord[0],coord[1]); break;} case 3: {return CoordonneeH(coord[0],coord[1],coord[2]); break;} default: { cout << "\n erreur de dimension: dim= " << dim << " il n'est pas possible de transformer en CoordonneeH !" << "\n CoordonneeB::Bas_haut()const" ; Sortie(1); }; }; return CoordonneeH(0.); // pour éviter le warning }; // mise a zero des coordonnées #ifndef MISE_AU_POINT inline #endif void CoordonneeB::Zero() { for (int i=0;i<dim;i++) coord[i] =0.; }; // surcharge de l'operateur de lecture dans la mémoire #ifndef MISE_AU_POINT inline #endif // lecture brut des coordonnées sans la dimension void CoordonneeB::Lecture (UtilLecture& entreePrinc) { int dim = Dimension (); double tab[3]; for (int i = 0; i<= dim-1; i++) *(entreePrinc.entree) >> tab[i]; switch (dim) { case 1 : {CoordonneeB c1(tab[0]);(*this) = c1; break;} case 2 : {CoordonneeB c1(tab[0],tab[1]);(*this) = c1; break;} case 3 : {CoordonneeB c1(tab[0],tab[1],tab[2]);(*this) = c1; break;} } }; // surcharge de l'operateur de lecture #ifndef MISE_AU_POINT inline #endif istream & operator >> ( istream & ent, CoordonneeB & coo) { // lecture du type et vérification string nomtype; ent >> nomtype; if (nomtype != "CoordonneeB") { Sortie(1); return ent; } // lecture de la dimension int dim; ent >> nomtype >> dim ; // on redimensionne éventuellement la taille if (coo.dim != dim) { if (coo.memoire) // cas ou c'est un vrai point { if (coo.coord != NULL) { delete [] coo.coord;} coo.coord = new double [dim]; coo.dim = dim; } else { cout << "\n erreur en lecture la dimension du point conteneur "<< dim << " est differente de celle lue " << dim << " et memoire est faux, donc on ne peut pas changer la dimension " << "\n operator >> ( istream & ent, CoordonneeB & coo) " << endl ; Sortie(2); }; }; // les data for (int i = 0; i<= coo.dim-1; i++) ent >> coo.coord[i] ; return ent; }; // surcharge de l'operateur d'ecriture #ifndef MISE_AU_POINT inline #endif ostream & operator << ( ostream & sort,const CoordonneeB & coo) { // écriture du type et de la dimension sort << "CoordonneeB dim= " << coo.dim << " "; // les data for (int i = 0; i<= coo.dim-1; i++) sort << setprecision(ParaGlob::NbdigdoCA()) << coo.coord[i] << " "; // sort << "\n"; return sort; }; // Calcul de la norme euclidienne des composantes du point #ifndef MISE_AU_POINT inline #endif double CoordonneeB::Norme () const { double norme=0.0; for (int i=0;i<dim;i++) // somme du carre des composantes du vecteur norme=norme + coord[i] * coord[i]; norme=sqrt(norme); // calcul de la norme return norme; }; // norme le vecteur coordonnée #ifndef MISE_AU_POINT inline #endif CoordonneeB& CoordonneeB::Normer () { double norme = this->Norme(); #ifdef MISE_AU_POINT if(Dabs(norme) <= ConstMath::trespetit) { cout << "\n erreur, division par zero "; cout << "\nCoordonneeB::Normer () " << endl; Sortie (1); } #endif *this /= norme; return *this ; }; #ifndef MISE_AU_POINT inline #endif // Retourne le maximum en valeur absolue des composantes double CoordonneeB::Max_val_abs () const { double maxi=0.; switch (dim) { case 3: maxi=DabsMaX(maxi,coord[2]); case 2: maxi=DabsMaX(maxi,coord[1]); case 1: maxi=DabsMaX(maxi,coord[0]); case 0: break; }; return maxi; }; #ifndef MISE_AU_POINT inline #endif // Retourne le maximum en valeur absolue des composantes et l'indice correspondant double CoordonneeB::Max_val_abs (int& in) const { double maxi=0.; in = 0; switch (dim) { case 3: if (maxi < Dabs(coord[2])) {maxi=coord[2]; in=3;} case 2: if (maxi < Dabs(coord[1])) {maxi=coord[1]; in=2;} case 1: if (maxi < Dabs(coord[0])) {maxi=coord[0]; in=1;} case 0: break; }; return maxi; }; #ifndef MISE_AU_POINT inline #endif // Retourne le maximum en valeur absolue des composantes du Coordonnee // mais ramène la grandeur signée (avec son signe) double CoordonneeB::Max_val_abs_signe () const { double maxi=0.; int in = 0; switch (dim) { case 3: if (maxi < Dabs(coord[2])) {maxi=coord[2]; in=3;} case 2: if (maxi < Dabs(coord[1])) {maxi=coord[1]; in=2;} case 1: if (maxi < Dabs(coord[0])) {maxi=coord[0]; in=1;} case 0: break; }; if (in != 0) {return coord[in-1];} else {return maxi;}; }; #ifndef MISE_AU_POINT inline #endif // Retourne le maximum en valeur absolue des composantes du Coordonnee // mais ramène la grandeur signée (avec son signe) et l'indice double CoordonneeB::Max_val_abs_signe (int& in) const { double maxi=0.; in = 0; switch (dim) { case 3: if (maxi < Dabs(coord[2])) {maxi=coord[2]; in=3;} case 2: if (maxi < Dabs(coord[1])) {maxi=coord[1]; in=2;} case 1: if (maxi < Dabs(coord[0])) {maxi=coord[0]; in=1;} case 0: break; }; if (in != 0) {return coord[in-1];} else {return maxi;}; }; #ifndef MISE_AU_POINT inline #endif // modifie éventuellement les coordonnées de this pour quelles soient supérieures ou égales // aux coordonnées en paramètre void CoordonneeB::Modif_en_max(const CoordonneeB& v) { for (int i=1;i<=dim;i++) if (coord[i-1] < v(i)) coord[i-1]=v(i); }; #ifndef MISE_AU_POINT inline #endif // modifie éventuellement les coordonnées de this pour quelles soient inférieures ou égales // aux coordonnées en paramètre void CoordonneeB::Modif_en_min(const CoordonneeB& v) { for (int i=1;i<=dim;i++) if (coord[i-1] > v(i)) coord[i-1]=v(i); }; #ifndef MISE_AU_POINT inline #endif // ajoute une même valeur à tous les coordonnées void CoordonneeB::Ajout_meme_valeur(double val) { for (int i=0;i<dim;i++) coord[i] += val; }; #ifndef MISE_AU_POINT inline #endif // sortie du schemaXML: en fonction de enu void CoordonneeB::SchemaXML_Coordonnee(ostream& sort,const Enum_IO_XML enu) { switch (enu) { case XML_TYPE_GLOBAUX : {sort << "\n <!-- *************************** CoordonneeB *************************** -->" << "\n<xs:complexType name=\"COORDONNEE_B\" >" << "\n <xs:annotation>" << "\n <xs:documentation> coordonnee de dimension 1 ou 2 ou 3: elements: " << "\n un entier (dim) donnant la dimension, et dim reels " << "\n </xs:documentation>" << "\n </xs:annotation>" << "\n <xs:sequence>" << "\n <xs:element name=\"dimension\" type=\"xs:double\" />" << "\n <xs:element name=\"coordonnees\" >" << "\n <xs:simpleType>" << "\n <xs:restriction base=\"liste_de_reels\">" << "\n <xs:minLength value=\"1\" />" << "\n <xs:maxLength value=\"3\" />" << "\n </xs:restriction>" << "\n </xs:simpleType>" << "\n </xs:element>" << "\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; } }; }; #endif