22834: [CEA 1347] Viscous layers: be able to choose the extrusion method

This commit is contained in:
eap 2015-02-10 14:14:01 +03:00
parent 02685fae6f
commit 146533380d
23 changed files with 1539 additions and 1183 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -75,12 +75,29 @@ computations.
\image html viscous_layers_hyp.png
\image html viscous_layers_2d_hyp.png
<ul>
<li><b>Name</b> - allows to define the name of the hypothesis.</li>
<li><b>Total thickness</b> - gives the total thickness of element layers.</li>
<li><b>Number of layers</b> - defines the number of element layers.</li>
<li><b>Stretch factor</b> - defines the growth factor of element height
from the mesh boundary inwards.</li>
<li><b>Extrusion method</b> (available in 3D only) - defines how
position of nodes are found during prism construction and how
creation of distorted and intersecting prisms is prevented.
<ul><li><b>Surface offset + smooth</b> method extrudes nodes along normal
to underlying geometrical surface. Smoothing of internal surface of
element layers is possible to avoid creation of invalid prisms.</li>
<li><b>Face offset</b> method extrudes nodes along average normal of
surrounding mesh faces till intersection with a neighbor mesh face
translated along its own normal by the layers thickness. Thickness
of layers can be limited to avoid creation of invalid prisms.</li>
<li><b>Node offset</b> method extrudes nodes along average normal of
surrounding mesh faces by the layers thickness. Thickness of
layers can be limited to avoid creation of invalid prisms.</li>
\image html viscous_layers_extrusion_method.png "Prisms created by the tree extrusion methods at the same other parameters"
</ul></li>
<li><b>Specified Faces/Edges are</b> - defines how the shapes specified by
the next parameter are used.
<li><b> Faces/Edges with/without layers</b> -
@ -90,11 +107,15 @@ computations.
Faces (or edges) can be selected either in the Object Browser or in
the VTK Viewer.
\note A mesh shown in the 3D Viewer can prevent selection of faces
and edges, just hide the mesh to avoid this. To avoid a long wait when a
and edges, just hide the mesh to avoid this. Sometimes a face to
select is hidden by other faces, in this case consider creating a
group of faces you want to select in the Geometry module.<br>
To avoid a long wait when a
geometry with many faces (or edges) is displayed, the number of faces
(edges) shown at a time is limited by the value of "Sub-shapes
preview chunk size" preference (in Preferences/Mesh/General tab).
If faces/edges without layers are specified, the element layers are
not constructed on geometrical faces shared by several solids in 3D
case and edges shared by several faces in 2D case. In other words,

View File

@ -857,6 +857,21 @@ module StdMeshers
void GetCopySourceMesh(out boolean toCopyMesh,out boolean toCopyGroups);
};
/*!
* Method of computing translation of a node at Viscous Layers construction
*/
enum VLExtrusionMethod {
// node is translated along normal to a surface with possible further smoothing
SURF_OFFSET_SMOOTH,
// node is translated along the average normal of surrounding faces till
// intersection with a neighbor face translated along its own normal
// by the layers thickness
FACE_OFFSET,
// node is translated along the average normal of surrounding faces
// by the layers thickness
NODE_OFFSET
};
/*!
* interface of "Viscous Layers" hypothesis.
* This hypothesis specifies parameters of layers of prisms to build
@ -896,6 +911,9 @@ module StdMeshers
*/
void SetStretchFactor(in double factor) raises (SALOME::SALOME_Exception);
double GetStretchFactor();
void SetMethod( in VLExtrusionMethod how );
VLExtrusionMethod GetMethod();
};
/*!

View File

@ -215,6 +215,9 @@ SET(SMESH_RESOURCES_FILES
mesh_measure_length.png
mesh_measure_area.png
mesh_measure_volume.png
mesh_extmeth_node_offset.png
mesh_extmeth_surf_offset_smooth.png
mesh_extmeth_face_offset.png
)
INSTALL(FILES ${SMESH_RESOURCES_FILES} DESTINATION ${SALOME_SMESH_INSTALL_RES_DATA})

View File

@ -321,7 +321,7 @@
dim ="3">
<python-wrap>
<algo>Hexa_3D=Hexahedron(algo=smeshBuilder.Hexa)</algo>
<hypo>ViscousLayers=ViscousLayers(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetIgnoreFaces())</hypo>
<hypo>ViscousLayers=ViscousLayers(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetFaces(1),SetFaces(2),SetMethod())</hypo>
</python-wrap>
</algorithm>

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 B

View File

@ -566,7 +566,7 @@ bool SMESH_Algo::IsStraight( const TopoDS_Edge & E,
if ( v1Len < std::numeric_limits< double >::min() )
return false; // E seems closed
const double tol = Min( 10 * curve.Tolerance(), v1Len * 1e-2 );
const int nbSamples = 7;
const double nbSamples = 7;
for ( int i = 0; i < nbSamples; ++i )
{
const double r = ( i + 1 ) / nbSamples;

View File

@ -2777,7 +2777,7 @@ void _pyHypothesis::Process( const Handle(_pyCommand)& theCommand)
myArgCommands.push_back( theCommand );
usedCommand = true;
while ( crMethod.myArgs.size() < i+1 )
crMethod.myArgs.push_back( "[]" );
crMethod.myArgs.push_back( "None" );
crMethod.myArgs[ i ] = theCommand->GetArg( crMethod.myArgNb[i] );
}
}

View File

@ -43,8 +43,9 @@ QUADRANGLE = "Quadrangle_2D"
## Algorithm type: Radial Quadrangle 1D-2D algorithm, see StdMeshersBuilder_RadialQuadrangle1D2D
RADIAL_QUAD = "RadialQuadrangle_1D2D"
# import items of enum QuadType
# import items of enums
for e in StdMeshers.QuadType._items: exec('%s = StdMeshers.%s'%(e,e))
for e in StdMeshers.VLExtrusionMethod._items: exec('%s = StdMeshers.%s'%(e,e))
#----------------------
# Algorithms

View File

@ -23,7 +23,7 @@
import salome
from salome.geom import geomBuilder
import SMESH
import SMESH, StdMeshers
## The base class to define meshing algorithms
#
@ -266,9 +266,22 @@ class Mesh_Algorithm:
# the value of \a isFacesToIgnore parameter.
# @param isFacesToIgnore if \c True, the Viscous layers are not generated on the
# faces specified by the previous parameter (\a faces).
# @param extrMethod extrusion method defines how position of nodes are found during
# prism construction and how creation of distorted and intersecting prisms is
# prevented. Possible values are:
# - StdMeshers.SURF_OFFSET_SMOOTH (default) method extrudes nodes along normal
# to underlying geometrical surface. Smoothing of internal surface of
# element layers can be used to avoid creation of invalid prisms.
# - StdMeshers.FACE_OFFSET method extrudes nodes along average normal of
# surrounding mesh faces till intersection with a neighbor mesh face
# translated along its own normal by the layers thickness. Thickness
# of layers can be limited to avoid creation of invalid prisms.
# - StdMeshers.NODE_OFFSET method extrudes nodes along average normal of
# surrounding mesh faces by the layers thickness. Thickness of
# layers can be limited to avoid creation of invalid prisms.
# @ingroup l3_hypos_additi
def ViscousLayers(self, thickness, numberOfLayers, stretchFactor,
faces=[], isFacesToIgnore=True ):
faces=[], isFacesToIgnore=True, extrMethod=StdMeshers.SURF_OFFSET_SMOOTH ):
if not isinstance(self.algo, SMESH._objref_SMESH_3D_Algo):
raise TypeError, "ViscousLayers are supported by 3D algorithms only"
if not "ViscousLayers" in self.GetCompatibleHypothesis():
@ -285,10 +298,11 @@ class Mesh_Algorithm:
hyp = self.Hypothesis("ViscousLayers",
[thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore],
toAdd=False)
hyp.SetTotalThickness(thickness)
hyp.SetNumberLayers(numberOfLayers)
hyp.SetStretchFactor(stretchFactor)
hyp.SetFaces(faces, isFacesToIgnore)
hyp.SetTotalThickness( thickness )
hyp.SetNumberLayers( numberOfLayers )
hyp.SetStretchFactor( stretchFactor )
hyp.SetFaces( faces, isFacesToIgnore )
hyp.SetMethod( extrMethod )
self.mesh.AddHypothesis( hyp, self.geom )
return hyp

File diff suppressed because it is too large Load Diff

View File

@ -42,29 +42,44 @@ public:
// Set boundary shapes (faces in 3D, edges in 2D) either to exclude from
// treatment or to make the Viscous Layers on
void SetBndShapes(const std::vector<int>& shapeIds, bool toIgnore);
void SetBndShapes(const std::vector<int>& shapeIds, bool toIgnore);
std::vector<int> GetBndShapes() const { return _shapeIds; }
bool IsToIgnoreShapes() const { return _isToIgnoreShapes; }
bool IsToIgnoreShapes() const { return _isToIgnoreShapes; }
// Set total thickness of layers of prisms
void SetTotalThickness(double thickness);
void SetTotalThickness(double thickness);
double GetTotalThickness() const { return _thickness; }
// Set number of layers of prisms
void SetNumberLayers(int nb);
int GetNumberLayers() const { return _nbLayers; }
void SetNumberLayers(int nb);
int GetNumberLayers() const { return _nbLayers; }
// Set factor (>1.0) of growth of layer thickness towards inside of mesh
void SetStretchFactor(double factor);
void SetStretchFactor(double factor);
double GetStretchFactor() const { return _stretchFactor; }
// Method of computing node translation
enum ExtrusionMethod {
// node is translated along normal to a surface with possible further smoothing
SURF_OFFSET_SMOOTH,
// node is translated along the average normal of surrounding faces till
// intersection with a neighbor face translated along its own normal
// by the layers thickness
FACE_OFFSET,
// node is translated along the average normal of surrounding faces
// by the layers thickness
NODE_OFFSET
};
void SetMethod( ExtrusionMethod how );
ExtrusionMethod GetMethod() const { return _method; }
// Computes temporary 2D mesh to be used by 3D algorithm.
// Return SMESH_ProxyMesh for each SOLID in theShape
SMESH_ProxyMesh::Ptr Compute(SMESH_Mesh& theMesh,
const TopoDS_Shape& theShape,
const bool toMakeN2NMap=false) const;
// Checks compatibility of assigned StdMeshers_ViscousLayers hypotheses
// Checks compatibility of assigned StdMeshers_ViscousLayers hypotheses
static SMESH_ComputeErrorPtr
CheckHypothesis(SMESH_Mesh& aMesh,
const TopoDS_Shape& aShape,
@ -81,8 +96,6 @@ public:
* \param theMesh - the built mesh
* \param theShape - the geometry of interest
* \retval bool - true if parameter values have been successfully defined
*
* Just return false as this hypothesis does not have parameters values
*/
virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape);
@ -102,6 +115,7 @@ public:
int _nbLayers;
double _thickness;
double _stretchFactor;
ExtrusionMethod _method;
};
class SMESH_subMesh;

View File

@ -18,7 +18,12 @@
//
#include "StdMeshersGUI_RadioButtonsGrpWdg.h"
#include <QVBoxLayout>
#include "SMESHGUI.h"
#include <SUIT_ResourceMgr.h>
#include <QGridLayout>
#include <QLabel>
#include <QRadioButton>
#include <QButtonGroup>
#include <QStringList>
@ -44,17 +49,28 @@ StdMeshersGUI_RadioButtonsGrpWdg::StdMeshersGUI_RadioButtonsGrpWdg( const QStrin
*/
//================================================================================
void StdMeshersGUI_RadioButtonsGrpWdg::setButtonLabels( const QStringList& buttonLabels )
void StdMeshersGUI_RadioButtonsGrpWdg::setButtonLabels( const QStringList& buttonLabels,
const QStringList& buttonIcons )
{
QVBoxLayout* layout = new QVBoxLayout( this );
QGridLayout* layout = new QGridLayout( this );
layout->setSpacing(SPACING);
layout->setMargin(MARGIN);
for ( int id = 0; id < buttonLabels.size(); ++id )
{
QRadioButton* button = new QRadioButton( buttonLabels.at(id), this );
layout->addWidget( button );
layout->addWidget( button, id, 0 );
myButtonGrp->addButton( button, id );
if ( id < buttonIcons.count() )
{
QPixmap pmi (SMESHGUI::resourceMgr()->loadPixmap("SMESH", buttonIcons.at(id)));
if ( !pmi.isNull() ) {
QLabel* pixLabel = new QLabel( this );
pixLabel->setPixmap( pmi );
layout->addWidget( pixLabel, id, 1 );
}
}
}
}

View File

@ -38,7 +38,8 @@ class STDMESHERSGUI_EXPORT StdMeshersGUI_RadioButtonsGrpWdg : public QGroupBox
public:
StdMeshersGUI_RadioButtonsGrpWdg (const QString& title);
void setButtonLabels( const QStringList& buttonLabels );
void setButtonLabels( const QStringList& buttonLabels,
const QStringList& buttonIcons=QStringList());
void setChecked(int id);

View File

@ -714,17 +714,18 @@ QString StdMeshersGUI_StdHypothesisCreator::storeParams() const
StdMeshers::StdMeshers_ViscousLayers_var h =
StdMeshers::StdMeshers_ViscousLayers::_narrow( hypothesis() );
h->SetVarParameter( params[0].text(), "SetTotalThickness" );
h->SetVarParameter ( params[0].text(), "SetTotalThickness" );
h->SetTotalThickness( params[0].myValue.toDouble() );
h->SetVarParameter( params[1].text(), "SetNumberLayers" );
h->SetVarParameter ( params[1].text(), "SetNumberLayers" );
h->SetNumberLayers ( params[1].myValue.toInt() );
h->SetVarParameter( params[2].text(), "SetStretchFactor" );
h->SetVarParameter ( params[2].text(), "SetStretchFactor" );
h->SetStretchFactor ( params[2].myValue.toDouble() );
h->SetMethod (( StdMeshers::VLExtrusionMethod ) params[3].myValue.toInt() );
if ( StdMeshersGUI_SubShapeSelectorWdg* idsWg =
widget< StdMeshersGUI_SubShapeSelectorWdg >( 4 ))
if ( StdMeshersGUI_SubShapeSelectorWdg* idsWg =
widget< StdMeshersGUI_SubShapeSelectorWdg >( 5 ))
{
h->SetFaces( idsWg->GetListOfIDs(), params[3].myValue.toInt() );
h->SetFaces( idsWg->GetListOfIDs(), params[4].myValue.toInt() );
}
}
else if( hypType()=="ViscousLayers2D" )
@ -732,11 +733,11 @@ QString StdMeshersGUI_StdHypothesisCreator::storeParams() const
StdMeshers::StdMeshers_ViscousLayers2D_var h =
StdMeshers::StdMeshers_ViscousLayers2D::_narrow( hypothesis() );
h->SetVarParameter( params[0].text(), "SetTotalThickness" );
h->SetVarParameter ( params[0].text(), "SetTotalThickness" );
h->SetTotalThickness( params[0].myValue.toDouble() );
h->SetVarParameter( params[1].text(), "SetNumberLayers" );
h->SetVarParameter ( params[1].text(), "SetNumberLayers" );
h->SetNumberLayers ( params[1].myValue.toInt() );
h->SetVarParameter( params[2].text(), "SetStretchFactor" );
h->SetVarParameter ( params[2].text(), "SetStretchFactor" );
h->SetStretchFactor ( params[2].myValue.toDouble() );
if ( StdMeshersGUI_SubShapeSelectorWdg* idsWg =
@ -1242,6 +1243,20 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const
p.append( item );
customWidgets()->append (0);
item.myName = tr( "EXTRUSION_METHOD" );
p.append( item );
StdMeshersGUI_RadioButtonsGrpWdg* methodWdg = new StdMeshersGUI_RadioButtonsGrpWdg("");
methodWdg->setButtonLabels ( QStringList()
<< tr("EXTMETH_SURF_OFFSET_SMOOTH")
<< tr("EXTMETH_FACE_OFFSET")
<< tr("EXTMETH_NODE_OFFSET"),
QStringList()
<< tr("ICON_EXTMETH_SURF_OFFSET_SMOOTH")
<< tr("ICON_EXTMETH_FACE_OFFSET")
<< tr("ICON_EXTMETH_NODE_OFFSET"));
methodWdg->setChecked( (int) h->GetMethod() );
customWidgets()->append( methodWdg );
QString aMainEntry = SMESHGUI_GenericHypothesisCreator::getMainShapeEntry();
QString aSubEntry = SMESHGUI_GenericHypothesisCreator::getShapeEntry();
if ( !aMainEntry.isEmpty() )

View File

@ -283,4 +283,19 @@
<translation>mesh_quadrangle_reduced.png</translation>
</message>
</context>
<context>
<name>StdMeshersGUI_StdHypothesisCreator</name>
<message>
<source>ICON_EXTMETH_SURF_OFFSET_SMOOTH</source>
<translation>mesh_extmeth_surf_offset_smooth.png</translation>
</message>
<message>
<source>ICON_EXTMETH_NODE_OFFSET</source>
<translation>mesh_extmeth_node_offset.png</translation>
</message>
<message>
<source>ICON_EXTMETH_FACE_OFFSET</source>
<translation>mesh_extmeth_face_offset.png</translation>
</message>
</context>
</TS>

View File

@ -43,6 +43,22 @@ mesh/sub-mesh.
Consider creating another hypothesis instead of using
this one for this mesh/sub-mesh.</translation>
</message>
<message>
<source>EXTMETH_SURF_OFFSET_SMOOTH</source>
<translation>Surface offset + smooth</translation>
</message>
<message>
<source>EXTRUSION_METHOD</source>
<translation>Extrusion method</translation>
</message>
<message>
<source>EXTMETH_NODE_OFFSET</source>
<translation>Node offset</translation>
</message>
<message>
<source>EXTMETH_FACE_OFFSET</source>
<translation>Face offset</translation>
</message>
</context>
<context>
<name>@default</name>

View File

@ -230,6 +230,33 @@ throw ( SALOME::SALOME_Exception )
return GetImpl()->GetStretchFactor();
}
//================================================================================
/*!
* \brief Set Method of computing translation of a node
*/
//================================================================================
void StdMeshers_ViscousLayers_i::SetMethod( ::StdMeshers::VLExtrusionMethod how )
{
GetImpl()->SetMethod( ::StdMeshers_ViscousLayers::ExtrusionMethod( how ));
const char* methNames[3] = { "SURF_OFFSET_SMOOTH",
"FACE_OFFSET",
"NODE_OFFSET" };
if ( how >= 0 && how < 3 )
SMESH::TPythonDump() << _this() << ".SetMethod( StdMeshers." << methNames[ how ]<< " )";
}
//================================================================================
/*!
* \brief Return Method of computing translation of a node
*/
//================================================================================
::StdMeshers::VLExtrusionMethod StdMeshers_ViscousLayers_i::GetMethod()
{
return (::StdMeshers::VLExtrusionMethod) GetImpl()->GetMethod();
}
//=============================================================================
/*!
* Get implementation

View File

@ -65,6 +65,9 @@ class STDMESHERS_I_EXPORT StdMeshers_ViscousLayers_i:
void SetStretchFactor(::CORBA::Double factor) throw ( SALOME::SALOME_Exception );
::CORBA::Double GetStretchFactor();
void SetMethod( ::StdMeshers::VLExtrusionMethod how );
::StdMeshers::VLExtrusionMethod GetMethod();
// Get implementation
::StdMeshers_ViscousLayers* GetImpl();