En fait, le message est directement écrit en (X)html dans l'éditeur. Du coups, si tu cliques sur "html", tu peux voir ton message entouré de tout le code qui lui donne sa forme actuelle
Pour une citation, on aura deux éléments:
une mise en gras de la personne qui est citée, qui utilise la balise <strong>et qui correspond au code html
<p><strong> XXX a écrit</strong></p>
et la citation elle-même qui utilise la balise <blockquote> et qui correspond au code html
<blockquote>
<p>Ce qui se conçoit bien s'énonce clairement</p>
<p>Et les mots pour le dire viennent aisément</p>
</blockquote>
Tu remarquera aussi la présence des balises <p> dans ces deux codes: ils correspond aux paragraphes qui apparaissent
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
En fait, le message est directement écrit en (X)html dans l'éditeur. Du coups, si tu cliques sur "html", tu peux voir ton message entouré de tout le code qui lui donne sa forme actuelle
Ça y est : j'ai "convergé" sur le modèle de données : quel contenu à donner pour les nœuds, les mailles et le maillage.
Je n'en suis pas encore à interpoler, ni à construire le maillage de façon "intelligente" (méthode incrémentale) mais j'ai quelque chose à vous soumettre :
-> avec une construction de maillage par une méthode "bestiale" - qui ne me sert pour l'instant qu'à générer des cas de référence pour la validation de la future méthode incrémentale.
-> je ne vous demande pas de commenter la méthode "bestiale" : elle disparaîtra sous peu.
1. Le programme principal
a) Lit le fichier de données utilisateur : abscisses dimensionnées, ordonnées dimensionnées, valeurs de la fonction
b) Fabrique l'objet Noeuds en éliminant (sur option) les noeuds trop proches
> pour lmghs : je n'ai pas encore compris comment utiliser la fonction remove_if car :
non seulement je travaille sur 2 tableaux de concert : pour l'instant, mais j'envisage d'inclure le tableau de z avec les autres (x, y) => cette difficulté disparaîtra
mais aussi : le critère d'élimination ne porte pas sur la valeur du nœud elle-même mais sur sa proximité avec les autres nœuds. Je n'arrive donc pas à formuler la fonction logique qui déclenche l'élimination.
c) Repère le répertoire de travail de l'utilisateur et élabore les noms des fichiers de sortie
d) Construit le maillage par la méthode "bestiale" pour l'instant
#include <cmath>
#include "Noeuds.h"
#include "utils.h"
#include "Maille.h"
void construireMaillageForceBrute (const Noeuds * Nds,
std::list < Maille_dev > &Maillage);
int
auditMaillage (const Noeuds * Nds,
const std::list < Maille_dev > &Maillage,
const std::filesystem::path &fichierAudit,
const std::filesystem::path &fichierTraceGpl);
int
main (int argc, char *argv[])
{
if (argc < 2)
{
std::
cerr << "Il faut préciser le nom du fichier d'entrée." << std::endl
<< "Arrêt du programme." << std::endl;
return EXIT_FAILURE;
}
// Lecture du fichier d'entrée et chargement des vecteurs de données
std::vector < double >tab_xd, tab_yd, tab_z;
if (lectureFichier (argv[1], tab_xd, tab_yd, tab_z) != EXIT_SUCCESS)
return EXIT_FAILURE;
// Création des noms de fichiers de sortie
std::filesystem::path fichierEntree = argv[1];
std::filesystem::path dum = fichierEntree;
std::filesystem::path fichierNoeuds =
dum.replace_filename ("noeuds_retenus.txt");
dum = fichierEntree;
std::filesystem::path fichierAudit =
dum.replace_filename ("audit_maillage.txt");
dum = fichierEntree;
std::filesystem::path fichierTraceGpl =
dum.replace_filename ("trace_maillage_gpl.dat");
// Construction et édition des noeuds
Noeuds Nds (tab_xd, tab_yd, tab_z, true);
Nds.edit (fichierNoeuds);
// Construction du maillage par la méthode combinatoire
std::list < Maille_dev > Maillage;
construireMaillageForceBrute (&Nds, Maillage);
auditMaillage (&Nds, Maillage, fichierAudit, fichierTraceGpl);
// Sortie normale
return EXIT_SUCCESS;
}
2. La classe Noeuds
Le .h
class Noeuds
{
private:
// Coordonnées adimensionnées de noeuds
std::vector < std::array < double, 2 >> m_xy;
std::vector < double >m_z; // valeurs de la fonction aux noeuds
double m_xdmin; // min des abscisses dimensionnées des noeuds
double m_ydmin; // min des ordonnées dimensionnées des noeuds
// Etendues des abscisses et ordonnées dimensionnées
double m_range_xd;
double m_range_yd;
// Inverses des étendues des abscisses et ordonnées dimensionnées
double m_inv_range_xd;
double m_inv_range_yd;
public:
// Le constructeur autorisé
Noeuds (const std::vector < double >&xd, const std::vector < double >&yd,
const std::vector < double >&z, bool elim = false);
// Accesseurs aux caractéristiques des noeuds (coord. adimensionnées)
size_t getNpt () const
{
return m_z.size ();
}
std::vector < std::array < double, 2 >>::const_iterator getItCoord
(size_t i) const
{
assert (i < m_xy.size ());
return (m_xy.begin () + i);
}
double getZ (size_t i) const
{
assert (i < m_z.size ());
return m_z[i];
}
// Edition des attributs de la classe sur fichier ASCII
int edit (const std::filesystem::path &fichierNoeuds) const;
// Adimensionnement des abscisses et ordonnées d'un point quelconque
std::array < double, 2 >
adimXYd (const std::array < double, 2 > &xyd) const;
// Re-dimensionnement des abscisses et ordonnées d'un point quelconque
std::array < double, 2 > dimXY (const std::array < double, 2 > &xy) const;
std::array < double, 2 > dimXY (double x, double y) const;
};
Le .cpp
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <algorithm>
#include <cassert> // assert appelé dans la déclaration de classe Noeuds
#include <array> // std::array utilisé dans les accesseurs inline de Noeuds
#include <filesystem> // utilisé dans Noeuds.h
#include "Noeuds.h"
#include "utils.h" // pour bénéficier des fonctions sur les array
Noeuds::Noeuds (const std::vector < double >&xd,
const std::vector < double >&yd,
const std::vector < double >&z, bool elim):
m_xy (0),
m_z (z),
m_xdmin (0.),
m_ydmin (0.),
m_range_xd (0.),
m_range_yd (0.),
m_inv_range_xd (0.),
m_inv_range_yd (0.)
{
// Récupération des min/max sur les abscisses et ordonnées dimensionnées
// Note : requiert C++17
auto [min_xd, max_xd] = std::minmax_element (xd.begin (), xd.end ());
m_xdmin = *min_xd;
m_range_xd = *max_xd - m_xdmin;
m_inv_range_xd = 1./m_range_xd;
auto [min_yd, max_yd] = std::minmax_element (yd.begin (), yd.end ());
m_ydmin = *min_yd;
m_range_yd = *max_yd - m_ydmin;
m_inv_range_yd = 1./m_range_yd;
// Calcul des abscisses et ordonnées adimensionnées
for (size_t i = 0; i < m_z.size (); i++)
{
std::array < double, 2 > point;
point[0] = (xd[i] - m_xdmin) * m_inv_range_xd;
point[1] = (yd[i] - m_ydmin) * m_inv_range_yd;
m_xy.push_back (point);
}
// Suppression des noeuds trop proches les uns des autres (sur option).
// Dans un tel cas, on n'en conserve qu'un par couple de noeuds trop proches.
// Attention : il faut travailler de concert sur les vecteurs m_xy et m_z.
if (elim)
{
const double dsqMin = 1.e-04;
for (size_t i = 0; i < m_z.size () - 1; i++)
for (size_t j = i + 1; j < m_z.size (); j++)
if ((m_xy[j] - m_xy[i]) * (m_xy[j] - m_xy[i]) < dsqMin)
{
std::vector < std::array < double, 2 >>::iterator it_xy =
m_xy.begin () + j;
m_xy.erase (it_xy);
std::vector < double >::iterator it_z = m_z.begin () + j;
m_z.erase (it_z);
std::cout << "Elimination du point " << j << " trop proche"
<< " du point " << i << std::endl;
// Décrémenter j pour examiner les nouveaux promus à l'indice j
j--;
}
}
// Optimisation de l'espace les vecteurs sont désormais figés
m_xy.shrink_to_fit ();
m_z.shrink_to_fit ();
}
// Adimensionnement des abscisses et ordonnées d'un point quelconque
std::array < double, 2 >
Noeuds::adimXYd (const std::array < double, 2 > &xyd) const
{
std::array < double, 2 > xy;
xy[0] = (xyd[0] - m_xdmin) * m_inv_range_xd;
xy[1] = (xyd[1] - m_ydmin) * m_inv_range_yd;
return xy;
}
// Re-dimensionnement des abscisses et ordonnées d'un point quelconque
std::array < double, 2 >
Noeuds::dimXY (const std::array < double, 2 > &xy) const
{
std::array < double, 2 > xyd;
xyd[0] = m_xdmin + xy[0] * m_range_xd;
xyd[1] = m_ydmin + xy[1] * m_range_yd;
return xyd;
}
std::array < double, 2 > Noeuds::dimXY (double x, double y) const
{
std::array < double, 2 > xyd;
xyd[0] = m_xdmin + x * m_range_xd;
xyd[1] = m_ydmin + y * m_range_yd;
return xyd;
}
// Edition du contenu de l'objet Noeuds
int
Noeuds::edit (const std::filesystem::path &fichierNoeuds) const
{
// Ouverture du fichier d'édition
std::ofstream outfl (fichierNoeuds);
if (!outfl)
{
std::cerr << "Impossible d'ouvrir le fichier d'édition des noeuds."
<< std::endl;
return EXIT_FAILURE;
}
// Edition des bornes min et des étendues
outfl << std::setw (11) << std::setiosflags (std::ios::left) << "xd min"
<< std::setw (11) << "xd range" << std::setw (11) << "yd min"
<< std::setw (11) << "yd range" << std::endl;
outfl << std::setw (10) << m_xdmin << " " << std::setw (10) << m_range_xd
<< " " << std::setw (10) << m_ydmin << " " << std::setw (10)
<< m_range_yd << std::endl << std::endl;
// Edition des noeuds en coordonnées adimensionnées
outfl << std::setw (7) << std::setiosflags (std::ios::left) << "i"
<< std::setw (11) << "x " << std::setw (11) << "y " << std:: setw (11)
<< "z" << std::endl;
for (size_t i = 0; i < m_z.size (); i++)
outfl << std::setw (6) << std::setiosflags (std::ios::left) << i
<< " " << std::setw (10) << m_xy[i][0] << " "
<< std::setw (10) << m_xy[i][1] << " " << std::setw (10)
<< m_z[i] << std::endl;
// Retour normal à l'appelant
return EXIT_SUCCESS;
}
3. La classe Maille
Le .h
// Maille en contexte opérationnel : à maillage figé
class Maille_op
{
protected:
// Itérateurs sur les coordonnées (x, y) des 3 sommets du triangle
std::vector < std::array < double, 2 >>::const_iterator m_it_sommet0;
std::vector < std::array < double, 2 >>::const_iterator m_it_sommet1;
std::vector < std::array < double, 2 >>::const_iterator m_it_sommet2;
// 2 * aire du triangle (signée)
double m_2Aire;
// Inverse de 2 * aire du triangle : mémorisée pour éviter les divisions
double m_inv_2Aire;
public:
Maille_op (size_t i, size_t j, size_t k, const Noeuds * Nds);
bool estDegenere () const
{
/* --------------------------------------------------------
* Test si la maille est dégénérée : 3 points quasi-alignés
* -------------------------------------------------------- */
const double deux_Aire_min = 1.e-04;
return fabs (m_2Aire) < deux_Aire_min;
}
void editMaille (std::vector < std::array < double,
2 >>::const_iterator & it_s0,
std::vector < std::array < double,
2 >>::const_iterator & it_s1,
std::vector < std::array < double,
2 >>::const_iterator & it_s2, double &deuxAire) const;
};
// Maille en contexte de construction du maillage
class Maille_dev:public Maille_op
{
private:
// Centre du cercle qui circonscrit la maille triangulaire
std::array < double, 2 > m_circle_centre;
// Carré du rayon du cercle qui circonscrit la maille triangulaire
double m_circle_rsq;
public:
Maille_dev (size_t i, size_t j, size_t k, const Noeuds * Nds);
// Détermine si un noeud quelconque est dans le cercle circonscrit d'une maille
bool estDansCercle (size_t ipoint, const Noeuds * Nds) const
{
const double tolerance = 1.e-04;
std::vector < std::array < double, 2 >>::const_iterator point
= Nds->getItCoord (ipoint);
return ((*point - m_circle_centre) * (*point - m_circle_centre)
< (m_circle_rsq - tolerance));
}
};
xd min xd range yd min yd range
-18.071 33.252 -19.46 36.681
i x y z
0 0.891465 0.997928 4.749
1 1 0.714348 5.777
2 0.915524 0.314686 4.841
3 0.738933 0.0663286 4.221
4 0.382383 0.803986 4.925
5 0 0.711731 5.154
6 0.00153374 1 3.704
7 0.0497414 0.317903 5.003
8 0.559305 0.315422 9.791
9 0.428937 0.236744 5.888
10 0.132022 0.838063 4.559
11 0.666967 0.334696 11.663
12 0.152773 0.00248085 4.083
13 0.704529 0.377798 8.921
14 0.317515 0 4.73
15 0.96304 0.152259 4.78
Le maillage trouvé donne la figure ci-dessous, et il répond bien aux critères de Delaunay :
En résumé : le programme fait ce que je veux qu'il soit fait pour l'instant - je n'en suis qu'à l'étape de construction et de critique du maillage.
Y a-t-il des points qui vous heurtent ? Je ne suis pas très content de ma manipulation de noms de fichiers dans main, mais je n'ai pas trouvé autre chose.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Discord NaN. Mon site.