.. image:: ../images/distributionwithtabledensity.png
:align: center
+**Beta Law Distribution** - is given by the following formula (see image below) where **t** is the position of the point in the segment [0, 1].
+
+.. image:: ../images/nbsegment_beta_law_formula.png
+ :align: center
+
+The beta parameter is usually set between 1.01 (narrow mesh) and 1.00001 (very narrow mesh).
+Values between [-1, 1] are forbidden to ensure validity of the log.
+Negative values are allowed and result with positions distributed in the opposite direction.
+
+.. image:: ../images/nbsegments_beta_law_dlg.png
+ :align: center
+
+Below is an example of **Beta Law Distribution** for a face that was done using default **Expansion coefficient** value 1.01.
+
+.. image:: ../images/nbsegments_beta_law_example.png
+ :align: center
+
**See Also** a sample TUI Script of :ref:`Defining Number of Segments <tui_deflection_1d>` hypothesis operation.
double GetScaleFactor()
raises (SALOME::SALOME_Exception);
+ /*!
+ * Sets <beta> coefficient for Beta Law distribution
+ */
+ void SetBeta(in double beta)
+ raises (SALOME::SALOME_Exception);
+
+ /*!
+ * Returns <beta> coefficient for Beta Law distribution
+ */
+ double GetBeta()
+ raises (SALOME::SALOME_Exception);
+
/*!
* Sets <table function> parameter value for distribution DT_TabFunc
*/
SMESHGUI_CreatePatternDlg.h
SMESHGUI_NodesDlg.h
SMESHGUI_SpinBox.h
+ SMESHGUI_SpinBoxForbiddendRange.h
SMESHGUI_TransparencyDlg.h
SMESHGUI_ClippingDlg.h
SMESHGUI_GroupDlg.h
SMESHGUI_CreatePatternDlg.cxx
SMESHGUI_NodesDlg.cxx
SMESHGUI_SpinBox.cxx
+ SMESHGUI_SpinBoxForbiddendRange.cxx
SMESHGUI_TransparencyDlg.cxx
SMESHGUI_ClippingDlg.cxx
SMESHGUI_GroupDlg.cxx
--- /dev/null
+// Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// SMESH SMESHGUI : GUI for SMESH component
+// File : SMESHGUI_SpinBoxForbiddendRange.cxx
+// Author : Konstantin Leontev, Open CASCADE S.A.S.
+// SMESH includes
+//
+#include "SMESHGUI_SpinBoxForbiddendRange.h"
+
+#include <QToolTip>
+
+#include "utilities.h"
+
+
+//=================================================================================
+// class : SMESHGUI_SpinBoxForbiddendRange()
+// purpose : constructor
+//=================================================================================
+SMESHGUI_SpinBoxForbiddendRange::SMESHGUI_SpinBoxForbiddendRange(QWidget* parent)
+ : SMESHGUI_SpinBox(parent), forbiddenMin(0.0), forbiddenMax(1.0)
+{
+ // This property allows to return QValidator::Invalid from QtxDoubleSpinBox::validate()
+ // for any values outside of the min/max range.
+ // Otherwise a user could type any intermediate value.
+ setProperty("strict_validity_check", true);
+}
+
+//=================================================================================
+// function : ~SMESHGUI_SpinBoxForbiddendRange()
+// purpose : destructor
+//=================================================================================
+SMESHGUI_SpinBoxForbiddendRange::~SMESHGUI_SpinBoxForbiddendRange()
+{
+}
+
+//=================================================================================
+// function : stepBy()
+// purpose : Validates value in ranges on each step
+//=================================================================================
+void SMESHGUI_SpinBoxForbiddendRange::stepBy(const int steps)
+{
+ double const newValue = value() + (steps * singleStep());
+ double const validatedValue = GetValueInRange(newValue);
+
+ setValue(validatedValue);
+}
+
+//=================================================================================
+// function : valueFromText()
+// purpose : Validates value entered by user
+//=================================================================================
+double SMESHGUI_SpinBoxForbiddendRange::valueFromText(QString const& text) const
+{
+ double const newValue = SMESHGUI_SpinBox::valueFromText(text);
+ return GetValueInRange(newValue);
+}
+
+QValidator::State SMESHGUI_SpinBoxForbiddendRange::validate(QString& text, int& pos) const
+{
+ // Do parent's min/max and all other validation first
+ const QValidator::State res = SMESHGUI_SpinBox::validate(text, pos);
+ if (res != QValidator::Acceptable)
+ return res;
+
+ // Now we know that we have a valid numeric value in the text
+ // that we can check against forbidden range.
+ bool ok = false;
+ const double inputValue = text.toDouble(&ok);
+
+ // Return intermediate to allow a user input any value.
+ // If press ok button, it will be checked again with checkRange() call.
+ const QValidator::State state = ok && IsValueInRange(inputValue) ?
+ QValidator::Acceptable : QValidator::Intermediate;
+
+ showValidationToolTip(state);
+
+ return state;
+}
+
+//=================================================================================
+// function : SetForbiddenRange()
+// purpose : Sets min and max values for forbidden range
+//=================================================================================
+void SMESHGUI_SpinBoxForbiddendRange::SetForbiddenRange(const double min, const double max)
+{
+ forbiddenMin = min;
+ forbiddenMax = max;
+}
+
+//=================================================================================
+// function : checkRange()
+// purpose : adds checking against forbidden range to the parent's inmplementation
+//=================================================================================
+bool SMESHGUI_SpinBoxForbiddendRange::checkRange(const double value) const
+{
+ return SalomeApp_DoubleSpinBox::checkRange(value) && IsValueInRange(value);
+}
+
+//=================================================================================
+// function : IsValueInRange()
+// purpose : Validates a given value against forbidden range
+//=================================================================================
+bool SMESHGUI_SpinBoxForbiddendRange::IsValueInRange(const double inputValue) const
+{
+ // A given value must be outside of [forbiddenMin, forbiddenMax] scope
+ return inputValue < forbiddenMin || inputValue > forbiddenMax;
+}
+
+//=================================================================================
+// function : GetValueInRange()
+// purpose : Validates value considering forbidden range
+//=================================================================================
+double SMESHGUI_SpinBoxForbiddendRange::GetValueInRange(const double inputValue) const
+{
+ // Check if a given value is outside of [forbiddenMin, forbiddenMax] scope
+ if (IsValueInRange(inputValue))
+ return inputValue;
+
+ const double curValue = value();
+ const double step = SMESHGUI_SpinBox::singleStep();
+
+ // Find the nearest value outside of forbidden range
+ if (inputValue > curValue)
+ return forbiddenMax + step;
+ else
+ return forbiddenMin - step;
+}
+
+//=================================================================================
+// function : showValidationToolTip()
+// purpose : Shows tooltip with a valid range
+//=================================================================================
+void SMESHGUI_SpinBoxForbiddendRange::showValidationToolTip(const QValidator::State state) const
+{
+ if (state == QValidator::Acceptable)
+ {
+ QToolTip::hideText();
+ return;
+ }
+
+ // All the rest is an edited copy from SalomeApp_DoubleSpinBox::validate()
+
+ // Get position and min/max values
+ const QPoint pos(size().width(), 0.);
+ const QPoint globalPos = mapToGlobal(pos);
+ const QString minVal = textFromValue(minimum());
+ const QString maxVal = textFromValue(maximum());
+
+ // Same stuff as in QtxDoubleSpinBox::textFromValue()
+ int digits = getPrecision();
+
+ // For 'g' format, max. number of digits after the decimal point is getPrecision() - 1
+ // See also QtxDoubleSpinBox::validate()
+ if (digits < 0)
+ digits = qAbs(digits) - 1;
+
+ QString msg = QString(tr("VALID_RANGE_NOVAR_MSG")).
+ arg(minVal).
+ arg(forbiddenMin).
+ arg(forbiddenMax).
+ arg(maxVal).
+ arg(digits);
+
+ // It is not possible to hide and shortly afterwards reshow a tooltip
+ // with the same text because of some interference between the internal hideTimer of the tooltip and
+ // the QToolTip::showText(). As a result, the tooltip does not persist - it disappears immediately.
+ // If we are here, then QToolTip::hideText() was just called from the parent.
+ // So, below is a workaround that changes the text and lets the tooltip stay in place.
+ toolTipFlag = !toolTipFlag;
+ if (toolTipFlag)
+ {
+ msg.append(" ");
+ }
+
+ // Show tooltip
+ QToolTip::showText(globalPos, msg, const_cast<SMESHGUI_SpinBoxForbiddendRange*>(this));
+}
--- /dev/null
+// Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// SMESH SMESHGUI : GUI for SMESH component
+// File : SMESHGUI_SpinBoxForbiddendRange.h
+// Author : Konstantin Leontev, Open CASCADE S.A.S.
+//
+#ifndef SMESHGUI_SPINBOXFORBIDDENRANGE_H
+#define SMESHGUI_SPINBOXFORBIDDENRANGE_H
+
+// SMESH includes
+#include "SMESHGUI_SpinBox.h"
+
+
+//=================================================================================
+// class : SMESHGUI_SpinBoxForbiddendRange
+// purpose : Allows validating with a range of forbidden values
+//=================================================================================
+class SMESHGUI_EXPORT SMESHGUI_SpinBoxForbiddendRange : public SMESHGUI_SpinBox
+{
+ Q_OBJECT
+
+public:
+ SMESHGUI_SpinBoxForbiddendRange(QWidget*);
+ ~SMESHGUI_SpinBoxForbiddendRange();
+
+ virtual void stepBy(const int steps) override;
+ virtual double valueFromText(QString const& text) const override;
+ virtual QValidator::State validate(QString& text, int& pos) const override;
+
+ void SetForbiddenRange(const double min, const double max);
+
+protected:
+ virtual bool checkRange(const double value) const override;
+ bool IsValueInRange(const double value) const;
+ double GetValueInRange(const double value) const;
+
+ virtual void showValidationToolTip(const QValidator::State state) const override;
+private:
+ double forbiddenMin;
+ double forbiddenMax;
+
+ mutable bool toolTipFlag = false;
+};
+
+#endif // SMESHGUI_SPINBOXFORBIDDENRANGE_H
+
<translation>Mean Size</translation>
</message>
</context>
+<context>
+ <name>SMESHGUI_SpinBoxForbiddendRange</name>
+ <message>
+ <source>VALID_RANGE_NOVAR_MSG</source>
+ <translation>Specify a floating-point value in range [%1; %2) U (%3; %4]
+with %5-digit precision</translation>
+ </message>
+</context>
</TS>
<translation>Taille moyenne</translation>
</message>
</context>
+<context>
+ <name>SMESHGUI_SpinBoxForbiddendRange</name>
+ <message>
+ <source>VALID_RANGE_NOVAR_MSG</source>
+ <translation>Spécifier une valeur à virgule flottante dans la plage [%1; %2) U (%3; %4]
+avec une précision de %5 chiffres</translation>
+ </message>
+</context>
</TS>
<translation>オプション値</translation>
</message>
</context>
+<context>
+ <name>SMESHGUI_SpinBoxForbiddendRange</name>
+ <message>
+ <source>VALID_RANGE_NOVAR_MSG</source>
+ <translation>範囲内の浮動小数点値を指定します [%1; %2) U (%3; %4]
+%5 桁の精度</translation>
+ </message>
+</context>
</TS>
hyp.SetUsePreestimatedLength( length == 0.0 )
return hyp
- def NumberOfSegments(self, n, s=[], reversedEdges=[], UseExisting=0):
+ def NumberOfSegments(self, n, s=[], reversedEdges=[], UseExisting=0, beta=None):
"""
Defines "NumberOfSegments" hypothesis to cut an edge in a fixed number of segments
A list item can also be a tuple (edge, 1st_vertex_of_edge)
UseExisting: if ==true - searches for an existing hypothesis created with
the same parameters, else (default) - create a new one
+ beta: beta coefficient for Beta Law distribution
Returns:
an instance of StdMeshers_NumberOfSegments hypothesis
reversedEdges, UseExisting = [], reversedEdges
entry = self.MainShapeEntry()
reversedEdgeInd = self.ReversedEdgeIndices(reversedEdges)
- if not s:
- hyp = self.Hypothesis("NumberOfSegments", [n, reversedEdgeInd, entry],
- UseExisting=UseExisting,
- CompareMethod=self._compareNumberOfSegments)
- else:
- hyp = self.Hypothesis("NumberOfSegments", [n,s, reversedEdgeInd, entry],
- UseExisting=UseExisting,
- CompareMethod=self._compareNumberOfSegments)
+
+ args = [n, reversedEdgeInd, entry]
+ if s:
+ args.insert(1, s)
+ elif beta:
+ args.append(beta)
+
+ hyp = self.Hypothesis(
+ "NumberOfSegments", args,
+ UseExisting=UseExisting, CompareMethod=self._compareNumberOfSegments)
+
+ if s:
hyp.SetScaleFactor(s)
+ elif beta:
+ hyp.SetBeta(s)
+
hyp.SetNumberOfSegments(n)
hyp.SetReversedEdges( reversedEdgeInd )
hyp.SetObjectEntry( entry )
void StdMeshers_NumberOfSegments::SetDistrType(DistrType typ)
{
- if (typ < DT_Regular || typ > DT_ExprFunc)
+ if (!IsValidDistrType(typ))
throw SALOME_Exception(LOCALIZED("distribution type is out of range"));
if (typ != _distrType)
*/
//================================================================================
+bool StdMeshers_NumberOfSegments::IsValidDistrType(int distrType) const
+{
+ // DistrType is sequential, so we can just check against its first and last values
+ return distrType >= DT_Regular && distrType <= DT_BetaLaw;
+}
+
+//================================================================================
+/*!
+ *
+ */
+//================================================================================
+
void StdMeshers_NumberOfSegments::SetScaleFactor(double scaleFactor)
{
if (scaleFactor < PRECISION)
return _scaleFactor;
}
+//================================================================================
+/*!
+ *
+ */
+//================================================================================
+
+void StdMeshers_NumberOfSegments::SetBeta(double beta)
+{
+ if (_distrType != DT_BetaLaw)
+ throw SALOME_Exception(LOCALIZED("not a Beta Law distribution"));
+
+ const double diff = fabs(fabs(_beta) - fabs(beta));
+ if (diff <= PRECISION)
+ {
+ // Check for a special case where we have values with
+ // equal base but opposite signs like -1.01 and 1.01
+ if (std::signbit(_beta) == std::signbit(beta))
+ return;
+ }
+
+ _beta = beta;
+ NotifySubMeshesHypothesisModification();
+}
+
+//================================================================================
+/*!
+ *
+ */
+//================================================================================
+
+double StdMeshers_NumberOfSegments::GetBeta() const
+{
+ if (_distrType != DT_BetaLaw)
+ throw SALOME_Exception(LOCALIZED("not a Beta Law distribution"));
+ return _beta;
+}
+
//================================================================================
/*!
*
case DT_ExprFunc:
save << " " << _func;
break;
+ case DT_BetaLaw:
+ save << " " << _beta;
+ break;
case DT_Regular:
default:
break;
// supposing that this hypothesis was written in the new format
if (isOK)
{
- if (a < DT_Regular || a > DT_ExprFunc)
+ if (!IsValidDistrType(a))
_distrType = DT_Regular;
else
_distrType = (DistrType) a;
}
}
break;
+
+ case DT_BetaLaw:
+ {
+ isOK = static_cast<bool>(load >> b);
+ if (isOK)
+ _beta = b;
+ else
+ {
+ load.clear(ios::badbit | load.rdstate());
+ // this can mean, that the hypothesis is stored in old format
+ _distrType = DT_Regular;
+ _scaleFactor = scale_factor;
+ }
+ }
+ break;
+
case DT_Regular:
default:
break;
DT_Regular, //!< equidistant distribution
DT_Scale, //!< scale distribution
DT_TabFunc, //!< distribution with density function presented by table
- DT_ExprFunc //!< distribution with density function presented by expression
+ DT_ExprFunc, //!< distribution with density function presented by expression
+ DT_BetaLaw //!< distribution with Beta Law using parameter beta (expansion coefficient)
};
/*!
*/
DistrType GetDistrType() const;
+ /*!
+ * \brief Check if a given int falls into distribution type scope
+ */
+ bool IsValidDistrType(int distrType) const;
+
/*!
* \brief Set scale factor for scale distribution
* \param scaleFactor - positive value different from 1
*/
double GetScaleFactor() const;
+ /*!
+ * \brief Set beta coefficient for Beta Law distribution
+ * \param beta - usually set between 1.01 (narrow mesh) and 1.00001 (very narrow mesh)
+ *
+ * Throws SALOME_Exception if distribution type is not DT_BetaLaw
+ */
+ virtual void SetBeta(double scaleFactor);
+
+ /*!
+ * \brief Get beta coefficient for Beta Law distribution
+ *
+ * Throws SALOME_Exception if distribution type is not DT_BetaLaw
+ */
+ double GetBeta() const;
+
/*!
* \brief Set table function for distribution DT_TabFunc
* \param table - this vector contains the pairs (parameter, value)
smIdType _numberOfSegments; //!< an edge will be split on to this number of segments
DistrType _distrType; //!< the type of distribution of density function
double _scaleFactor; //!< the scale parameter for DT_Scale
+ double _beta; //!< beta coefficient for DT_BetaLaw
std::vector<double> _table, _distr; //!< the table for DT_TabFunc, a sequence of pairs of numbers
std::string _func; //!< the expression of the function for DT_ExprFunc
int _convMode; //!< flag of conversion mode: 0=exponent, 1=cut negative
_svalue[ EXPR_FUNC_IND ] = hyp->GetExpressionFunction();
_revEdgesIDs = hyp->GetReversedEdges();
break;
+ case StdMeshers_NumberOfSegments::DT_BetaLaw:
+ _value[BETA_IND] = hyp->GetBeta();
+ _revEdgesIDs = hyp->GetReversedEdges();
+ break;
case StdMeshers_NumberOfSegments::DT_Regular:
break;
default:
}
}
+bool StdMeshers_Regular_1D::computeBetaLaw(
+ Adaptor3d_Curve& theC3d,
+ std::list<double>& theParams,
+ double f,
+ double theLength,
+ double beta,
+ int nbSegments,
+ bool theReverse
+ )
+{
+ // Implemented with formula, where h is the position of a point on the segment [0,1]:
+ // ratio=(1+beta)/(beta -1)
+ // zlog=log(ratio)
+ // puiss=exp(zlog*(1-h))
+ // rapp=(1-puiss)/(1+puiss)
+ // f(h) =1+beta*rapp
+ //
+ // Look at https://gitlab.onelab.info/gmsh/gmsh/-/commit/d581b381f2b8639fba40f2e771e2573d1a0f8424
+ // Especially gmsh/src/mesh/meshGEdge.cpp, 507: createPoints()
+
+ if (theReverse)
+ {
+ beta *= -1;
+ }
+
+ MESSAGE("Compute BetaLaw. beta: " << beta);
+
+ // Prepare a temp storage for position values
+ const int nbNewPoints = nbSegments - 1;
+ std::vector<double> t(nbNewPoints);
+
+ // Calculate position values with beta for each point
+ const double zlog = log((1. + beta) / (beta - 1.));
+ for(smIdType i = 0; i < nbNewPoints; i++)
+ {
+ const double eta = (double)(i + 1) / nbSegments;
+ const double power = exp(zlog * (1. - eta));
+ const double ratio = (1. - power) / (1. + power);
+ const double pos = 1.0 + beta * ratio;
+
+ // Check if we need to reverse distribution
+ if (beta > 0)
+ {
+ t[i] = pos;
+ }
+ else
+ {
+ t[nbNewPoints - i - 1] = 1.0 - pos;
+ }
+
+ // Commented to prevent bloated output with a casual debug
+ // MESSAGE("Calculated position " << i << ": " << pos);
+ }
+
+ // Make points for each calculated value
+ for(const auto i : t)
+ {
+ const double abscissa = i * theLength;
+ MESSAGE("abscissa: " << abscissa);
+
+ GCPnts_AbscissaPoint Discret(Precision::Confusion(), theC3d, abscissa, f);
+ if (Discret.IsDone())
+ theParams.push_back(Discret.Parameter());
+ }
+
+ return true;
+}
+
//=============================================================================
/*!
*
theParams);
}
break;
+
+ case StdMeshers_NumberOfSegments::DT_BetaLaw:
+ return computeBetaLaw(theC3d, theParams, f, theLength, _value[BETA_IND], nbSegments, theReverse);
+
case StdMeshers_NumberOfSegments::DT_Regular:
eltSize = theLength / double( nbSegments );
break;
double theLastU,
std::list<double> & theParameters );
+ bool computeBetaLaw(Adaptor3d_Curve& theC3d,
+ std::list<double>& theParams,
+ double f,
+ double theLength,
+ double beta,
+ int nbSegments,
+ bool theReverse);
+
/*!
* \brief Return StdMeshers_SegmentLengthAroundVertex assigned to vertex
*/
enum ValueIndex {
SCALE_FACTOR_IND = 0,
+ BETA_IND = 0,
BEG_LENGTH_IND = 0,
END_LENGTH_IND = 1,
DEFLECTION_IND = 0,
#include <SMESHGUI_Utils.h>
#include <SMESHGUI_HypothesesUtils.h>
#include <SMESHGUI_SpinBox.h>
+#include <SMESHGUI_SpinBoxForbiddendRange.h>
// IDL includes
#include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
myNbSeg( 0 ),
myDistr( 0 ),
myScale( 0 ),
+ myBeta( 0 ),
myTable( 0 ),
#ifndef DISABLE_PLOT2DVIEWER
myPreview( 0 ),
myConvBox( 0 ),
myConv( 0 ),
myLScale( 0 ),
+ myLBeta( 0 ),
myLTable( 0 ),
myLExpr( 0 ),
myInfo( 0 ),
bool res = storeParamsToHypo( data_new );
res = myNbSeg->isValid( msg, true ) && res;
res = myScale->isValid( msg, true ) && res;
+ res = myBeta->isValid( msg, true ) && res;
if ( !res )
storeParamsToHypo( data_old );
return res;
types.append( tr( "SMESH_DISTR_SCALE" ) );
types.append( tr( "SMESH_DISTR_TAB" ) );
types.append( tr( "SMESH_DISTR_EXPR" ) );
+ types.append( tr( "SMESH_DISTR_BETALAW" ) );
myDistr->addItems( types );
myGroupLayout->addWidget( myDistr, row, 1 );
row++;
lay->setStretchFactor( myReversedEdgesHelper, 1 );
}
+ // 7) Beta Law distribution
+ myGroupLayout->addWidget(myLBeta = new QLabel(tr("SMESH_NB_SEGMENTS_BETA_PARAM"), GroupC1), row, 0);
+ myBeta = new SMESHGUI_SpinBoxForbiddendRange(GroupC1);
+ myBeta->RangeStepAndValidator(-1E+5, 1E+5, 0.00001, "parametric_precision");
+ myBeta->SetForbiddenRange(-1.0, 1.0);
+ myGroupLayout->addWidget(myBeta, row, 1);
+ row++;
+
connect( myNbSeg, SIGNAL( valueChanged( const QString& ) ), this, SLOT( onValueChanged() ) );
connect( myDistr, SIGNAL( activated( int ) ), this, SLOT( onValueChanged() ) );
connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SLOT( onValueChanged() ) );
myTable->setData( data.myTable );
myExpr->setText( data.myExpr );
+ myBeta->setValue(data.myBeta);
+
if ( dlg() )
dlg()->setMinimumSize( dlg()->minimumSizeHint().width(), dlg()->minimumSizeHint().height() );
}
Regular, //!< equidistant distribution
Scale, //!< scale distribution
TabFunc, //!< distribution with density function presented by table
- ExprFunc //!< distribution with density function presented by expression
+ ExprFunc, //!< distribution with density function presented by expression
+ BetaLaw //!< distribution with density function presented by expression
};
bool hasConv = false;
switch ( data.myDistrType ) {
valStr += data.myExpr;
hasConv = true;
break;
+
+ case BetaLaw:
+ valStr += tr("SMESH_NB_SEGMENTS_BETA_PARAM") + " = " + QString::number(data.myBeta);
+ break;
}
if ( hasConv )
{
h_data.myExpr = distr==3 ? h->GetExpressionFunction() : "1";
h_data.myConv = distr==2 || distr==3 ? h->ConversionMode() : 1; /*cut negative by default*/
+ h_data.myBeta = distr==4 ? h->GetBeta() : 1.01;
return true;
}
if( distr==2 || distr==3 )
h->SetConversionMode( h_data.myConv );
- if( distr==1 || distr==2 || distr==3 ) {
+ if( distr==1 || distr==2 || distr==3 || distr == 4) {
h->SetReversedEdges( myDirectionWidget->GetListOfIDs() );
h->SetObjectEntry( myDirectionWidget->GetMainShapeEntry() );
}
//setting of function must follow after setConversionMode, because otherwise
//the function will be checked with old conversion mode, so that it may occurs
//unexpected errors for user
+
+ if(distr == 4)
+ {
+ h->SetDistrType(distr);
+ h->SetBeta(h_data.myBeta);
+ }
}
catch(const SALOME::SALOME_Exception& ex)
{
h_data.myDistrType = myDistr->currentIndex();
h_data.myConv = myConv->checkedId();
h_data.myScale = myScale->value();
+ h_data.myBeta = myBeta->value();
myTable->data( h_data.myTable );
h_data.myExpr = myExpr->text();
return true;
myPreview->setConversion( StdMeshersGUI_DistrPreview::Conversion( myConv->checkedId() ) );
#endif
+ // Beta Law UI elements
+ const bool isBetaLaw = distr == 4;
+ myBeta->setVisible(isBetaLaw);
+ myLBeta->setVisible(isBetaLaw);
+
if ( (QtxComboBox*)sender() == myDistr && dlg() ) {
QApplication::instance()->processEvents();
myGroupLayout->invalidate();
class QRadioButton;
class StdMeshersGUI_SubShapeSelectorWdg;
class StdMeshersGUI_PropagationHelperWdg;
+class SMESHGUI_SpinBoxForbiddendRange;
typedef struct
{
int myNbSeg, myDistrType, myConv;
double myScale;
+ double myBeta;
SMESH::double_array myTable;
QString myName, myExpr;
QString myNbSegVarName, myScaleVarName;
-
} NbSegmentsHypothesisData;
class STDMESHERSGUI_EXPORT StdMeshersGUI_NbSegmentsCreator : public StdMeshersGUI_StdHypothesisCreator
SalomeApp_IntSpinBox* myNbSeg;
QtxComboBox* myDistr;
SMESHGUI_SpinBox* myScale;
+ SMESHGUI_SpinBoxForbiddendRange* myBeta;
StdMeshersGUI_DistrTableFrame* myTable;
#ifndef DISABLE_PLOT2DVIEWER
StdMeshersGUI_DistrPreview* myPreview;
QLineEdit *myName, *myExpr;
QGroupBox* myConvBox;
QButtonGroup* myConv;
- QLabel *myLScale, *myLTable, *myLExpr, *myInfo;
+ QLabel *myLScale, *myLTable, *myLExpr, *myInfo, *myLBeta;
QGridLayout* myGroupLayout;
int myTableRow, myPreviewRow;
//QRadioButton* myCutNeg;
<source>SMESH_DISTR_TAB</source>
<translation>Distribution with table density</translation>
</message>
+ <message>
+ <source>SMESH_DISTR_BETALAW</source>
+ <translation>Distribution with Beta Law</translation>
+ </message>
<message>
<source>SMESH_DISTR_TYPE</source>
<translation>Type of distribution</translation>
<source>SMESH_NB_SEGMENTS_SCALE_PARAM</source>
<translation>Scale Factor</translation>
</message>
+ <message>
+ <source>SMESH_NB_SEGMENTS_BETA_PARAM</source>
+ <translation>Expansion coefficient</translation>
+ </message>
<message>
<source>SMESH_NB_SEGMENTS_TITLE</source>
<translation>Hypothesis Construction</translation>
<source>SMESH_DISTR_TAB</source>
<translation>Distribution avec une table de densités</translation>
</message>
+ <message>
+ <source>SMESH_DISTR_BETALAW</source>
+ <translation>Distribution avec la Loi Bêta</translation>
+ </message>
<message>
<source>SMESH_DISTR_TYPE</source>
<translation>Type de distribution</translation>
<source>SMESH_NB_SEGMENTS_PARAM</source>
<translation>Nombre de segments</translation>
</message>
+ <message>
+ <source>SMESH_NB_SEGMENTS_BETA_PARAM</source>
+ <translation>Coefficient de dilatation</translation>
+ </message>
<message>
<source>SMESH_NB_SEGMENTS_SCALE_PARAM</source>
<translation>Facteur d'échelle</translation>
<source>SMESH_DISTR_TAB</source>
<translation>密度のテーブル</translation>
</message>
+ <message>
+ <source>SMESH_DISTR_BETALAW</source>
+ <translation>ベータ法による分布</translation>
+ </message>
<message>
<source>SMESH_DISTR_TYPE</source>
<translation>分布の種類</translation>
<source>SMESH_NB_SEGMENTS_PARAM</source>
<translation>セグメントの数</translation>
</message>
+ <message>
+ <source>SMESH_NB_SEGMENTS_BETA_PARAM</source>
+ <translation>膨張係数</translation>
+ </message>
<message>
<source>SMESH_NB_SEGMENTS_SCALE_PARAM</source>
<translation>スケール ファクター</translation>
return scale;
}
+//=============================================================================
+/*!
+ * StdMeshers_NumberOfSegments_i::SetBeta
+ *
+ * Set beta coefficient for Beta Law distribution
+ */
+//=============================================================================
+
+void StdMeshers_NumberOfSegments_i::SetBeta(CORBA::Double beta)
+{
+ ASSERT(myBaseImpl);
+ try {
+ this->GetImpl()->SetBeta(beta);
+ // Update Python script
+ SMESH::TPythonDump() << _this() << ".SetBeta( " << SMESH::TVar(beta) << " )";
+ }
+ catch (SALOME_Exception& S_ex) {
+ THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
+ }
+}
+
+//=============================================================================
+/*!
+ * StdMeshers_NumberOfSegments_i::GetBeta
+ *
+ * Get beta coefficient for Beta Law distribution
+ */
+//=============================================================================
+
+CORBA::Double StdMeshers_NumberOfSegments_i::GetBeta()
+{
+ ASSERT(myBaseImpl);
+
+ double beta = 1.0;
+ try {
+ beta = this->GetImpl()->GetBeta();
+ }
+ catch (SALOME_Exception& S_ex) {
+ THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
+ }
+
+ return beta;
+}
+
//=============================================================================
/*!
*/
// Get scalar factor
CORBA::Double GetScaleFactor();
+ // Set beta coefficient for Beta Law distribution
+ void SetBeta(CORBA::Double beta);
+ // Get beta coefficient for Beta Law distribution
+ CORBA::Double GetBeta();
+
// Set table function for distribution DT_TabFunc
void SetTableFunction(const SMESH::double_array& table);
// Get table function for distribution DT_TabFunc
--- /dev/null
+#!/usr/bin/env python
+
+import salome
+
+salome.salome_init()
+
+###
+### GEOM component
+###
+
+from salome.geom import geomBuilder
+
+geompy = geomBuilder.New()
+
+p1 = geompy.MakeVertex(0, 0, 0, theName="p1")
+p2 = geompy.MakeVertex(.1, 0, 0, theName="p2")
+p3 = geompy.MakeVertex(.1, .3, 0, theName="p3")
+p4 = geompy.MakeVertex(0, .3, 0, theName="p4")
+
+p5 = geompy.MakeVertex(-0.05, 0.1, 0, theName="p5")
+p6 = geompy.MakeVertex(-0.05, 0.05, 0, theName="p6")
+
+points = [p1, p2, p3, p4, p5, p6, p1]
+
+polyline = geompy.MakePolyline(points, theName="polyline")
+
+face = geompy.MakeFace(polyline, 1, theName="face")
+
+edges_by_name = {}
+for i in range(len(points)-1):
+ name = "edge_%i"%(i+1)
+ edge = geompy.GetEdge(face, points[i], points[i+1], theName=name)
+ edges_by_name[name] = edge
+
+###
+### SMESH component
+###
+
+import SMESH
+from salome.smesh import smeshBuilder
+
+smesh = smeshBuilder.New()
+
+Mesh_1 = smesh.Mesh(face,'Mesh_1')
+
+main_algo1D = Mesh_1.Segment()
+main_algo1D.NumberOfSegments(5)
+
+sub_algo1D = Mesh_1.Segment(edges_by_name["edge_1"])
+nb_seg_hyp = sub_algo1D.NumberOfSegments(29)
+nb_seg_hyp.SetDistrType( 4 )
+nb_seg_hyp.SetBeta( 1.001 )
+
+
+sub_algo1D = Mesh_1.Segment(edges_by_name["edge_2"])
+nb_seg_hyp = sub_algo1D.NumberOfSegments(19)
+
+sub_algo1D = Mesh_1.Segment(edges_by_name["edge_3"])
+nb_seg_hyp = sub_algo1D.NumberOfSegments(29)
+nb_seg_hyp.SetDistrType( 4 )
+nb_seg_hyp.SetBeta( -1.001 )
+
+sub_algo1D = Mesh_1.Segment(edges_by_name["edge_4"])
+nb_seg_hyp = sub_algo1D.NumberOfSegments(9)
+
+Quadrangle_2D = Mesh_1.Quadrangle()
+
+isDone = Mesh_1.Compute()
+Mesh_1.CheckCompute()
+
+gr_edges_by_name = {}
+for name, edge in edges_by_name.items():
+ gr_edge = Mesh_1.Group(edge)
+ gr_edges_by_name[name] = gr_edge
+
+assert Mesh_1.NbEdges() == 5+5+29*2+19+9
+assert Mesh_1.NbQuadrangles() == 551
+
+expected_mini = 2.9948449467664952e-05
+expected_maxi = 0.013044372341778604
+mini_1, maxi_1 = Mesh_1.GetMinMax(SMESH.FT_Length, meshPart=gr_edges_by_name["edge_1"])
+mini_3, maxi_3 = Mesh_1.GetMinMax(SMESH.FT_Length, meshPart=gr_edges_by_name["edge_3"])
+
+assert abs(expected_mini-mini_1)/mini_1 < 1e-12
+assert abs(expected_mini-mini_3)/mini_3 < 1e-12
+
+assert abs(expected_maxi-maxi_1)/maxi_1 < 1e-12
+assert abs(expected_maxi-maxi_3)/maxi_3 < 1e-12
+
+
+if salome.sg.hasDesktop():
+ salome.sg.updateObjBrowser()
# ---- Creating meshes
box = salome.IDToObject(idbox)
-names = [ "MeshBoxReg", "MeshBoxScale", "MeshBoxTable", "MeshBoxExpr" ]
+names = [ "MeshBoxReg", "MeshBoxScale", "MeshBoxTable", "MeshBoxExpr", "MeshBoxBeta" ]
print("-------------------------- Create ", names[0], " mesh")
algo = mesh.Triangle()
algo.MaxElementArea(2500)
+mesh.Compute()
+mesh.CheckCompute()
+
print("-------------------------- Create ", names[1], " mesh")
mesh = smesh.Mesh(box, names[1])
algo = mesh.Segment()
algo = mesh.Triangle()
algo.MaxElementArea(2500)
+mesh.Compute()
+mesh.CheckCompute()
+
print("-------------------------- Create ", names[2], " mesh")
mesh = smesh.Mesh(box,names[2])
algo = mesh.Segment()
algo = mesh.Triangle()
algo.MaxElementArea(2500)
+mesh.Compute()
+mesh.CheckCompute()
+
print("-------------------------- Create ", names[3], " mesh")
mesh = smesh.Mesh(box, names[3])
algo = mesh.Segment()
algo = mesh.Triangle()
algo.MaxElementArea(2500)
+mesh.Compute()
+mesh.CheckCompute()
-salome.sg.updateObjBrowser()
+print("-------------------------- Create ", names[4], " mesh")
+mesh = smesh.Mesh(box, names[4])
+algo = mesh.Segment()
+hyp = algo.NumberOfSegments(7)
+hyp.SetDistrType(4)
+hyp.SetBeta(1.01)
+smesh.SetName(hyp, "NumberOfSegmentsBeta")
+quad_2d = mesh.Quadrangle()
+quad_2d.SetName("Quadrangle_2D")
+
+hexa_3d = mesh.Hexahedron()
+hexa_3d.SetName("Hexa_3D")
+
+mesh.Compute()
+mesh.CheckCompute()
+
+
+salome.sg.updateObjBrowser()
PAL_MESH_041_mesh.py
PAL_MESH_043_3D.py
SMESH_BelongToGeom.py
+ SMESH_beta_law.py
SMESH_box2_tetra.py
SMESH_box3_tetra.py
SMESH_box_tetra.py