refs 254#: 7.5.5. Mesh generation for semi-analytical boundaries

Add "Chordal Error" parameter to NETGEN
This commit is contained in:
eap 2017-09-25 20:48:41 +03:00
parent 3a149003e1
commit 1a836a25cc
13 changed files with 630 additions and 152 deletions

View File

@ -31,13 +31,19 @@ parameters below. You can select \a Custom to define them manually.
- <b>Growth rate</b> - allows to define how much the linear dimensions of - <b>Growth rate</b> - allows to define how much the linear dimensions of
two adjacent cells can differ (e.g. 0.3 means 30%). two adjacent cells can differ (e.g. 0.3 means 30%).
- <b>Nb. Segs per Edge</b> - allows to define the minimum number of - <b>Nb. Segs per Edge</b> - allows to define the minimum number of
mesh segments in which edges will be split. This parameter is used mesh segments in which edges will be split. Size of elements computed using
only if <b>Limit Size by Surface Curvature</b> is checked. this value is trimmed between <b>Min Size</b> and <b>Max Size</b>
bounds. This parameter is used only if <b>Limit Size by Surface
Curvature</b> is checked.
- <b>Nb Segs per Radius</b> - allows to define the size of - <b>Nb Segs per Radius</b> - allows to define the size of
mesh segments and mesh faces in which curved edges and surfaces will mesh segments and mesh faces in which curved edges and surfaces will
be split. This value divided by a radius of curvature gives an element be split. A radius of local curvature divided by this value gives an element
size at a given point. This parameter is used only if <b>Limit Size by size at a given point. Element size computed this way is then trimmed
Surface Curvature</b> is checked. between <b>Min Size</b> and <b>Max Size</b> bounds. This parameter is
used only if <b>Limit Size by Surface Curvature</b> is checked.
- <b>Chordal Error</b> - allows to define the maximum distance between
the generated 2D element and the surface. Size of elements computed using
this criterion is trimmed between <b>Min Size</b> and <b>Max Size</b> bounds.
- <b>Limit Size by Surface Curvature</b> - if this box is checked in, - <b>Limit Size by Surface Curvature</b> - if this box is checked in,
then size of mesh segments and mesh faces on curved edges and surfaces then size of mesh segments and mesh faces on curved edges and surfaces
is defined using value of <b>Nb Segs per Radius</b> parameter, and is defined using value of <b>Nb Segs per Radius</b> parameter, and
@ -87,6 +93,9 @@ section.<br>
"25 25 0 25 25 200 0.3" means that along the line between points (25, "25 25 0 25 25 200 0.3" means that along the line between points (25,
25, 0) and (25, 25, 200) size of elements should be 0.3. 25, 0) and (25, 25, 200) size of elements should be 0.3.
Sizes defined in the file are trimmed between <b>Min Size</b> and <b>Max Size</b>
bounds.
\image html netgen2d3d_simple.png \image html netgen2d3d_simple.png
<b>NETGEN 2D simple parameters</b> and <b>NETGEN 3D simple <b>NETGEN 2D simple parameters</b> and <b>NETGEN 3D simple

View File

@ -92,6 +92,11 @@ module NETGENPlugin
void SetNbSegPerEdge(in double value); void SetNbSegPerEdge(in double value);
double GetNbSegPerEdge(); double GetNbSegPerEdge();
void SetChordalErrorEnabled(in boolean value);
boolean GetChordalErrorEnabled();
void SetChordalError(in double value);
double GetChordalError();
void SetNbSegPerRadius(in double value); void SetNbSegPerRadius(in double value);
double GetNbSegPerRadius(); double GetNbSegPerRadius();

View File

@ -177,7 +177,7 @@ QFrame* NETGENPluginGUI_HypothesisCreator::buildFrame()
myFineness = new QComboBox( GroupC1 ); myFineness = new QComboBox( GroupC1 );
QStringList types; QStringList types;
types << tr( "NETGEN_VERYCOARSE" ) << tr( "NETGEN_COARSE" ) << tr( "NETGEN_MODERATE" ) << types << tr( "NETGEN_VERYCOARSE" ) << tr( "NETGEN_COARSE" ) << tr( "NETGEN_MODERATE" ) <<
tr( "NETGEN_FINE" ) << tr( "NETGEN_VERYFINE" ) << tr( "NETGEN_CUSTOM" ); tr( "NETGEN_FINE" ) << tr( "NETGEN_VERYFINE" ) << tr( "NETGEN_CUSTOM" );
myFineness->addItems( types ); myFineness->addItems( types );
aGroupLayout->addWidget( myFineness, row, 1 ); aGroupLayout->addWidget( myFineness, row, 1 );
connect( myFineness, SIGNAL( activated( int ) ), this, SLOT( onFinenessChanged() ) ); connect( myFineness, SIGNAL( activated( int ) ), this, SLOT( onFinenessChanged() ) );
@ -208,6 +208,19 @@ QFrame* NETGENPluginGUI_HypothesisCreator::buildFrame()
row++; row++;
} }
myChordalErrorEnabled = 0;
myChordalError = 0;
if ( myIs2D || !myIsONLY )
{
myChordalErrorEnabled = new QCheckBox( tr( "NETGEN_CHORDAL_ERROR" ), GroupC1 );
aGroupLayout->addWidget( myChordalErrorEnabled, row, 0 );
myChordalError = new SMESHGUI_SpinBox( GroupC1 );
myChordalError->RangeStepAndValidator( COORD_MIN, COORD_MAX, .1, "length_precision" );
aGroupLayout->addWidget( myChordalError, row, 1 );
connect( myChordalErrorEnabled, SIGNAL( stateChanged(int)), SLOT( onChordalErrorEnabled()));
row++;
}
mySurfaceCurvature = 0; mySurfaceCurvature = 0;
if ( myIs2D || !myIsONLY ) if ( myIs2D || !myIsONLY )
{ {
@ -337,6 +350,15 @@ void NETGENPluginGUI_HypothesisCreator::retrieveParams() const
else else
myNbSegPerRadius->setText( data.myNbSegPerRadiusVar ); myNbSegPerRadius->setText( data.myNbSegPerRadiusVar );
} }
if ( myChordalError )
{
myChordalErrorEnabled->setChecked( data.myChordalErrorEnabled && data.myChordalError > 0 );
if(data.myChordalErrorVar.isEmpty())
myChordalError->setValue( data.myChordalError > 0 ? data.myChordalError : 0.1 );
else
myChordalError->setText( data.myChordalErrorVar );
myChordalError->setEnabled( myChordalErrorEnabled->isChecked() );
}
if (myAllowQuadrangles) if (myAllowQuadrangles)
myAllowQuadrangles->setChecked( data.myAllowQuadrangles ); myAllowQuadrangles->setChecked( data.myAllowQuadrangles );
@ -408,26 +430,28 @@ bool NETGENPluginGUI_HypothesisCreator::readParamsFromHypo( NetgenHypothesisData
NETGENPlugin::NETGENPlugin_Hypothesis_var h = NETGENPlugin::NETGENPlugin_Hypothesis_var h =
NETGENPlugin::NETGENPlugin_Hypothesis::_narrow( initParamsHypothesis() ); NETGENPlugin::NETGENPlugin_Hypothesis::_narrow( initParamsHypothesis() );
//HypothesisData* data = SMESH::GetHypothesisData( hypType() );
h_data.myName = isCreation() ? hypName() : ""; h_data.myName = isCreation() ? hypName() : "";
h_data.myMaxSize = h->GetMaxSize(); h_data.myMaxSize = h->GetMaxSize();
h_data.myMaxSizeVar = getVariableName("SetMaxSize"); h_data.myMaxSizeVar = getVariableName("SetMaxSize");
h_data.mySecondOrder = h->GetSecondOrder(); h_data.mySecondOrder = h->GetSecondOrder();
h_data.myOptimize = h->GetOptimize(); h_data.myOptimize = h->GetOptimize();
h_data.myFineness = (int) h->GetFineness(); h_data.myFineness = (int) h->GetFineness();
h_data.myGrowthRate = h->GetGrowthRate(); h_data.myGrowthRate = h->GetGrowthRate();
h_data.myGrowthRateVar = getVariableName("SetGrowthRate"); h_data.myGrowthRateVar = getVariableName("SetGrowthRate");
h_data.myNbSegPerEdge = h->GetNbSegPerEdge(); h_data.myNbSegPerEdge = h->GetNbSegPerEdge();
h_data.myNbSegPerEdgeVar = getVariableName("SetNbSegPerEdge"); h_data.myNbSegPerEdgeVar = getVariableName("SetNbSegPerEdge");
h_data.myNbSegPerRadius = h->GetNbSegPerRadius(); h_data.myNbSegPerRadius = h->GetNbSegPerRadius();
h_data.myNbSegPerRadiusVar = getVariableName("SetNbSegPerRadius"); h_data.myNbSegPerRadiusVar = getVariableName("SetNbSegPerRadius");
h_data.myMinSize = h->GetMinSize(); h_data.myChordalError = h->GetChordalError();
h_data.myMinSizeVar = getVariableName("SetMinSize"); h_data.myChordalErrorVar = getVariableName("SetChordalError");
h_data.mySurfaceCurvature = h->GetUseSurfaceCurvature(); h_data.myChordalErrorEnabled = h->GetChordalErrorEnabled();
h_data.myFuseEdges = h->GetFuseEdges(); h_data.myMinSize = h->GetMinSize();
h_data.myMeshSizeFile = h->GetMeshSizeFile(); h_data.myMinSizeVar = getVariableName("SetMinSize");
h_data.mySurfaceCurvature = h->GetUseSurfaceCurvature();
h_data.myFuseEdges = h->GetFuseEdges();
h_data.myMeshSizeFile = h->GetMeshSizeFile();
//if ( myIs2D ) //if ( myIs2D )
{ {
@ -486,6 +510,9 @@ bool NETGENPluginGUI_HypothesisCreator::storeParamsToHypo( const NetgenHypothesi
h->SetVarParameter ( h_data.myNbSegPerRadiusVar.toLatin1().constData(), "SetNbSegPerRadius"); h->SetVarParameter ( h_data.myNbSegPerRadiusVar.toLatin1().constData(), "SetNbSegPerRadius");
h->SetNbSegPerRadius( h_data.myNbSegPerRadius ); h->SetNbSegPerRadius( h_data.myNbSegPerRadius );
} }
h->SetVarParameter ( h_data.myChordalErrorVar.toLatin1().constData(), "SetChordalError");
h->SetChordalError ( h_data.myChordalError );
h->SetChordalErrorEnabled( h_data.myChordalErrorEnabled );
h->SetVarParameter ( h_data.myMinSizeVar.toLatin1().constData(), "SetMinSize"); h->SetVarParameter ( h_data.myMinSizeVar.toLatin1().constData(), "SetMinSize");
h->SetMinSize ( h_data.myMinSize ); h->SetMinSize ( h_data.myMinSize );
h->SetUseSurfaceCurvature( h_data.mySurfaceCurvature ); h->SetUseSurfaceCurvature( h_data.mySurfaceCurvature );
@ -551,8 +578,13 @@ bool NETGENPluginGUI_HypothesisCreator::readParamsFromWidgets( NetgenHypothesisD
h_data.myNbSegPerEdgeVar = myNbSegPerEdge->text(); h_data.myNbSegPerEdgeVar = myNbSegPerEdge->text();
if ( myNbSegPerRadius ) if ( myNbSegPerRadius )
h_data.myNbSegPerRadiusVar = myNbSegPerRadius->text(); h_data.myNbSegPerRadiusVar = myNbSegPerRadius->text();
if ( myChordalError )
{
h_data.myChordalErrorVar = myChordalError->text();
h_data.myChordalError = myChordalError->value();
h_data.myChordalErrorEnabled = myChordalError->isEnabled();
}
if ( myAllowQuadrangles ) if ( myAllowQuadrangles )
h_data.myAllowQuadrangles = myAllowQuadrangles->isChecked(); h_data.myAllowQuadrangles = myAllowQuadrangles->isChecked();
@ -577,6 +609,11 @@ bool NETGENPluginGUI_HypothesisCreator::readParamsFromWidgets( NetgenHypothesisD
return true; return true;
} }
void NETGENPluginGUI_HypothesisCreator::onChordalErrorEnabled()
{
myChordalError->setEnabled( myChordalErrorEnabled->isChecked() );
}
void NETGENPluginGUI_HypothesisCreator::onSurfaceCurvatureChanged() void NETGENPluginGUI_HypothesisCreator::onSurfaceCurvatureChanged()
{ {
bool isSurfaceCurvature = (mySurfaceCurvature ? mySurfaceCurvature->isChecked() : true); bool isSurfaceCurvature = (mySurfaceCurvature ? mySurfaceCurvature->isChecked() : true);
@ -587,6 +624,11 @@ void NETGENPluginGUI_HypothesisCreator::onSurfaceCurvatureChanged()
myNbSegPerEdge->setEnabled(isCustom && isSurfaceCurvature); myNbSegPerEdge->setEnabled(isCustom && isSurfaceCurvature);
if ( myNbSegPerRadius ) if ( myNbSegPerRadius )
myNbSegPerRadius->setEnabled(isCustom && isSurfaceCurvature); myNbSegPerRadius->setEnabled(isCustom && isSurfaceCurvature);
// if ( myChordalError )
// {
// myChordalError->setEnabled( isSurfaceCurvature );
// myChordalErrorEnabled->setEnabled( isSurfaceCurvature );
// }
} }
void NETGENPluginGUI_HypothesisCreator::onFinenessChanged() void NETGENPluginGUI_HypothesisCreator::onFinenessChanged()

View File

@ -44,11 +44,11 @@ class QTableWidget;
typedef struct typedef struct
{ {
double myMaxSize, myMinSize, myGrowthRate, myNbSegPerEdge, myNbSegPerRadius; double myMaxSize, myMinSize, myGrowthRate, myNbSegPerEdge, myNbSegPerRadius, myChordalError;
int myFineness; int myFineness;
bool mySecondOrder, myAllowQuadrangles, myOptimize, mySurfaceCurvature, myFuseEdges; bool mySecondOrder, myAllowQuadrangles, myOptimize, mySurfaceCurvature, myFuseEdges, myChordalErrorEnabled;
QString myName, myMeshSizeFile; QString myName, myMeshSizeFile;
QString myMaxSizeVar, myMinSizeVar, myGrowthRateVar, myNbSegPerEdgeVar, myNbSegPerRadiusVar; QString myMaxSizeVar, myMinSizeVar, myGrowthRateVar, myNbSegPerEdgeVar, myNbSegPerRadiusVar, myChordalErrorVar;
} NetgenHypothesisData; } NetgenHypothesisData;
/*! /*!
@ -76,6 +76,7 @@ protected:
protected slots: protected slots:
virtual void onFinenessChanged(); virtual void onFinenessChanged();
virtual void onChordalErrorEnabled();
virtual void onSurfaceCurvatureChanged(); virtual void onSurfaceCurvatureChanged();
virtual void onAddLocalSizeOnVertex(); virtual void onAddLocalSizeOnVertex();
virtual void onAddLocalSizeOnEdge(); virtual void onAddLocalSizeOnEdge();
@ -102,12 +103,14 @@ private:
SMESHGUI_SpinBox* myGrowthRate; SMESHGUI_SpinBox* myGrowthRate;
SMESHGUI_SpinBox* myNbSegPerEdge; SMESHGUI_SpinBox* myNbSegPerEdge;
SMESHGUI_SpinBox* myNbSegPerRadius; SMESHGUI_SpinBox* myNbSegPerRadius;
QCheckBox* myChordalErrorEnabled;
SMESHGUI_SpinBox* myChordalError;
QCheckBox* myAllowQuadrangles; QCheckBox* myAllowQuadrangles;
QCheckBox* mySurfaceCurvature; QCheckBox* mySurfaceCurvature;
QCheckBox* myFuseEdges; QCheckBox* myFuseEdges;
bool myIs2D; bool myIs2D; // 2D or 3D
bool myIsONLY; bool myIsONLY; // one dim or several
QLineEdit* myMeshSizeFile; QLineEdit* myMeshSizeFile;
QTableWidget* myLocalSizeTable; QTableWidget* myLocalSizeTable;

View File

@ -91,6 +91,10 @@
<source>NETGEN_SEG_PER_RADIUS</source> <source>NETGEN_SEG_PER_RADIUS</source>
<translation>Nb. Segs per Radius</translation> <translation>Nb. Segs per Radius</translation>
</message> </message>
<message>
<source>NETGEN_CHORDAL_ERROR</source>
<translation>Chordal Error</translation>
</message>
<message> <message>
<source>NETGEN_SURFACE_CURVATURE</source> <source>NETGEN_SURFACE_CURVATURE</source>
<translation>Limit Size by Surface Curvature</translation> <translation>Limit Size by Surface Curvature</translation>

View File

@ -221,6 +221,14 @@ class NETGEN_1D2D3D_Algorithm(NETGEN_Algorithm):
if self.Parameters(): self.params.SetNbSegPerRadius(theVal) if self.Parameters(): self.params.SetNbSegPerRadius(theVal)
pass pass
## Sets @c ChordalError parameter
# @param theVal new value of the @c ChordalError parameter
def SetChordalError(self, theVal):
if self.Parameters():
self.params.SetChordalError(theVal)
self.params.SetChordalErrorEnabled( theVal > 0 )
pass
## Sets @c QuadAllowed flag ## Sets @c QuadAllowed flag
# @param toAllow new value of the @c QuadAllowed parameter (@c True by default) # @param toAllow new value of the @c QuadAllowed parameter (@c True by default)
def SetQuadAllowed(self, toAllow=True): def SetQuadAllowed(self, toAllow=True):

View File

@ -43,18 +43,20 @@ using namespace std;
NETGENPlugin_Hypothesis::NETGENPlugin_Hypothesis (int hypId, int studyId, NETGENPlugin_Hypothesis::NETGENPlugin_Hypothesis (int hypId, int studyId,
SMESH_Gen * gen) SMESH_Gen * gen)
: SMESH_Hypothesis(hypId, studyId, gen), : SMESH_Hypothesis(hypId, studyId, gen),
_maxSize (GetDefaultMaxSize()), _maxSize (GetDefaultMaxSize()),
_minSize (0), _minSize (0),
_growthRate (GetDefaultGrowthRate()), _growthRate (GetDefaultGrowthRate()),
_nbSegPerEdge (GetDefaultNbSegPerEdge()), _nbSegPerEdge (GetDefaultNbSegPerEdge()),
_nbSegPerRadius (GetDefaultNbSegPerRadius()), _nbSegPerRadius (GetDefaultNbSegPerRadius()),
_fineness (GetDefaultFineness()), _fineness (GetDefaultFineness()),
_secondOrder (GetDefaultSecondOrder()), _chordalErrorEnabled(GetDefaultChordalError() > 0),
_optimize (GetDefaultOptimize()), _chordalError (GetDefaultChordalError() ),
_localSize (GetDefaultLocalSize()), _secondOrder (GetDefaultSecondOrder()),
_quadAllowed (GetDefaultQuadAllowed()), _optimize (GetDefaultOptimize()),
_surfaceCurvature(GetDefaultSurfaceCurvature()), _localSize (GetDefaultLocalSize()),
_fuseEdges (GetDefaultFuseEdges()) _quadAllowed (GetDefaultQuadAllowed()),
_surfaceCurvature (GetDefaultSurfaceCurvature()),
_fuseEdges (GetDefaultFuseEdges())
{ {
_name = "NETGEN_Parameters"; _name = "NETGEN_Parameters";
_param_algo_dim = 3; _param_algo_dim = 3;
@ -208,6 +210,34 @@ void NETGENPlugin_Hypothesis::SetNbSegPerRadius(double theVal)
} }
} }
//=============================================================================
/*!
*
*/
//=============================================================================
void NETGENPlugin_Hypothesis::SetChordalErrorEnabled(bool theVal)
{
if (theVal != _chordalErrorEnabled)
{
_chordalErrorEnabled = theVal;
NotifySubMeshesHypothesisModification();
}
}
//=============================================================================
/*!
*
*/
//=============================================================================
void NETGENPlugin_Hypothesis::SetChordalError(double theVal)
{
if (theVal != _chordalError)
{
_chordalError = theVal;
NotifySubMeshesHypothesisModification();
}
}
//============================================================================= //=============================================================================
/*! /*!
* *
@ -351,8 +381,8 @@ ostream & NETGENPlugin_Hypothesis::SaveTo(ostream & save)
if (it_sm != _localSize.end()) { if (it_sm != _localSize.end()) {
save << " " << "__LOCALSIZE_BEGIN__"; save << " " << "__LOCALSIZE_BEGIN__";
for ( ; it_sm != _localSize.end(); ++it_sm ) { for ( ; it_sm != _localSize.end(); ++it_sm ) {
save << " " << it_sm->first save << " " << it_sm->first
<< " " << it_sm->second << "%#"; // "%#" is a mark of value end << " " << it_sm->second << "%#"; // "%#" is a mark of value end
} }
save << " " << "__LOCALSIZE_END__"; save << " " << "__LOCALSIZE_END__";
} }
@ -363,6 +393,8 @@ ostream & NETGENPlugin_Hypothesis::SaveTo(ostream & save)
save << " " << _meshSizeFile.size() << " " << _meshSizeFile; save << " " << _meshSizeFile.size() << " " << _meshSizeFile;
save << " " << ( _chordalErrorEnabled ? _chordalError : 0. );
return save; return save;
} }
@ -476,12 +508,19 @@ istream & NETGENPlugin_Hypothesis::LoadFrom(istream & load)
load.get( &_meshSizeFile[0], is+1 ); load.get( &_meshSizeFile[0], is+1 );
} }
isOK = static_cast<bool>(load >> val);
if (isOK)
_chordalError = val;
else
load.clear(ios::badbit | load.rdstate());
_chordalErrorEnabled = ( _chordalError > 0 );
return load; return load;
} }
//============================================================================= //=============================================================================
/*! /*!
* *
*/ */
//============================================================================= //=============================================================================
ostream & operator <<(ostream & save, NETGENPlugin_Hypothesis & hyp) ostream & operator <<(ostream & save, NETGENPlugin_Hypothesis & hyp)
@ -491,7 +530,7 @@ ostream & operator <<(ostream & save, NETGENPlugin_Hypothesis & hyp)
//============================================================================= //=============================================================================
/*! /*!
* *
*/ */
//============================================================================= //=============================================================================
istream & operator >>(istream & load, NETGENPlugin_Hypothesis & hyp) istream & operator >>(istream & load, NETGENPlugin_Hypothesis & hyp)
@ -584,6 +623,15 @@ double NETGENPlugin_Hypothesis::GetDefaultNbSegPerRadius()
{ {
return 2; return 2;
} }
//=============================================================================
/*!
*
*/
//=============================================================================
double NETGENPlugin_Hypothesis::GetDefaultChordalError()
{
return -1; // disabled by default
}
//============================================================================= //=============================================================================
/*! /*!

View File

@ -83,6 +83,11 @@ public:
void SetNbSegPerRadius(double theVal); void SetNbSegPerRadius(double theVal);
double GetNbSegPerRadius() const { return _nbSegPerRadius; } double GetNbSegPerRadius() const { return _nbSegPerRadius; }
void SetChordalErrorEnabled(bool value);
double GetChordalErrorEnabled() const { return _chordalErrorEnabled; }
void SetChordalError(double value);
double GetChordalError() const { return _chordalError; }
typedef std::map<std::string, double> TLocalSize; typedef std::map<std::string, double> TLocalSize;
static TLocalSize GetDefaultLocalSize() { return TLocalSize(); } static TLocalSize GetDefaultLocalSize() { return TLocalSize(); }
void SetLocalSizeOnEntry(const std::string& entry, double localSize); void SetLocalSizeOnEntry(const std::string& entry, double localSize);
@ -109,6 +114,7 @@ public:
static double GetDefaultGrowthRate(); static double GetDefaultGrowthRate();
static double GetDefaultNbSegPerEdge(); static double GetDefaultNbSegPerEdge();
static double GetDefaultNbSegPerRadius(); static double GetDefaultNbSegPerRadius();
static double GetDefaultChordalError();
static bool GetDefaultSecondOrder(); static bool GetDefaultSecondOrder();
static bool GetDefaultOptimize(); static bool GetDefaultOptimize();
static bool GetDefaultQuadAllowed(); static bool GetDefaultQuadAllowed();
@ -141,6 +147,8 @@ private:
double _nbSegPerEdge; double _nbSegPerEdge;
double _nbSegPerRadius; double _nbSegPerRadius;
Fineness _fineness; Fineness _fineness;
bool _chordalErrorEnabled;
double _chordalError;
bool _secondOrder; bool _secondOrder;
bool _optimize; bool _optimize;
TLocalSize _localSize; TLocalSize _localSize;

View File

@ -307,6 +307,36 @@ CORBA::Double NETGENPlugin_Hypothesis_i::GetNbSegPerRadius()
//============================================================================= //=============================================================================
void NETGENPlugin_Hypothesis_i::SetChordalErrorEnabled(CORBA::Boolean theValue)
{
if ( isToSetParameter( GetChordalErrorEnabled(), theValue, METH_SetChordalErrorEnabled ))
{
this->GetImpl()->SetChordalErrorEnabled(theValue);
SMESH::TPythonDump() << _this() << ".SetChordalErrorEnabled( " << theValue << " )";
}
}
CORBA::Boolean NETGENPlugin_Hypothesis_i::GetChordalErrorEnabled()
{
return GetImpl()->GetChordalErrorEnabled();
}
void NETGENPlugin_Hypothesis_i::SetChordalError(CORBA::Double theValue)
{
if ( isToSetParameter( GetChordalError(), theValue, METH_SetChordalError ))
{
this->GetImpl()->SetChordalError(theValue);
SMESH::TPythonDump() << _this() << ".SetChordalError( " << SMESH::TVar(theValue) << " )";
}
}
CORBA::Double NETGENPlugin_Hypothesis_i::GetChordalError()
{
return GetImpl()->GetChordalError();
}
//=============================================================================
void NETGENPlugin_Hypothesis_i::SetLocalSizeOnShape(GEOM::GEOM_Object_ptr GeomObj, void NETGENPlugin_Hypothesis_i::SetLocalSizeOnShape(GEOM::GEOM_Object_ptr GeomObj,
CORBA::Double localSize) CORBA::Double localSize)
throw (SALOME::SALOME_Exception) throw (SALOME::SALOME_Exception)

View File

@ -79,6 +79,11 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Hypothesis_i:
void SetNbSegPerRadius(CORBA::Double theVal); void SetNbSegPerRadius(CORBA::Double theVal);
CORBA::Double GetNbSegPerRadius(); CORBA::Double GetNbSegPerRadius();
void SetChordalErrorEnabled(CORBA::Boolean value);
CORBA::Boolean GetChordalErrorEnabled();
void SetChordalError(CORBA::Double value);
CORBA::Double GetChordalError();
void SetLocalSizeOnShape(GEOM::GEOM_Object_ptr GeomObj, CORBA::Double localSize) void SetLocalSizeOnShape(GEOM::GEOM_Object_ptr GeomObj, CORBA::Double localSize)
throw (SALOME::SALOME_Exception); throw (SALOME::SALOME_Exception);
void SetLocalSizeOnEntry(const char* entry, CORBA::Double localSize); void SetLocalSizeOnEntry(const char* entry, CORBA::Double localSize);
@ -109,19 +114,21 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Hypothesis_i:
// to remember whether a parameter is already set (issue 0021364) // to remember whether a parameter is already set (issue 0021364)
enum SettingMethod enum SettingMethod
{ {
METH_SetMaxSize = 1, METH_SetMaxSize = 1,
METH_SetMinSize = 2, METH_SetMinSize = 2,
METH_SetSecondOrder = 4, METH_SetSecondOrder = 4,
METH_SetOptimize = 8, METH_SetOptimize = 8,
METH_SetFineness = 16, METH_SetFineness = 16,
METH_SetGrowthRate = 32, METH_SetGrowthRate = 32,
METH_SetNbSegPerEdge = 64, METH_SetNbSegPerEdge = 64,
METH_SetNbSegPerRadius = 128, METH_SetNbSegPerRadius = 128,
METH_SetLocalSizeOnEntry = 256, METH_SetLocalSizeOnEntry = 256,
METH_SetQuadAllowed = METH_SetLocalSizeOnEntry * 2, METH_SetQuadAllowed = METH_SetLocalSizeOnEntry * 2,
METH_SetSurfaceCurvature = METH_SetQuadAllowed * 2, METH_SetSurfaceCurvature = METH_SetQuadAllowed * 2,
METH_SetFuseEdges = METH_SetSurfaceCurvature * 2, METH_SetFuseEdges = METH_SetSurfaceCurvature * 2,
METH_LAST = METH_SetFuseEdges METH_SetChordalErrorEnabled = METH_SetFuseEdges * 2,
METH_SetChordalError = METH_SetChordalErrorEnabled * 2,
METH_LAST = METH_SetFuseEdges
}; };
int mySetMethodFlags; int mySetMethodFlags;

View File

@ -52,21 +52,29 @@
#include <utilities.h> #include <utilities.h>
#include <BRepAdaptor_Surface.hxx>
#include <BRepBuilderAPI_Copy.hxx> #include <BRepBuilderAPI_Copy.hxx>
#include <BRepLProp_SLProps.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx> #include <BRep_Tool.hxx>
#include <Bnd_B3d.hxx> #include <Bnd_B3d.hxx>
#include <GeomLib_IsPlanarSurface.hxx>
#include <NCollection_Map.hxx> #include <NCollection_Map.hxx>
#include <Poly_Triangulation.hxx>
#include <Standard_ErrorHandler.hxx> #include <Standard_ErrorHandler.hxx>
#include <Standard_ProgramError.hxx> #include <Standard_ProgramError.hxx>
#include <TColStd_MapOfInteger.hxx> #include <TColStd_MapOfInteger.hxx>
#include <TopExp.hxx> #include <TopExp.hxx>
#include <TopExp_Explorer.hxx> #include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
#include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx> #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx> #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
#include <TopTools_DataMapOfShapeInteger.hxx> #include <TopTools_DataMapOfShapeInteger.hxx>
#include <TopTools_DataMapOfShapeShape.hxx> #include <TopTools_DataMapOfShapeShape.hxx>
#include <TopTools_MapOfShape.hxx> #include <TopTools_MapOfShape.hxx>
#include <TopoDS.hxx> #include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
// Netgen include files // Netgen include files
#ifndef OCCGEOMETRY #ifndef OCCGEOMETRY
@ -151,12 +159,14 @@ NETGENPlugin_Mesher::NETGENPlugin_Mesher (SMESH_Mesh* mesh,
_optimize(true), _optimize(true),
_fineness(NETGENPlugin_Hypothesis::GetDefaultFineness()), _fineness(NETGENPlugin_Hypothesis::GetDefaultFineness()),
_isViscousLayers2D(false), _isViscousLayers2D(false),
_chordalError(-1), // means disabled
_ngMesh(NULL), _ngMesh(NULL),
_occgeom(NULL), _occgeom(NULL),
_curShapeIndex(-1), _curShapeIndex(-1),
_progressTic(1), _progressTic(1),
_totalTime(1.0), _totalTime(1.0),
_simpleHyp(NULL), _simpleHyp(NULL),
_viscousLayersHyp(NULL),
_ptrToMe(NULL) _ptrToMe(NULL)
{ {
SetDefaultParameters(); SetDefaultParameters();
@ -292,32 +302,36 @@ void NETGENPlugin_Mesher::SetParameters(const NETGENPlugin_Hypothesis* hyp)
_fineness = hyp->GetFineness(); _fineness = hyp->GetFineness();
mparams.uselocalh = hyp->GetSurfaceCurvature(); mparams.uselocalh = hyp->GetSurfaceCurvature();
netgen::merge_solids = hyp->GetFuseEdges(); netgen::merge_solids = hyp->GetFuseEdges();
_chordalError = hyp->GetChordalErrorEnabled() ? hyp->GetChordalError() : -1.;
_simpleHyp = NULL; _simpleHyp = NULL;
// mesh size file // mesh size file
mparams.meshsizefilename= hyp->GetMeshSizeFile().empty() ? 0 : hyp->GetMeshSizeFile().c_str(); mparams.meshsizefilename= hyp->GetMeshSizeFile().empty() ? 0 : hyp->GetMeshSizeFile().c_str();
SMESH_Gen_i* smeshGen_i = SMESH_Gen_i::GetSMESHGen(); const NETGENPlugin_Hypothesis::TLocalSize& localSizes = hyp->GetLocalSizesAndEntries();
CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager"); if ( !localSizes.empty() )
SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject);
SALOMEDS::Study_var myStudy = aStudyMgr->GetStudyByID(hyp->GetStudyId());
if ( !myStudy->_is_nil() )
{ {
const NETGENPlugin_Hypothesis::TLocalSize localSizes = hyp->GetLocalSizesAndEntries(); SMESH_Gen_i* smeshGen_i = SMESH_Gen_i::GetSMESHGen();
NETGENPlugin_Hypothesis::TLocalSize::const_iterator it = localSizes.begin(); CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager");
for ( ; it != localSizes.end() ; it++) SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject);
SALOMEDS::Study_var myStudy = aStudyMgr->GetStudyByID(hyp->GetStudyId());
if ( !myStudy->_is_nil() )
{ {
std::string entry = (*it).first; NETGENPlugin_Hypothesis::TLocalSize::const_iterator it = localSizes.begin();
double val = (*it).second; for ( ; it != localSizes.end() ; it++)
// -- {
GEOM::GEOM_Object_var aGeomObj; std::string entry = (*it).first;
SALOMEDS::SObject_var aSObj = myStudy->FindObjectID( entry.c_str() ); double val = (*it).second;
if ( !aSObj->_is_nil() ) { // --
CORBA::Object_var obj = aSObj->GetObject(); GEOM::GEOM_Object_var aGeomObj;
aGeomObj = GEOM::GEOM_Object::_narrow(obj); SALOMEDS::SObject_var aSObj = myStudy->FindObjectID( entry.c_str() );
aSObj->UnRegister(); if ( !aSObj->_is_nil() ) {
CORBA::Object_var obj = aSObj->GetObject();
aGeomObj = GEOM::GEOM_Object::_narrow(obj);
aSObj->UnRegister();
}
TopoDS_Shape S = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
::SetLocalSize(S, val);
} }
TopoDS_Shape S = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
::SetLocalSize(S, val);
} }
} }
} }
@ -336,6 +350,17 @@ void NETGENPlugin_Mesher::SetParameters(const NETGENPlugin_SimpleHypothesis_2D*
SetDefaultParameters(); SetDefaultParameters();
} }
//================================================================================
/*!
* \brief Store a Viscous Layers hypothesis
*/
//================================================================================
void NETGENPlugin_Mesher::SetParameters(const StdMeshers_ViscousLayers* hyp )
{
_viscousLayersHyp = hyp;
}
//============================================================================= //=============================================================================
/*! /*!
* Link - a pair of integer numbers * Link - a pair of integer numbers
@ -585,7 +610,8 @@ namespace
void setLocalSize(const TopoDS_Edge& edge, void setLocalSize(const TopoDS_Edge& edge,
double size, double size,
netgen::Mesh& mesh) netgen::Mesh& mesh,
const bool overrideMinH = true)
{ {
if ( size <= std::numeric_limits<double>::min() ) if ( size <= std::numeric_limits<double>::min() )
return; return;
@ -596,7 +622,7 @@ namespace
TopoDS_Iterator vIt( edge ); TopoDS_Iterator vIt( edge );
if ( !vIt.More() ) return; if ( !vIt.More() ) return;
gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( vIt.Value() )); gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( vIt.Value() ));
NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size ); NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size, overrideMinH );
} }
else else
{ {
@ -606,15 +632,29 @@ namespace
{ {
Standard_Real u = u1 + delta*i; Standard_Real u = u1 + delta*i;
gp_Pnt p = curve->Value(u); gp_Pnt p = curve->Value(u);
NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size ); NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size, overrideMinH );
netgen::Point3d pi(p.X(), p.Y(), p.Z()); netgen::Point3d pi(p.X(), p.Y(), p.Z());
double resultSize = mesh.GetH(pi); double resultSize = mesh.GetH(pi);
if ( resultSize - size > 0.1*size ) if ( resultSize - size > 0.1*size )
// netgen does restriction iff oldH/newH > 1.2 (localh.cpp:136) // netgen does restriction iff oldH/newH > 1.2 (localh.cpp:136)
NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), resultSize/1.201 ); NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), resultSize/1.201, overrideMinH );
} }
} }
} }
//================================================================================
/*!
* \brief Return triangle size for a given chordalError and radius of curvature
*/
//================================================================================
double elemSizeForChordalError( double chordalError, double radius )
{
if ( 2 * radius < chordalError )
return 1.5 * radius;
return Sqrt( 3 ) * Sqrt( chordalError * ( 2 * radius - chordalError ));
}
} // namespace } // namespace
//================================================================================ //================================================================================
@ -624,16 +664,19 @@ namespace
//================================================================================ //================================================================================
void NETGENPlugin_Mesher::SetLocalSize( netgen::OCCGeometry& occgeo, void NETGENPlugin_Mesher::SetLocalSize( netgen::OCCGeometry& occgeo,
netgen::Mesh& ngMesh ) netgen::Mesh& ngMesh)
{ {
for(std::map<int,double>::const_iterator it=EdgeId2LocalSize.begin(); it!=EdgeId2LocalSize.end(); it++) // edges
std::map<int,double>::const_iterator it;
for( it=EdgeId2LocalSize.begin(); it!=EdgeId2LocalSize.end(); it++)
{ {
int key = (*it).first; int key = (*it).first;
double hi = (*it).second; double hi = (*it).second;
const TopoDS_Shape& shape = ShapesWithLocalSize.FindKey(key); const TopoDS_Shape& shape = ShapesWithLocalSize.FindKey(key);
setLocalSize( TopoDS::Edge(shape), hi, ngMesh ); setLocalSize( TopoDS::Edge(shape), hi, ngMesh );
} }
for(std::map<int,double>::const_iterator it=VertexId2LocalSize.begin(); it!=VertexId2LocalSize.end(); it++) // vertices
for(it=VertexId2LocalSize.begin(); it!=VertexId2LocalSize.end(); it++)
{ {
int key = (*it).first; int key = (*it).first;
double hi = (*it).second; double hi = (*it).second;
@ -641,7 +684,8 @@ void NETGENPlugin_Mesher::SetLocalSize( netgen::OCCGeometry& occgeo,
gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex(shape) ); gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex(shape) );
NETGENPlugin_Mesher::RestrictLocalSize( ngMesh, p.XYZ(), hi ); NETGENPlugin_Mesher::RestrictLocalSize( ngMesh, p.XYZ(), hi );
} }
for(map<int,double>::const_iterator it=FaceId2LocalSize.begin(); it!=FaceId2LocalSize.end(); it++) // faces
for(it=FaceId2LocalSize.begin(); it!=FaceId2LocalSize.end(); it++)
{ {
int key = (*it).first; int key = (*it).first;
double val = (*it).second; double val = (*it).second;
@ -659,7 +703,8 @@ void NETGENPlugin_Mesher::SetLocalSize( netgen::OCCGeometry& occgeo,
ShapesWithControlPoints.insert( key ); ShapesWithControlPoints.insert( key );
} }
} }
for(map<int,double>::const_iterator it=SolidId2LocalSize.begin(); it!=SolidId2LocalSize.end(); it++) //solids
for(it=SolidId2LocalSize.begin(); it!=SolidId2LocalSize.end(); it++)
{ {
int key = (*it).first; int key = (*it).first;
double val = (*it).second; double val = (*it).second;
@ -676,6 +721,146 @@ void NETGENPlugin_Mesher::SetLocalSize( netgen::OCCGeometry& occgeo,
for ( size_t i = 0; i < ControlPoints.size(); ++i ) for ( size_t i = 0; i < ControlPoints.size(); ++i )
NETGENPlugin_Mesher::RestrictLocalSize( ngMesh, ControlPoints[i].XYZ(), ControlPoints[i].Size() ); NETGENPlugin_Mesher::RestrictLocalSize( ngMesh, ControlPoints[i].XYZ(), ControlPoints[i].Size() );
} }
return;
}
//================================================================================
/*!
* \brief Restrict local size to achieve a required _chordalError
*/
//================================================================================
void NETGENPlugin_Mesher::SetLocalSizeForChordalError( netgen::OCCGeometry& occgeo,
netgen::Mesh& ngMesh)
{
if ( _chordalError <= 0. )
return;
TopLoc_Location loc;
BRepLProp_SLProps surfProp( 2, 1e-6 );
const double sizeCoef = 0.95;
// find non-planar FACEs with non-constant curvature
std::vector<int> fInd;
for ( int i = 1; i <= occgeo.fmap.Extent(); ++i )
{
const TopoDS_Face& face = TopoDS::Face( occgeo.fmap( i ));
BRepAdaptor_Surface surfAd( face, false );
switch ( surfAd.GetType() )
{
case GeomAbs_Plane:
continue;
case GeomAbs_Cylinder:
case GeomAbs_Sphere:
case GeomAbs_Torus: // constant curvature
{
surfProp.SetSurface( surfAd );
surfProp.SetParameters( 0, 0 );
double maxCurv = Max( Abs( surfProp.MaxCurvature()), Abs( surfProp.MinCurvature() ));
double size = elemSizeForChordalError( _chordalError, 1 / maxCurv );
occgeo.SetFaceMaxH( i, size * sizeCoef );
// limit size one edges
TopTools_MapOfShape edgeMap;
for ( TopExp_Explorer eExp( face, TopAbs_EDGE ); eExp.More(); eExp.Next() )
if ( edgeMap.Add( eExp.Current() ))
setLocalSize( TopoDS::Edge( eExp.Current() ), size, ngMesh, /*overrideMinH=*/false );
break;
}
default:
Handle(Geom_Surface) surf = BRep_Tool::Surface( face, loc );
if ( GeomLib_IsPlanarSurface( surf ).IsPlanar() )
continue;
fInd.push_back( i );
}
}
// set local size
if ( !fInd.empty() )
{
BRep_Builder b;
TopoDS_Compound allFacesComp;
b.MakeCompound( allFacesComp );
for ( size_t i = 0; i < fInd.size(); ++i )
b.Add( allFacesComp, occgeo.fmap( fInd[i] ));
// copy the shape to avoid spoiling its triangulation
TopoDS_Shape allFacesCompCopy = BRepBuilderAPI_Copy( allFacesComp );
// create triangulation with desired chordal error
BRepMesh_IncrementalMesh( allFacesCompCopy,
_chordalError,
/*isRelative = */Standard_False,
/*theAngDeflection = */ 0.5,
/*isInParallel = */Standard_True);
// loop on FACEs
for ( TopExp_Explorer fExp( allFacesCompCopy, TopAbs_FACE ); fExp.More(); fExp.Next() )
{
const TopoDS_Face& face = TopoDS::Face( fExp.Current() );
Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation ( face, loc );
if ( triangulation.IsNull() ) continue;
BRepAdaptor_Surface surf( face, false );
surfProp.SetSurface( surf );
gp_XY uv[3];
gp_XYZ p[3];
double size[3];
for ( int i = 1; i <= triangulation->NbTriangles(); ++i )
{
Standard_Integer n1,n2,n3;
triangulation->Triangles()(i).Get( n1,n2,n3 );
p [0] = triangulation->Nodes()(n1).Transformed(loc).XYZ();
p [1] = triangulation->Nodes()(n2).Transformed(loc).XYZ();
p [2] = triangulation->Nodes()(n3).Transformed(loc).XYZ();
uv[0] = triangulation->UVNodes()(n1).XY();
uv[1] = triangulation->UVNodes()(n2).XY();
uv[2] = triangulation->UVNodes()(n3).XY();
surfProp.SetParameters( uv[0].X(), uv[0].Y() );
if ( !surfProp.IsCurvatureDefined() )
break;
for ( int n = 0; n < 3; ++n ) // get size at triangle nodes
{
surfProp.SetParameters( uv[n].X(), uv[n].Y() );
double maxCurv = Max( Abs( surfProp.MaxCurvature()), Abs( surfProp.MinCurvature() ));
size[n] = elemSizeForChordalError( _chordalError, 1 / maxCurv );
}
for ( int n1 = 0; n1 < 3; ++n1 ) // limit size along each triangle edge
{
int n2 = ( n1 + 1 ) % 3;
double minSize = size[n1], maxSize = size[n2];
if ( size[n1] > size[n2] )
minSize = size[n2], maxSize = size[n1];
if ( maxSize / minSize < 1.2 ) // netgen ignores size difference < 1.2
{
ngMesh.RestrictLocalHLine ( netgen::Point3d( p[n1].X(), p[n1].Y(), p[n1].Z() ),
netgen::Point3d( p[n2].X(), p[n2].Y(), p[n2].Z() ),
sizeCoef * minSize );
}
else
{
gp_XY uvVec( uv[n2] - uv[n1] );
double len = ( p[n1] - p[n2] ).Modulus();
int nb = int( len / minSize ) + 1;
for ( int j = 0; j <= nb; ++j )
{
double r = double( j ) / nb;
gp_XY uvj = uv[n1] + r * uvVec;
surfProp.SetParameters( uvj.X(), uvj.Y() );
double maxCurv = Max( Abs( surfProp.MaxCurvature()), Abs( surfProp.MinCurvature() ));
double h = elemSizeForChordalError( _chordalError, 1 / maxCurv );
const gp_Pnt& pj = surfProp.Value();
netgen::Point3d ngP( pj.X(), pj.Y(), pj.Z());
ngMesh.RestrictLocalH( ngP, h * sizeCoef );
}
}
}
}
}
}
} }
//================================================================================ //================================================================================
@ -808,7 +993,7 @@ double NETGENPlugin_Mesher::GetDefaultMinSize(const TopoDS_Shape& geom,
} }
else else
{ {
minh = 3 * sqrt( minh ); // triangulation for visualization is rather fine minh = sqrt( minh ); // triangulation for visualization is rather fine
//cout << "TRIANGULATION minh = " <<minh << endl; //cout << "TRIANGULATION minh = " <<minh << endl;
} }
if ( minh > 0.5 * maxSize ) if ( minh > 0.5 * maxSize )
@ -926,7 +1111,8 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom,
// get all nodes from connected <edges> // get all nodes from connected <edges>
const bool isQuad = smDS->IsQuadratic(); const bool isQuad = smDS->IsQuadratic();
StdMeshers_FaceSide fSide( face, edges, _mesh, isForwad, isQuad ); //StdMeshers_FaceSide fSide( face, edges, _mesh, isForwad, isQuad, &helper ); -- master
StdMeshers_FaceSide fSide( face, edges, _mesh, isForwad, isQuad ); // -- V8_2_BR
const vector<UVPtStruct>& points = fSide.GetUVPtStruct(); const vector<UVPtStruct>& points = fSide.GetUVPtStruct();
if ( points.empty() ) if ( points.empty() )
return false; // invalid node params? return false; // invalid node params?
@ -1054,13 +1240,6 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom,
// Find solids the geomFace bounds // Find solids the geomFace bounds
int solidID1 = 0, solidID2 = 0; int solidID1 = 0, solidID2 = 0;
StdMeshers_QuadToTriaAdaptor* quadAdaptor =
dynamic_cast<StdMeshers_QuadToTriaAdaptor*>( proxyMesh.get() );
if ( quadAdaptor )
{
solidID1 = occgeom.somap.FindIndex( quadAdaptor->GetShape() );
}
else
{ {
PShapeIteratorPtr solidIt = helper.GetAncestors( geomFace, *sm->GetFather(), TopAbs_SOLID); PShapeIteratorPtr solidIt = helper.GetAncestors( geomFace, *sm->GetFather(), TopAbs_SOLID);
while ( const TopoDS_Shape * solid = solidIt->next() ) while ( const TopoDS_Shape * solid = solidIt->next() )
@ -1070,6 +1249,81 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom,
else solidID1 = id; else solidID1 = id;
} }
} }
if ( proxyMesh && proxyMesh->GetProxySubMesh( geomFace ))
{
// if a proxy sub-mesh contains temporary faces, then these faces
// should be used to mesh only one SOLID
bool hasTmp = false;
smDS = proxyMesh->GetSubMesh( geomFace );
SMDS_ElemIteratorPtr faces = smDS->GetElements();
while ( faces->more() )
{
const SMDS_MeshElement* f = faces->next();
if ( proxyMesh->IsTemporary( f ))
{
hasTmp = true;
std::vector<const SMDS_MeshNode*> fNodes( f->begin_nodes(), f->end_nodes() );
std::vector<const SMDS_MeshElement*> vols;
if ( _mesh->GetMeshDS()->GetElementsByNodes( fNodes, vols, SMDSAbs_Volume ) == 1 )
{
int geomID = vols[0]->getshapeId();
const TopoDS_Shape& solid = helper.GetMeshDS()->IndexToShape( geomID );
if ( !solid.IsNull() )
solidID1 = occgeom.somap.FindIndex ( solid );
solidID2 = 0;
break;
}
}
}
// exclude faces generated by NETGEN from computation of 3D mesh
const int fID = occgeom.fmap.FindIndex( geomFace );
if ( !hasTmp ) // shrunk mesh
{
// move netgen points according to moved nodes
SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true);
while ( smIt->more() )
{
SMESH_subMesh* sub = smIt->next();
if ( !sub->GetSubMeshDS() ) continue;
SMDS_NodeIteratorPtr nodeIt = sub->GetSubMeshDS()->GetNodes();
while ( nodeIt->more() )
{
const SMDS_MeshNode* n = nodeIt->next();
int ngID = ngNodeId( n, ngMesh, nodeNgIdMap );
netgen::MeshPoint& ngPoint = ngMesh.Point( ngID );
ngPoint(0) = n->X();
ngPoint(1) = n->Y();
ngPoint(2) = n->Z();
}
}
// remove faces near boundary to avoid their overlapping
// with shrunk faces
for ( int i = 1; i <= ngMesh.GetNSE(); ++i )
{
const netgen::Element2d& elem = ngMesh.SurfaceElement(i);
if ( elem.GetIndex() == fID )
{
for ( int iN = 0; iN < elem.GetNP(); ++iN )
if ( ngMesh[ elem[ iN ]].Type() != netgen::SURFACEPOINT )
{
ngMesh.DeleteSurfaceElement( i );
break;
}
}
}
}
//if ( hasTmp )
{
faceNgID++;
ngMesh.AddFaceDescriptor( netgen::FaceDescriptor( faceNgID,/*solid1=*/0,/*solid2=*/0,0 ));
for (int i = 1; i <= ngMesh.GetNSE(); ++i )
{
const netgen::Element2d& elem = ngMesh.SurfaceElement(i);
if ( elem.GetIndex() == fID )
const_cast< netgen::Element2d& >( elem ).SetIndex( faceNgID );
}
}
}
// Add ng face descriptors of meshed faces // Add ng face descriptors of meshed faces
faceNgID++; faceNgID++;
ngMesh.AddFaceDescriptor( netgen::FaceDescriptor( faceNgID, solidID1, solidID2, 0 )); ngMesh.AddFaceDescriptor( netgen::FaceDescriptor( faceNgID, solidID1, solidID2, 0 ));
@ -1112,8 +1366,6 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom,
cout << "SMESH face " << helper.GetMeshDS()->ShapeToIndex( geomFace ) cout << "SMESH face " << helper.GetMeshDS()->ShapeToIndex( geomFace )
<< " internal="<<isInternalFace << endl; << " internal="<<isInternalFace << endl;
#endif #endif
if ( proxyMesh )
smDS = proxyMesh->GetSubMesh( geomFace );
SMDS_ElemIteratorPtr faces = smDS->GetElements(); SMDS_ElemIteratorPtr faces = smDS->GetElements();
while ( faces->more() ) while ( faces->more() )
@ -1430,10 +1682,15 @@ namespace
int ngIdCloseN; //!< ng id of closest node of the closest 2d mesh element int ngIdCloseN; //!< ng id of closest node of the closest 2d mesh element
}; };
inline double dist2(const netgen::MeshPoint& p1, const netgen::MeshPoint& p2) inline double dist2( const netgen::MeshPoint& p1, const netgen::MeshPoint& p2 )
{ {
return gp_Pnt( NGPOINT_COORDS(p1)).SquareDistance( gp_Pnt( NGPOINT_COORDS(p2))); return gp_Pnt( NGPOINT_COORDS(p1)).SquareDistance( gp_Pnt( NGPOINT_COORDS(p2)));
} }
// inline double dist2(const netgen::MeshPoint& p, const SMDS_MeshNode* n )
// {
// return gp_Pnt( NGPOINT_COORDS(p)).SquareDistance( SMESH_NodeXYZ(n));
// }
} }
//================================================================================ //================================================================================
@ -2136,13 +2393,35 @@ int NETGENPlugin_Mesher::FillSMesh(const netgen::OCCGeometry& occgeo,
if ( quadHelper && !quadHelper->GetIsQuadratic() && quadHelper->GetTLinkNodeMap().empty() ) if ( quadHelper && !quadHelper->GetIsQuadratic() && quadHelper->GetTLinkNodeMap().empty() )
quadHelper = 0; quadHelper = 0;
int i, nbInitNod = initState._nbNodes;
if ( initState._elementsRemoved )
{
// PAL23427. Update nodeVec to track removal of netgen free points as a result
// of removal of faces in FillNgMesh() in the case of a shrunk sub-mesh
int ngID, nodeVecSize = nodeVec.size();
const double eps = std::numeric_limits<double>::min();
for ( ngID = i = 1; i < nodeVecSize; ++ngID, ++i )
{
gp_Pnt ngPnt( NGPOINT_COORDS( ngMesh.Point( ngID )));
gp_Pnt node ( SMESH_NodeXYZ ( nodeVec[ i ]));
if ( ngPnt.SquareDistance( node ) < eps )
{
nodeVec[ ngID ] = nodeVec[ i ];
}
else
{
--ngID;
}
}
nodeVec.resize( ngID );
nbInitNod = ngID - 1;
}
// ------------------------------------- // -------------------------------------
// Create and insert nodes into nodeVec // Create and insert nodes into nodeVec
// ------------------------------------- // -------------------------------------
nodeVec.resize( nbNod + 1 ); nodeVec.resize( nbNod + 1 );
int i, nbInitNod = initState._nbNodes; for ( i = nbInitNod+1; i <= nbNod; ++i )
for (i = nbInitNod+1; i <= nbNod; ++i )
{ {
const netgen::MeshPoint& ngPoint = ngMesh.Point(i); const netgen::MeshPoint& ngPoint = ngMesh.Point(i);
SMDS_MeshNode* node = NULL; SMDS_MeshNode* node = NULL;
@ -2503,8 +2782,6 @@ bool NETGENPlugin_Mesher::Compute()
SMESH_MesherHelper quadHelper( *_mesh ); SMESH_MesherHelper quadHelper( *_mesh );
quadHelper.SetIsQuadratic( mparams.secondorder ); quadHelper.SetIsQuadratic( mparams.secondorder );
static string debugFile = "/tmp/ngMesh.py"; /* to call toPython( _ngMesh, debugFile )
while debugging netgen */
// ------------------------- // -------------------------
// Prepare OCC geometry // Prepare OCC geometry
// ------------------------- // -------------------------
@ -2621,6 +2898,7 @@ bool NETGENPlugin_Mesher::Compute()
{ {
// Local size on shapes // Local size on shapes
SetLocalSize( occgeo, *_ngMesh ); SetLocalSize( occgeo, *_ngMesh );
SetLocalSizeForChordalError( occgeo, *_ngMesh );
} }
// Precompute internal edges (issue 0020676) in order to // Precompute internal edges (issue 0020676) in order to
@ -2791,7 +3069,8 @@ bool NETGENPlugin_Mesher::Compute()
helper.SetSubShape( F ); helper.SetSubShape( F );
TSideVector wires = TSideVector wires =
StdMeshers_FaceSide::GetFaceWires( F, *_mesh, /*skipMediumNodes=*/true, StdMeshers_FaceSide::GetFaceWires( F, *_mesh, /*skipMediumNodes=*/true,
error, viscousMesh ); error, viscousMesh ); // -- V8_2_BR
// error, &helper, viscousMesh ); -- master
error = AddSegmentsToMesh( *_ngMesh, occgeo, wires, helper, nodeVec ); error = AddSegmentsToMesh( *_ngMesh, occgeo, wires, helper, nodeVec );
if ( !error ) error = SMESH_ComputeError::New(); if ( !error ) error = SMESH_ComputeError::New();
@ -2835,37 +3114,58 @@ bool NETGENPlugin_Mesher::Compute()
// generate volume mesh // generate volume mesh
// --------------------- // ---------------------
// Fill _ngMesh with nodes and faces of computed 2D submeshes // Fill _ngMesh with nodes and faces of computed 2D submeshes
if ( !err && _isVolume && ( !meshedSM[ MeshDim_2D ].empty() || mparams.quad )) if ( !err && _isVolume &&
( !meshedSM[ MeshDim_2D ].empty() || mparams.quad || _viscousLayersHyp ))
{ {
// load SMESH with computed segments and faces // load SMESH with computed segments and faces
FillSMesh( occgeo, *_ngMesh, initState, *_mesh, nodeVec, comment, &quadHelper ); FillSMesh( occgeo, *_ngMesh, initState, *_mesh, nodeVec, comment, &quadHelper );
// compute prismatic boundary volumes
int nbQuad = _mesh->NbQuadrangles();
SMESH_ProxyMesh::Ptr viscousMesh;
if ( _viscousLayersHyp )
{
viscousMesh = _viscousLayersHyp->Compute( *_mesh, _shape );
if ( !viscousMesh )
return false;
}
// compute pyramids on quadrangles // compute pyramids on quadrangles
SMESH_ProxyMesh::Ptr proxyMesh; vector<SMESH_ProxyMesh::Ptr> pyramidMeshes( occgeo.somap.Extent() );
if ( _mesh->NbQuadrangles() > 0 ) if ( nbQuad > 0 )
for ( int iS = 1; iS <= occgeo.somap.Extent(); ++iS ) for ( int iS = 1; iS <= occgeo.somap.Extent(); ++iS )
{ {
StdMeshers_QuadToTriaAdaptor* Adaptor = new StdMeshers_QuadToTriaAdaptor; StdMeshers_QuadToTriaAdaptor* adaptor = new StdMeshers_QuadToTriaAdaptor;
proxyMesh.reset( Adaptor ); pyramidMeshes[ iS-1 ].reset( adaptor );
bool ok = adaptor->Compute( *_mesh, occgeo.somap(iS), viscousMesh.get() );
int nbPyrams = _mesh->NbPyramids(); if ( !ok )
Adaptor->Compute( *_mesh, occgeo.somap(iS) ); return false;
if ( nbPyrams != _mesh->NbPyramids() )
{
list< SMESH_subMesh* > quadFaceSM;
for (TopExp_Explorer face(occgeo.somap(iS), TopAbs_FACE); face.More(); face.Next())
if ( Adaptor->GetProxySubMesh( face.Current() ))
{
quadFaceSM.push_back( _mesh->GetSubMesh( face.Current() ));
meshedSM[ MeshDim_2D ].remove( quadFaceSM.back() );
}
FillNgMesh(occgeo, *_ngMesh, nodeVec, quadFaceSM, &quadHelper, proxyMesh);
}
} }
// add proxy faces to NG mesh
list< SMESH_subMesh* > viscousSM;
for ( int iS = 1; iS <= occgeo.somap.Extent(); ++iS )
{
list< SMESH_subMesh* > quadFaceSM;
for (TopExp_Explorer face(occgeo.somap(iS), TopAbs_FACE); face.More(); face.Next())
if ( pyramidMeshes[iS-1] && pyramidMeshes[iS-1]->GetProxySubMesh( face.Current() ))
{
quadFaceSM.push_back( _mesh->GetSubMesh( face.Current() ));
meshedSM[ MeshDim_2D ].remove( quadFaceSM.back() );
}
else if ( viscousMesh && viscousMesh->GetProxySubMesh( face.Current() ))
{
viscousSM.push_back( _mesh->GetSubMesh( face.Current() ));
meshedSM[ MeshDim_2D ].remove( viscousSM.back() );
}
if ( !quadFaceSM.empty() )
FillNgMesh(occgeo, *_ngMesh, nodeVec, quadFaceSM, &quadHelper, pyramidMeshes[iS-1]);
}
if ( !viscousSM.empty() )
FillNgMesh(occgeo, *_ngMesh, nodeVec, viscousSM, &quadHelper, viscousMesh );
// fill _ngMesh with faces of sub-meshes // fill _ngMesh with faces of sub-meshes
err = ! ( FillNgMesh(occgeo, *_ngMesh, nodeVec, meshedSM[ MeshDim_2D ], &quadHelper)); err = ! ( FillNgMesh(occgeo, *_ngMesh, nodeVec, meshedSM[ MeshDim_2D ], &quadHelper));
initState = NETGENPlugin_ngMeshInfo(_ngMesh); initState = NETGENPlugin_ngMeshInfo(_ngMesh, /*checkRemovedElems=*/true);
//toPython( _ngMesh, "/tmp/ngPython.py"); // toPython( _ngMesh );
} }
if (!err && _isVolume) if (!err && _isVolume)
{ {
@ -3166,25 +3466,25 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap)
sm->GetComputeError().reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED )); sm->GetComputeError().reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED ));
return false; return false;
} }
if ( _simpleHyp ) // if ( _simpleHyp )
{ // {
// Pass 1D simple parameters to NETGEN // // Pass 1D simple parameters to NETGEN
// -------------------------------- // // --------------------------------
int nbSeg = _simpleHyp->GetNumberOfSegments(); // int nbSeg = _simpleHyp->GetNumberOfSegments();
double segSize = _simpleHyp->GetLocalLength(); // double segSize = _simpleHyp->GetLocalLength();
for ( int iE = 1; iE <= occgeo.emap.Extent(); ++iE ) // for ( int iE = 1; iE <= occgeo.emap.Extent(); ++iE )
{ // {
const TopoDS_Edge& e = TopoDS::Edge( occgeo.emap(iE)); // const TopoDS_Edge& e = TopoDS::Edge( occgeo.emap(iE));
if ( nbSeg ) // if ( nbSeg )
segSize = SMESH_Algo::EdgeLength( e ) / ( nbSeg - 0.4 ); // segSize = SMESH_Algo::EdgeLength( e ) / ( nbSeg - 0.4 );
setLocalSize( e, segSize, *ngMesh ); // setLocalSize( e, segSize, *ngMesh );
} // }
} // }
else // if ( ! _simpleHyp ) // else // if ( ! _simpleHyp )
{ // {
// Local size on shapes // // Local size on shapes
SetLocalSize( occgeo, *ngMesh ); // SetLocalSize( occgeo, *ngMesh );
} // }
// calculate total nb of segments and length of edges // calculate total nb of segments and length of edges
double fullLen = 0.0; double fullLen = 0.0;
int fullNbSeg = 0; int fullNbSeg = 0;
@ -3492,7 +3792,7 @@ void NETGENPlugin_Mesher::toPython( const netgen::Mesh* ngMesh )
ofstream outfile( pyFile, ios::out ); ofstream outfile( pyFile, ios::out );
if ( !outfile ) return; if ( !outfile ) return;
outfile << "import SMESH" << endl outfile << "import salome, SMESH" << endl
<< "from salome.smesh import smeshBuilder" << endl << "from salome.smesh import smeshBuilder" << endl
<< "smesh = smeshBuilder.New(salome.myStudy)" << endl << "smesh = smeshBuilder.New(salome.myStudy)" << endl
<< "mesh = smesh.Mesh()" << endl << endl; << "mesh = smesh.Mesh()" << endl << endl;
@ -3556,8 +3856,9 @@ void NETGENPlugin_Mesher::toPython( const netgen::Mesh* ngMesh )
*/ */
//================================================================================ //================================================================================
NETGENPlugin_ngMeshInfo::NETGENPlugin_ngMeshInfo( netgen::Mesh* ngMesh): NETGENPlugin_ngMeshInfo::NETGENPlugin_ngMeshInfo( netgen::Mesh* ngMesh,
_copyOfLocalH(0) bool checkRemovedElems):
_elementsRemoved( false ), _copyOfLocalH(0)
{ {
if ( ngMesh ) if ( ngMesh )
{ {
@ -3565,6 +3866,10 @@ NETGENPlugin_ngMeshInfo::NETGENPlugin_ngMeshInfo( netgen::Mesh* ngMesh):
_nbSegments = ngMesh->GetNSeg(); _nbSegments = ngMesh->GetNSeg();
_nbFaces = ngMesh->GetNSE(); _nbFaces = ngMesh->GetNSE();
_nbVolumes = ngMesh->GetNE(); _nbVolumes = ngMesh->GetNE();
if ( checkRemovedElems )
for ( int i = 1; i <= ngMesh->GetNSE() && !_elementsRemoved; ++i )
_elementsRemoved = ngMesh->SurfaceElement(i).IsDeleted();
} }
else else
{ {

View File

@ -46,14 +46,15 @@ namespace nglib {
#include <vector> #include <vector>
#include <set> #include <set>
class NETGENPlugin_Hypothesis;
class NETGENPlugin_Internals;
class NETGENPlugin_SimpleHypothesis_2D;
class SMESHDS_Mesh; class SMESHDS_Mesh;
class SMESH_Comment; class SMESH_Comment;
class SMESH_Mesh; class SMESH_Mesh;
class SMESH_MesherHelper; class SMESH_MesherHelper;
class StdMeshers_ViscousLayers;
class TopoDS_Shape; class TopoDS_Shape;
class NETGENPlugin_Hypothesis;
class NETGENPlugin_SimpleHypothesis_2D;
class NETGENPlugin_Internals;
namespace netgen { namespace netgen {
class OCCGeometry; class OCCGeometry;
class Mesh; class Mesh;
@ -66,9 +67,10 @@ namespace netgen {
struct NETGENPlugin_ngMeshInfo struct NETGENPlugin_ngMeshInfo
{ {
int _nbNodes, _nbSegments, _nbFaces, _nbVolumes; int _nbNodes, _nbSegments, _nbFaces, _nbVolumes;
bool _elementsRemoved; // case where netgen can remove free nodes
char* _copyOfLocalH; char* _copyOfLocalH;
NETGENPlugin_ngMeshInfo( netgen::Mesh* ngMesh=0); NETGENPlugin_ngMeshInfo( netgen::Mesh* ngMesh=0, bool checkRemovedElems=false );
void transferLocalH( netgen::Mesh* fromMesh, netgen::Mesh* toMesh ); void transferLocalH( netgen::Mesh* fromMesh, netgen::Mesh* toMesh );
void restoreLocalH ( netgen::Mesh* ngMesh); void restoreLocalH ( netgen::Mesh* ngMesh);
}; };
@ -120,7 +122,10 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Mesher
void SetParameters(const NETGENPlugin_Hypothesis* hyp); void SetParameters(const NETGENPlugin_Hypothesis* hyp);
void SetParameters(const NETGENPlugin_SimpleHypothesis_2D* hyp); void SetParameters(const NETGENPlugin_SimpleHypothesis_2D* hyp);
void SetParameters(const StdMeshers_ViscousLayers* hyp );
void SetViscousLayers2DAssigned(bool isAssigned) { _isViscousLayers2D = isAssigned; } void SetViscousLayers2DAssigned(bool isAssigned) { _isViscousLayers2D = isAssigned; }
void SetLocalSizeForChordalError( netgen::OCCGeometry& occgeo, netgen::Mesh& ngMesh );
static void SetLocalSize( netgen::OCCGeometry& occgeo, netgen::Mesh& ngMesh ); static void SetLocalSize( netgen::OCCGeometry& occgeo, netgen::Mesh& ngMesh );
bool Compute(); bool Compute();
@ -201,6 +206,7 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Mesher
bool _optimize; bool _optimize;
int _fineness; int _fineness;
bool _isViscousLayers2D; bool _isViscousLayers2D;
double _chordalError;
netgen::Mesh* _ngMesh; netgen::Mesh* _ngMesh;
netgen::OCCGeometry* _occgeom; netgen::OCCGeometry* _occgeom;
@ -210,6 +216,7 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Mesher
volatile double _totalTime; volatile double _totalTime;
const NETGENPlugin_SimpleHypothesis_2D * _simpleHyp; const NETGENPlugin_SimpleHypothesis_2D * _simpleHyp;
const StdMeshers_ViscousLayers* _viscousLayersHyp;
// a pointer to NETGENPlugin_Mesher* field of the holder, that will be // a pointer to NETGENPlugin_Mesher* field of the holder, that will be
// nullified at destruction of this // nullified at destruction of this

View File

@ -319,6 +319,7 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh,
// set local size defined on shapes // set local size defined on shapes
aMesher.SetLocalSize( occgeoComm, *ngMeshes[0] ); aMesher.SetLocalSize( occgeoComm, *ngMeshes[0] );
aMesher.SetLocalSizeForChordalError( occgeoComm, *ngMeshes[0] );
try { try {
ngMeshes[0]->LoadLocalMeshSize( mparam.meshsizefilename ); ngMeshes[0]->LoadLocalMeshSize( mparam.meshsizefilename );
} catch (NgException & ex) { } catch (NgException & ex) {
@ -460,6 +461,7 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh,
bb.Increase (bb.Diam()/10); bb.Increase (bb.Diam()/10);
ngMesh->SetLocalH (bb.PMin(), bb.PMax(), mparam.grading); ngMesh->SetLocalH (bb.PMin(), bb.PMax(), mparam.grading);
aMesher.SetLocalSize( occgeom, *ngMesh ); aMesher.SetLocalSize( occgeom, *ngMesh );
aMesher.SetLocalSizeForChordalError( occgeoComm, *ngMesh );
try { try {
ngMesh->LoadLocalMeshSize( mparam.meshsizefilename ); ngMesh->LoadLocalMeshSize( mparam.meshsizefilename );
} catch (NgException & ex) { } catch (NgException & ex) {