diff --git a/src/Core/Topo/EdgeMeshingPropertyBeta.cpp b/src/Core/Topo/EdgeMeshingPropertyBeta.cpp index 8ee77cb8..b443c80b 100644 --- a/src/Core/Topo/EdgeMeshingPropertyBeta.cpp +++ b/src/Core/Topo/EdgeMeshingPropertyBeta.cpp @@ -17,30 +17,27 @@ namespace Mgx3D { /*----------------------------------------------------------------------------*/ namespace Topo { /*----------------------------------------------------------------------------*/ -#define _DEBUG_beta -/*----------------------------------------------------------------------------*/EdgeMeshingPropertyBeta:: -EdgeMeshingPropertyBeta(int nb, double beta, bool isDirect, bool initWithFirstEdge, double meshingEdgeLength) -: CoEdgeMeshingProperty(nb, beta_resserrement, isDirect) +//#define _DEBUG_beta +/*----------------------------------------------------------------------------*/ +EdgeMeshingPropertyBeta:: +EdgeMeshingPropertyBeta(int nbBras, double beta, bool isDirect, + bool initWithFirstEdge, double meshingEdgeLength) +: CoEdgeMeshingProperty(nbBras, beta_resserrement, isDirect) , m_beta(beta) , m_arm1(meshingEdgeLength) , m_initWithArm1(initWithFirstEdge) { - if (!m_initWithArm1 && m_beta<=1.0){ + if (!m_initWithArm1 && (m_beta<1.00001 || m_beta>1.01)){ TkUtil::UTF8String messErr (TkUtil::Charset::UTF_8); - messErr << "EdgeMeshingPropertyBeta, la valeur de beta doit être légèrement supérieur à 1, actuellement : "<2.0){ - TkUtil::UTF8String messErr (TkUtil::Charset::UTF_8); - messErr << "EdgeMeshingPropertyBeta, la longueur de beta n'a pas été testé jusque là "<m_nb_edges){ +#ifdef _DEBUG_beta + std::cout<<"EdgeMeshingPropertyBeta::initCoeff() "<m_nb_edges){ - TkUtil::UTF8String messErr (TkUtil::Charset::UTF_8); - messErr<<"EdgeMeshingPropertyGeometric::nextCoeff est en dehors des limites: dernierIndice : " - <<(long)m_dernierIndice<<", nb de bras : "<<(long)m_nb_edges; - throw TkUtil::Exception(messErr); - } -#endif if (m_sens){ m_dernierCoeff *= m_raison; m_dernierSommeCoeff += m_dernierCoeff; @@ -280,8 +273,8 @@ computeRaison(const double lg) double lg_iter = computePolynome(raison); #ifdef _DEBUG_raison - std::cout<<"iter "< 0; * en pratique beta peut varier de 1.01 (peu resséré) à 1.00001 (très resséré) + * Si la longueur du premier bras est non nulle, alors beta est calculé */ EdgeMeshingPropertyBeta(int nb, double beta, bool isDirect=true, bool initWithFirstEdge=false, double meshingEdgeLength=0.0); + /// Pour les pythoneries, cast par opérateur = : EdgeMeshingPropertyBeta (const CoEdgeMeshingProperty&); @@ -43,19 +46,31 @@ class EdgeMeshingPropertyBeta : public CoEdgeMeshingProperty { /// Accesseur sur le nom de la méthode de maillage virtual std::string getMeshLawName() const {return "Beta";} + /// change le nombre de bras demandé pour un côté + virtual void setNbEdges(const int nb); + /// le ratio entre deux bras successifs double getBeta() const {return m_beta;} -#ifndef SWIG + bool initWithFirstEdge() const {return m_initWithArm1;} + + /// longueur de la première arête + double getFirstEdgeLength() const {return m_arm1;} + void setFirstEdgeLength(const double & arm1) {m_arm1 = arm1;} + + #ifndef SWIG /** Création d'un clone, on copie toutes les informations */ virtual CoEdgeMeshingProperty* clone() {return new EdgeMeshingPropertyBeta(*this);} - /// retourne le coefficient suivant pour les noeuds internes - virtual double nextCoeff(); + // initialisation avant appel à nextCoeff + virtual void initCoeff(); /// initialisation avant appel à nextCoeff pour le cas où la longueur est utile virtual void initCoeff(double length); + /// retourne le coefficient suivant pour les noeuds internes + virtual double nextCoeff(); + /*------------------------------------------------------------------------*/ /// Script pour la commande de création Python virtual TkUtil::UTF8String getScriptCommand() const; @@ -72,9 +87,7 @@ class EdgeMeshingPropertyBeta : public CoEdgeMeshingProperty { /** f(eta) : est en sortie de resserre, ça peut être vu comme la position du point après resserrement (feta=0 --> paroi, feta=1--> frontière amont) - - transformation de (0,1) sur (0,1) permettant de resserrer - le maillage au voisinage du corps + transformation de (0,1) sur (0,1) permettant de resserrer le maillage au voisinage du corps */ double resserre(double eta, double beta); @@ -83,8 +96,8 @@ class EdgeMeshingPropertyBeta : public CoEdgeMeshingProperty { /// valeur de beta pour le resserrement (de la forme 1+epsilon) double m_beta; - double m_arm1; + /// vrai si c'est la longueur du premier bras qui permet de déterminer beta bool m_initWithArm1; }; diff --git a/src/Core/protected/Topo/EdgeMeshingPropertyGeometric.h b/src/Core/protected/Topo/EdgeMeshingPropertyGeometric.h index 7c3be015..215e8788 100644 --- a/src/Core/protected/Topo/EdgeMeshingPropertyGeometric.h +++ b/src/Core/protected/Topo/EdgeMeshingPropertyGeometric.h @@ -31,11 +31,14 @@ class EdgeMeshingPropertyGeometric : public CoEdgeMeshingProperty { * Si la longueur du premier bras est non nulle, alors le ratio est calculé * à l'aide de la longueur de l'arête (projetée s'il y a lieu) */ - EdgeMeshingPropertyGeometric(int nb, double raison, bool isDirect=true, bool initWithFirstEdge=false, double meshingEdgeLength=0.0); + EdgeMeshingPropertyGeometric(int nb, double raison, bool isDirect=true, + bool initWithFirstEdge=false, double meshingEdgeLength=0.0); /// idem avec un centre pour découpage polaire EdgeMeshingPropertyGeometric(int nb, double raison, - Utils::Math::Point polar_center, bool isDirect=true, bool initWithFirstEdge=false, double meshingEdgeLength=0.0); + Utils::Math::Point polar_center, bool isDirect=true, + bool initWithFirstEdge=false, double meshingEdgeLength=0.0); + /// Pour les pythoneries, cast par opérateur = : EdgeMeshingPropertyGeometric (const CoEdgeMeshingProperty&); /*------------------------------------------------------------------------*/ @@ -51,14 +54,12 @@ class EdgeMeshingPropertyGeometric : public CoEdgeMeshingProperty { /// le ratio entre deux bras successifs double getRatio() const {return m_raison;} - void setRatio(const double & ratio) {m_raison = ratio;} bool initWithFirstEdge() const {return m_initWithArm1;} /// longueur de la première arête double getFirstEdgeLength() const {return m_arm1;} - void setFirstEdgeLength(const double & arm1) {m_arm1 = arm1;} #ifndef SWIG diff --git a/src/QtComponents/QtEdgeMeshingPropertyAction.cpp b/src/QtComponents/QtEdgeMeshingPropertyAction.cpp index cad66fb0..1e381982 100644 --- a/src/QtComponents/QtEdgeMeshingPropertyAction.cpp +++ b/src/QtComponents/QtEdgeMeshingPropertyAction.cpp @@ -363,7 +363,9 @@ EdgeMeshingPropertyUniform* QtGeometricProgressionPanel::QtGeometricProgressionPanel ( QWidget* parent, double factor, QtMgx3DMainWindow& window) : QtDiscretisationPanelIfc (parent, window), - _buttonGroup (0), _factorRadioButton (0), _factorTextField (0), _firstEdgeLengthRadioButton (0), _firstEdgeLengthTextField(0), _orientationCheckBox (0) + _buttonGroup (0), _factorRadioButton (0), _factorTextField (0), + _firstEdgeLengthRadioButton (0), _firstEdgeLengthTextField(0), + _orientationCheckBox (0) { QVBoxLayout* layout = new QVBoxLayout (this); layout->setContentsMargins ( @@ -392,10 +394,10 @@ QtGeometricProgressionPanel::QtGeometricProgressionPanel ( connect (_factorTextField, SIGNAL (editingFinished ( )), this, SLOT (discretisationModifiedCallback ( ))); - // La longueur de la première arête : + // La longueur du premier segment : QHBoxLayout* hlayout2 = new QHBoxLayout ( ); layout->addLayout (hlayout2); - _firstEdgeLengthRadioButton = new QRadioButton("Longueur de la première arête :", this); + _firstEdgeLengthRadioButton = new QRadioButton("Longueur du premier segment :", this); hlayout2->addWidget (_firstEdgeLengthRadioButton); _buttonGroup->addButton(_firstEdgeLengthRadioButton); connect (_firstEdgeLengthRadioButton, SIGNAL(clicked()), this, @@ -467,7 +469,6 @@ void QtGeometricProgressionPanel::reset ( ) void QtGeometricProgressionPanel::setMeshingProperty ( const CoEdgeMeshingProperty& cemp) { - std::cout << "Dans QtGeometricProgressionPanel::setMeshingProperty " << std::endl; CHECK_NULL_PTR_ERROR (_factorTextField) CHECK_NULL_PTR_ERROR (_firstEdgeLengthTextField) CHECK_NULL_PTR_ERROR (_orientationCheckBox) @@ -505,8 +506,8 @@ double QtGeometricProgressionPanel::getFirstEdgeLength ( ) const double QtGeometricProgressionPanel::initWithFirstEdgeLength () const { - CHECK_NULL_PTR_ERROR (_factorTextField) - return (_firstEdgeLengthRadioButton->isChecked()); + CHECK_NULL_PTR_ERROR (_firstEdgeLengthRadioButton) + return _firstEdgeLengthRadioButton->isChecked(); } bool QtGeometricProgressionPanel::invertOrientation ( ) const @@ -1438,7 +1439,9 @@ EdgeMeshingPropertyHyperbolic* QtBetaDiscretisationPanel::QtBetaDiscretisationPanel ( QWidget* parent, double factor, QtMgx3DMainWindow& window) : QtDiscretisationPanelIfc (parent, window), - _betaTextField (0), _orientationCheckBox (0) + _buttonGroup (0), _betaRadioButton (0), _betaTextField (0), + _firstEdgeLengthRadioButton (0), _firstEdgeLengthTextField(0), + _orientationCheckBox (0) { QVBoxLayout* layout = new QVBoxLayout (this); setLayout (layout); @@ -1449,17 +1452,39 @@ QtBetaDiscretisationPanel::QtBetaDiscretisationPanel ( Resources::instance ( )._margin.getValue ( )); layout->setSpacing (Resources::instance ( )._spacing.getValue ( )); + _buttonGroup = new QButtonGroup(this); + _buttonGroup->setExclusive(true); + // Le facteur de resserrement beta : QHBoxLayout* hlayout = new QHBoxLayout ( ); layout->addLayout (hlayout); - QLabel* label = new QLabel (QString::fromUtf8("Bêta resserrement :"), this); - hlayout->addWidget (label); + _betaRadioButton = new QRadioButton("Bêta resserrement :", this); + hlayout->addWidget (_betaRadioButton); + _buttonGroup->addButton(_betaRadioButton); + _betaRadioButton->setChecked (true); + connect (_betaRadioButton, SIGNAL(clicked()), this, + SLOT (betaRadioButtonSelected ())); _betaTextField = &QtNumericFieldsFactory::createRatioTextField (this); - _betaTextField->setValue (1.1); + _betaTextField->setValue (1.01); hlayout->addWidget (_betaTextField); connect (_betaTextField, SIGNAL (editingFinished ( )), this, SLOT (discretisationModifiedCallback ( ))); + // La longueur de la première arête : + QHBoxLayout* hlayout2 = new QHBoxLayout ( ); + layout->addLayout (hlayout2); + _firstEdgeLengthRadioButton = new QRadioButton("Longueur du premier segment :", this); + hlayout2->addWidget (_firstEdgeLengthRadioButton); + _buttonGroup->addButton(_firstEdgeLengthRadioButton); + connect (_firstEdgeLengthRadioButton, SIGNAL(clicked()), this, + SLOT (firstEdgeLengthRadioButton ( ))); + _firstEdgeLengthTextField = &QtNumericFieldsFactory::createDistanceTextField (this); + _firstEdgeLengthTextField->setValue (1.0); + _firstEdgeLengthTextField->setEnabled(false); + hlayout2->addWidget (_firstEdgeLengthTextField); + connect (_firstEdgeLengthTextField, SIGNAL (editingFinished ( )), this, + SLOT (discretisationModifiedCallback ( ))); + // Le sens de la discrétisation : _orientationCheckBox = new QCheckBox ("Inverser le sens", this); layout->addWidget (_orientationCheckBox); @@ -1475,7 +1500,8 @@ QtBetaDiscretisationPanel::QtBetaDiscretisationPanel ( const QtBetaDiscretisationPanel& p) : QtDiscretisationPanelIfc ( 0, *new QtMgx3DMainWindow(0)), - _betaTextField (0), _orientationCheckBox (0) + _buttonGroup (0), _betaRadioButton (0), _firstEdgeLengthRadioButton (0), + _betaTextField (0), _firstEdgeLengthTextField (0), _orientationCheckBox (0) { MGX_FORBIDDEN ("QtBetaDiscretisationPanel copy constructor is not allowed."); } // QtBetaDiscretisationPanel::QtBetaDiscretisationPanel @@ -1498,8 +1524,13 @@ void QtBetaDiscretisationPanel::reset ( ) { BEGIN_QT_TRY_CATCH_BLOCK + _betaRadioButton->setChecked(true); + CHECK_NULL_PTR_ERROR (_betaTextField) - _betaTextField->setValue (1.1); + _betaTextField->setValue (1.01); + + CHECK_NULL_PTR_ERROR (_firstEdgeLengthTextField) + _firstEdgeLengthTextField->setValue (1.0); COMPLETE_QT_TRY_CATCH_BLOCK (true, this, "Magix 3D") @@ -1511,6 +1542,7 @@ void QtBetaDiscretisationPanel::setMeshingProperty ( const CoEdgeMeshingProperty& cemp) { CHECK_NULL_PTR_ERROR (_betaTextField) + CHECK_NULL_PTR_ERROR (_firstEdgeLengthTextField) CHECK_NULL_PTR_ERROR (_orientationCheckBox) const EdgeMeshingPropertyBeta* properties = @@ -1523,6 +1555,9 @@ void QtBetaDiscretisationPanel::setMeshingProperty ( } // if (0 == properties) _betaTextField->setValue (properties->getBeta ( )); + _firstEdgeLengthTextField->setValue (properties->getFirstEdgeLength ( )); + _betaRadioButton->setChecked(!properties->initWithFirstEdge()); + _firstEdgeLengthRadioButton->setChecked(properties->initWithFirstEdge()); _orientationCheckBox->setCheckState ( true == properties->getDirect ( ) ? Qt::Unchecked : Qt::Checked); QtDiscretisationPanelIfc::setMeshingProperty(cemp); @@ -1536,6 +1571,17 @@ double QtBetaDiscretisationPanel::getBeta ( ) const return _betaTextField->getValue ( ); } // QtBetaDiscretisationPanel::getBeta +double QtBetaDiscretisationPanel::getFirstEdgeLength ( ) const +{ + CHECK_NULL_PTR_ERROR (_firstEdgeLengthTextField) + return _firstEdgeLengthTextField->getValue ( ); +} // QtBetaDiscretisationPanel::getFirstEdgeLength + +double QtBetaDiscretisationPanel::initWithFirstEdgeLength () const +{ + CHECK_NULL_PTR_ERROR (_firstEdgeLengthRadioButton) + return (_firstEdgeLengthRadioButton->isChecked()); +} bool QtBetaDiscretisationPanel::invertOrientation ( ) const { @@ -1549,7 +1595,8 @@ EdgeMeshingPropertyBeta* { EdgeMeshingPropertyBeta* emp = new EdgeMeshingPropertyBeta ( - edgeNum, getBeta ( ), !invertOrientation ( )); + edgeNum, getBeta ( ), !invertOrientation ( ), + initWithFirstEdgeLength(), getFirstEdgeLength()); updateProperty (*emp); return emp; diff --git a/src/QtComponents/protected/QtComponents/QtEdgeMeshingPropertyAction.h b/src/QtComponents/protected/QtComponents/QtEdgeMeshingPropertyAction.h index 75ed94fc..59af6df5 100644 --- a/src/QtComponents/protected/QtComponents/QtEdgeMeshingPropertyAction.h +++ b/src/QtComponents/protected/QtComponents/QtEdgeMeshingPropertyAction.h @@ -308,7 +308,7 @@ class QtGeometricProgressionPanel : public QtDiscretisationPanelIfc QRadioButton* _factorRadioButton; QtDoubleTextField* _factorTextField; - /** La saisie de la raison de la progression géométrique. */ + /** La saisie de la longueur de la première arête. */ QRadioButton* _firstEdgeLengthRadioButton; QtDoubleTextField* _firstEdgeLengthTextField; @@ -320,8 +320,6 @@ class QtGeometricProgressionPanel : public QtDiscretisationPanelIfc void factorRadioButtonSelected() { _factorTextField->setEnabled(true); _firstEdgeLengthTextField->setEnabled(false); } void firstEdgeLengthRadioButton() { _factorTextField->setEnabled(false); _firstEdgeLengthTextField->setEnabled(true); } - - }; // class QtGeometricProgressionPanel @@ -748,7 +746,8 @@ class QtBetaDiscretisationPanel : public QtDiscretisationPanelIfc * utilisée notamment pour récupérer le contexte. */ QtBetaDiscretisationPanel ( - QWidget* parent, double beta, + QWidget* parent, + double beta, Mgx3D::QtComponents::QtMgx3DMainWindow& mw); /** @@ -772,6 +771,17 @@ class QtBetaDiscretisationPanel : public QtDiscretisationPanelIfc */ virtual double getBeta ( ) const; + /** + * \return La longueur de la première arête. + */ + virtual double getFirstEdgeLength ( ) const; + + /** + * \ return Si on initialise à partir de la longueur de la première arête + * Par défaut False -> on initialise à partir de la raison + */ + virtual double initWithFirstEdgeLength () const; + /** * \return true s'il faut inverser l'orientation du découpage, * false dans le sens contraire. @@ -795,11 +805,24 @@ class QtBetaDiscretisationPanel : public QtDiscretisationPanelIfc QtBetaDiscretisationPanel& operator = ( const QtBetaDiscretisationPanel&); + QButtonGroup* _buttonGroup; + /** La saisie du facteur beta de resserrement. */ + QRadioButton* _betaRadioButton; QtDoubleTextField* _betaTextField; + /** La saisie de la longueur de la première arête. */ + QRadioButton* _firstEdgeLengthRadioButton; + QtDoubleTextField* _firstEdgeLengthTextField; + /** Faut il inverser le sens de discrétisation ? */ QCheckBox* _orientationCheckBox; + + private slots: + + void betaRadioButtonSelected() { _betaTextField->setEnabled(true); _firstEdgeLengthTextField->setEnabled(false); } + void firstEdgeLengthRadioButton() { _betaTextField->setEnabled(false); _firstEdgeLengthTextField->setEnabled(true); } + }; // class QtBetaDiscretisationPanel diff --git a/test_link/test_beta_shrinkage_law.py b/test_link/test_beta_shrinkage_law.py new file mode 100644 index 00000000..c8708015 --- /dev/null +++ b/test_link/test_beta_shrinkage_law.py @@ -0,0 +1,30 @@ +import pyMagix3D as Mgx3D +import pytest + +def test_beta_shrinkage_law(capfd): + ctx = Mgx3D.getStdContext() + gm = ctx.getGeomManager() + tm = ctx.getTopoManager() + mm = ctx.getMeshManager() + # Création d'une boite avec une topologie + ctx.getTopoManager().newBoxWithTopo (Mgx3D.Point(0, 0, 0), Mgx3D.Point(1, 1, 1), 10, 10, 10) + + with pytest.raises(RuntimeError) as excinfo: + # Changement de discrétisation pour les arêtes Ar0011 + emp = Mgx3D.EdgeMeshingPropertyBeta(10,1.02) + ctx.getTopoManager().setMeshingProperty (emp, ["Ar0011"]) + expected = "la valeur de beta doit être comprise entre 1 et 1.01" + assert expected in str(excinfo.value) + + with pytest.raises(RuntimeError) as excinfo: + # Changement de discrétisation pour les arêtes Ar0011 + emp = Mgx3D.EdgeMeshingPropertyBeta(10,1.000005) + ctx.getTopoManager().setMeshingProperty (emp, ["Ar0011"]) + expected = "la valeur de beta doit être comprise entre 1 et 1.01" + assert expected in str(excinfo.value) + + emp = Mgx3D.EdgeMeshingPropertyBeta(10,1.01) + ctx.getTopoManager().setMeshingProperty (emp, ["Ar0011"]) + + # Création du maillage pour tous les blocs + ctx.getMeshManager().newAllBlocksMesh() \ No newline at end of file