#17237: Body fitting on sub-mesh, #16523: Treatment of internal faces

This commit is contained in:
eap 2020-02-05 14:58:45 +03:00
parent 66ec81f68d
commit 650885c135
17 changed files with 2306 additions and 323 deletions

View File

@ -14,10 +14,13 @@ smesh = smeshBuilder.New()
# create a sphere
sphere = geompy.MakeSphereR( 50 )
geompy.addToStudy( sphere, "sphere" )
# cut the sphere by a box
box = geompy.MakeBoxDXDYDZ( 100, 100, 100 )
partition = geompy.MakePartition([ sphere ], [ box ], theName="partition")
# create a mesh and assign a "Body Fitting" algo
mesh = smesh.Mesh( sphere )
mesh = smesh.Mesh( partition )
cartAlgo = mesh.BodyFitted()
# define a cartesian grid using Coordinates
@ -38,7 +41,27 @@ mesh.Compute()
print("nb hexahedra",mesh.NbHexas())
print("nb tetrahedra",mesh.NbTetras())
print("nb polyhedra",mesh.NbPolyhedrons())
print("nb faces",mesh.NbFaces())
print()
# activate creation of faces
cartHyp.SetToCreateFaces( True )
mesh.Compute()
print("nb hexahedra",mesh.NbHexas())
print("nb tetrahedra",mesh.NbTetras())
print("nb polyhedra",mesh.NbPolyhedrons())
print("nb faces",mesh.NbFaces())
print()
# enable consideration of shared faces
cartHyp.SetToConsiderInternalFaces( True )
mesh.Compute()
print("nb hexahedra",mesh.NbHexas())
print("nb tetrahedra",mesh.NbTetras())
print("nb polyhedra",mesh.NbPolyhedrons())
print("nb faces",mesh.NbFaces())
print()
# define the grid by setting different spacing in 2 sub-ranges of geometry
spaceFuns = ["5","10+10*t"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -52,6 +52,9 @@ This dialog allows to define
.. centered::
Implement Edges switched off to the left and on to the right
* **Create Faces** check-box activates creation on mesh faces.
* **Consider Shared and Internal Faces** check-box activates treatment of faces shared by solids and internal. By default the algorithm considers only outer boundaries of the geometry.
* **Apply Threshold to Shared / Internal Faces** check-box activates application of **Threshold** to cells cut by shared and internal faces, that can cause appearance of holes inside the mesh.
* **Definition mode** allows choosing how Cartesian structured grid is defined. Location of nodes along each grid axis is defined individually:
* You can specify the **Coordinates** of grid nodes. **Insert** button inserts a node at **Step** distance (negative or positive) from the selected node. **Delete** button removes the selected node. Double click on a coordinate in the list enables its edition. **Note** that node coordinates are measured along directions of axes that can differ from the directions of the Global Coordinate System.

View File

@ -1037,7 +1037,7 @@ module StdMeshers
boolean GetFixedPoint(out SMESH::PointStruct p);
/*!
* Enables implementation of geometrical edges into the mesh. If this feature
* Enable implementation of geometrical edges into the mesh. If this feature
* is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
* they don't coincide with the grid lines
*/
@ -1045,17 +1045,35 @@ module StdMeshers
boolean GetToAddEdges();
/*!
* Returns axes at which a number of generated hexahedra is maximal
* Enable treatment of geom faces, either shared by solids or internal.
*/
void SetToConsiderInternalFaces(in boolean toTreat);
boolean GetToConsiderInternalFaces();
/*!
* Enable applying size threshold to grid cells cut by internal geom faces.
*/
void SetToUseThresholdForInternalFaces(in boolean toUse);
boolean GetToUseThresholdForInternalFaces();
/*!
* Enable creation of mesh faces.
*/
void SetToCreateFaces(in boolean toCreate);
boolean GetToCreateFaces();
/*!
* Return axes at which a number of generated hexahedra is maximal
*/
void ComputeOptimalAxesDirs(in GEOM::GEOM_Object shape,
in boolean isOrthogonal,
out SMESH::DirStruct x,
out SMESH::DirStruct y,
out SMESH::DirStruct z )
out SMESH::DirStruct z )
raises (SALOME::SALOME_Exception);
/*!
* \brief Computes node coordinates by spacing functions
* \brief Compute node coordinates by spacing functions
* \param x0 - lower coordinate
* \param x1 - upper coordinate
* \param spaceFuns - space functions

View File

@ -224,7 +224,6 @@
<hypothesis type ="CartesianParameters3D"
label-id ="Body Fitting Parameters"
icon-id ="mesh_hypo_length.png"
context ="GLOBAL"
dim ="3"/>
</hypotheses>
@ -570,7 +569,6 @@
support-submeshes="false"
output ="HEXA"
need-hyp ="true"
context ="GLOBAL"
dim ="3">
<python-wrap>
<algo>Cartesian_3D=BodyFitted()</algo>

View File

@ -4262,6 +4262,7 @@ private:
bool isOutOfFace (const gp_Pnt& p);
bool isOutOfEdge (const gp_Pnt& p);
bool isOutOfVertex(const gp_Pnt& p);
bool isOutOfNone (const gp_Pnt& p) { return true; }
bool isBox (const TopoDS_Shape& s);
bool (Classifier::* myIsOutFun)(const gp_Pnt& p);
@ -4583,7 +4584,7 @@ bool ElementsOnShape::IsSatisfy (const SMDS_MeshNode* node,
{
isNodeOut = false;
if ( okShape )
*okShape = myWorkClassifiers[i]->Shape();
*okShape = myClassifiers[i].Shape();
break;
}
}
@ -4621,17 +4622,27 @@ void ElementsOnShape::Classifier::Init( const TopoDS_Shape& theShape,
{
Standard_Real u1,u2,v1,v2;
Handle(Geom_Surface) surf = BRep_Tool::Surface( TopoDS::Face( theShape ));
surf->Bounds( u1,u2,v1,v2 );
myProjFace.Init(surf, u1,u2, v1,v2, myTol );
myIsOutFun = & ElementsOnShape::Classifier::isOutOfFace;
if ( surf.IsNull() )
myIsOutFun = & ElementsOnShape::Classifier::isOutOfNone;
else
{
surf->Bounds( u1,u2,v1,v2 );
myProjFace.Init(surf, u1,u2, v1,v2, myTol );
myIsOutFun = & ElementsOnShape::Classifier::isOutOfFace;
}
break;
}
case TopAbs_EDGE:
{
Standard_Real u1, u2;
Handle(Geom_Curve) curve = BRep_Tool::Curve( TopoDS::Edge( theShape ), u1, u2);
myProjEdge.Init(curve, u1, u2);
myIsOutFun = & ElementsOnShape::Classifier::isOutOfEdge;
if ( curve.IsNull() )
myIsOutFun = & ElementsOnShape::Classifier::isOutOfNone;
else
{
myProjEdge.Init(curve, u1, u2);
myIsOutFun = & ElementsOnShape::Classifier::isOutOfEdge;
}
break;
}
case TopAbs_VERTEX:

View File

@ -161,8 +161,7 @@ SMESH_MeshEditor::ElemFeatures::Init( const SMDS_MeshElement* elem, bool basicOn
myIsQuad = elem->IsQuadratic();
if ( myType == SMDSAbs_Volume && !basicOnly )
{
vector<int> quant = static_cast<const SMDS_MeshVolume* >( elem )->GetQuantities();
myPolyhedQuantities.swap( quant );
myPolyhedQuantities = static_cast<const SMDS_MeshVolume* >( elem )->GetQuantities();
}
}
}

View File

@ -115,9 +115,12 @@ void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * elem)
(LOCALIZED("add element in subshape already belonging to a subshape"));
}
}
else
{
++myNbElements;
}
elem->setShapeID( myIndex );
myNbElements++;
// remember element with smallest ID to optimize iteration on them
add( elem );
@ -178,8 +181,11 @@ void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
(LOCALIZED("a node being in sub-mesh is added to another sub-mesh"));
return; // already in
}
else
{
++myNbNodes;
}
N->setShapeID( myIndex );
myNbNodes++;
// remember node with smallest ID to optimize iteration on them
add( N );

View File

@ -813,8 +813,8 @@ HypothesesSet::HypothesesSet( const QString& theSetName,
: myUseCommonSize( useCommonSize ),
myQuadDominated( isQuadDominated ),
myHypoSetName( theSetName ),
myHypoList { mainHypos, altHypos, intHypos },
myAlgoList { mainAlgos, altAlgos, intAlgos },
myHypoList { mainHypos, altHypos, intHypos },
myAlgoList { mainAlgos, altAlgos, intAlgos },
myIsAlgo( false ),
myIsCustom( false ),
myIndex( 0 )

View File

@ -64,7 +64,10 @@ StdMeshers_CartesianParameters3D::StdMeshers_CartesianParameters3D(int h
SMESH_Gen * gen)
: SMESH_Hypothesis(hypId, gen),
_sizeThreshold( 4.0 ), // default according to the customer specification
_toAddEdges( false )
_toAddEdges( false ),
_toConsiderInternalFaces( false ),
_toUseThresholdForInternalFaces( false ),
_toCreateFaces( false )
{
_name = "CartesianParameters3D"; // used by "Cartesian_3D"
_param_algo_dim = 3; // 3D
@ -739,6 +742,48 @@ bool StdMeshers_CartesianParameters3D::GetToAddEdges() const
return _toAddEdges;
}
//=======================================================================
//function : SetToConsiderInternalFaces
//purpose : Enables treatment of geom faces either shared by solids or internal
//=======================================================================
void StdMeshers_CartesianParameters3D::SetToConsiderInternalFaces(bool toTreat)
{
if ( _toConsiderInternalFaces != toTreat )
{
_toConsiderInternalFaces = toTreat;
NotifySubMeshesHypothesisModification();
}
}
//=======================================================================
//function : SetToUseThresholdForInternalFaces
//purpose : Enables applying size threshold to grid cells cut by internal geom faces.
//=======================================================================
void StdMeshers_CartesianParameters3D::SetToUseThresholdForInternalFaces(bool toUse)
{
if ( _toUseThresholdForInternalFaces != toUse )
{
_toUseThresholdForInternalFaces = toUse;
NotifySubMeshesHypothesisModification();
}
}
//=======================================================================
//function : SetToCreateFaces
//purpose : Enables creation of mesh faces.
//=======================================================================
void StdMeshers_CartesianParameters3D::SetToCreateFaces(bool toCreate)
{
if ( _toCreateFaces != toCreate )
{
_toCreateFaces = toCreate;
NotifySubMeshesHypothesisModification();
}
}
//=======================================================================
//function : IsDefined
//purpose : Return true if parameters are well defined
@ -786,6 +831,10 @@ std::ostream & StdMeshers_CartesianParameters3D::SaveTo(std::ostream & save)
for ( int i = 0; i < 3; ++i )
save << _fixedPoint[i] << " ";
save << " " << _toConsiderInternalFaces
<< " " << _toUseThresholdForInternalFaces
<< " " << _toCreateFaces;
return save;
}
@ -844,6 +893,12 @@ std::istream & StdMeshers_CartesianParameters3D::LoadFrom(std::istream & load)
for ( int i = 0; i < 3 && ok ; ++i )
ok = static_cast<bool>( load >> _fixedPoint[i]);
if ( load >> _toConsiderInternalFaces )
{
load >> _toUseThresholdForInternalFaces;
load >> _toCreateFaces;
}
return load;
}

View File

@ -139,6 +139,25 @@ public:
void SetToAddEdges(bool toAdd);
bool GetToAddEdges() const;
/*!
* \brief Enables treatment of geom faces either shared by solids or internal.
*/
void SetToConsiderInternalFaces(bool toTreat);
bool GetToConsiderInternalFaces() const { return _toConsiderInternalFaces; }
/*!
* \brief Enables applying size threshold to grid cells cut by internal geom faces.
*/
void SetToUseThresholdForInternalFaces(bool toUse);
bool GetToUseThresholdForInternalFaces() const { return _toUseThresholdForInternalFaces; }
/*!
* \brief Enables creation of mesh faces.
*/
void SetToCreateFaces(bool toCreate);
bool GetToCreateFaces() const { return _toCreateFaces; }
/*!
* \brief Return true if parameters are well defined
*/
@ -171,6 +190,9 @@ public:
double _sizeThreshold;
bool _toAddEdges;
bool _toConsiderInternalFaces;
bool _toUseThresholdForInternalFaces;
bool _toCreateFaces;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -204,8 +204,8 @@ namespace StdMeshersGUI
axisTabLayout->setSpacing( SPACING );
axisTabLayout->addWidget( modeBox , 0, 0, 1, 3 );
axisTabLayout->addWidget( myInsertBtn , 1, 0, 1, 2 );
axisTabLayout->addWidget( myDeleteBtn , 2, 0, 1, 2 );
axisTabLayout->addWidget( myInsertBtn, 1, 0, 1, 2 );
axisTabLayout->addWidget( myDeleteBtn, 2, 0, 1, 2 );
axisTabLayout->addWidget( myStepLabel, 3, 0 );
axisTabLayout->addWidget( myStepSpin , 3, 1 );
axisTabLayout->addWidget( csFrame , 1, 2, 4, 1 );
@ -821,6 +821,15 @@ QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame()
myAddEdges = new QCheckBox( tr("ADD_EDGES"), GroupC1 );
argGroupLayout->addWidget( myAddEdges, row, 0, 1, 2 );
row++;
myCreateFaces = new QCheckBox( tr("CREATE_FACES"), GroupC1 );
argGroupLayout->addWidget( myCreateFaces, row, 0, 1, 2 );
row++;
myConsiderInternalFaces = new QCheckBox( tr("CONSIDER_INTERNAL_FACES"), GroupC1 );
argGroupLayout->addWidget( myConsiderInternalFaces, row, 0, 1, 2 );
row++;
myUseThresholdForInternalFaces = new QCheckBox( tr("USE_THRESHOLD_FOR_INTERNAL_FACES"), GroupC1 );
argGroupLayout->addWidget( myUseThresholdForInternalFaces, row, 0, 1, 2 );
row++;
// 3) Grid definition
QTabWidget* tabWdg = new QTabWidget( fr );
@ -924,6 +933,8 @@ QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame()
connect( myOrthogonalChk, SIGNAL( toggled(bool)), SLOT( onOrthogonalAxes(bool)));
connect( optimBtn, SIGNAL( clicked(bool)), SLOT( onOptimalAxes(bool)));
connect( resetBtn, SIGNAL( clicked(bool)), SLOT( onResetAxes(bool)));
connect( myConsiderInternalFaces, SIGNAL( toggled(bool)),
myUseThresholdForInternalFaces, SLOT( setEnabled(bool)));
for ( int i = 0; i < 3; ++i )
{
connect( myXDirSpin[i], SIGNAL(valueChanged (const QString&)),
@ -999,6 +1010,9 @@ void StdMeshersGUI_CartesianParamCreator::retrieveParams() const
myThreshold->setText( varName );
myAddEdges->setChecked( h->GetToAddEdges() );
myCreateFaces->setChecked( h->GetToCreateFaces() );
myConsiderInternalFaces->setChecked( h->GetToConsiderInternalFaces() );
myUseThresholdForInternalFaces->setChecked( h->GetToUseThresholdForInternalFaces() );
// grid definition
for ( int ax = 0; ax < 3; ++ax )
@ -1086,6 +1100,9 @@ QString StdMeshersGUI_CartesianParamCreator::storeParams() const
h->SetVarParameter( myThreshold->text().toLatin1().constData(), "SetSizeThreshold" );
h->SetSizeThreshold( myThreshold->text().toDouble() );
h->SetToAddEdges( myAddEdges->isChecked() );
h->SetToCreateFaces( myCreateFaces->isChecked() );
h->SetToConsiderInternalFaces( myConsiderInternalFaces->isChecked() );
h->SetToUseThresholdForInternalFaces( myUseThresholdForInternalFaces->isChecked() );
// grid
for ( int ax = 0; ax < 3; ++ax )

View File

@ -152,6 +152,9 @@ private:
QLineEdit* myName;
SMESHGUI_SpinBox* myThreshold;
QCheckBox* myAddEdges;
QCheckBox* myCreateFaces;
QCheckBox* myConsiderInternalFaces;
QCheckBox* myUseThresholdForInternalFaces;
StdMeshersGUI::GridAxisTab* myAxisTabs[3];
QGroupBox* myFixedPointGrp;

View File

@ -580,6 +580,18 @@ this one for this mesh/sub-mesh.</translation>
<source>ADD_EDGES</source>
<translation>Implement Edges</translation>
</message>
<message>
<source>CREATE_FACES</source>
<translation>Create Faces</translation>
</message>
<message>
<source>CONSIDER_INTERNAL_FACES</source>
<translation>Consider Shared and Internal Faces</translation>
</message>
<message>
<source>USE_THRESHOLD_FOR_INTERNAL_FACES</source>
<translation>Apply Threshold to Shared / Internal Faces</translation>
</message>
<message>
<source>AXIS_X</source>
<translation>Axis X</translation>

View File

@ -240,6 +240,14 @@ void StdMeshers_CartesianParameters3D_i::SetAxesDirs(const SMESH::DirStruct& xDi
coords[6] = zDir.PS.x;
coords[7] = zDir.PS.y;
coords[8] = zDir.PS.z;
const double* oldCoords = GetImpl()->GetAxisDirs();
bool isSame = true;
for ( int i = 0; i < 9 && isSame; ++i )
isSame = ( oldCoords[i] == coords[i] );
if ( isSame )
return;
try {
this->GetImpl()->SetAxisDirs(coords);
@ -283,6 +291,11 @@ void StdMeshers_CartesianParameters3D_i::GetAxesDirs(SMESH::DirStruct& xDir,
void StdMeshers_CartesianParameters3D_i::SetFixedPoint(const SMESH::PointStruct& ps,
CORBA::Boolean toUnset)
{
SMESH::PointStruct oldPS;
GetFixedPoint( oldPS );
if ( oldPS.x == ps.x && oldPS.y == ps.y && oldPS.z == ps.z )
return;
double p[3] = { ps.x, ps.y, ps.z };
GetImpl()->SetFixedPoint( p, toUnset );
@ -335,6 +348,76 @@ CORBA::Boolean StdMeshers_CartesianParameters3D_i::GetToAddEdges()
return GetImpl()->GetToAddEdges();
}
//=======================================================================
//function : SetToConsiderInternalFaces
//purpose : Enables treatment of geom faces, either shared by solids or internal.
//=======================================================================
void StdMeshers_CartesianParameters3D_i::SetToConsiderInternalFaces(CORBA::Boolean toTreat)
{
if ( GetToConsiderInternalFaces() == toTreat )
return;
GetImpl()->SetToConsiderInternalFaces( toTreat );
SMESH::TPythonDump() << _this() << ".SetToConsiderInternalFaces( " << toTreat << " )";
}
//=======================================================================
//function : GetToConsiderInternalFaces
//purpose : Return true if treatment of internal geom faces is enabled
//=======================================================================
CORBA::Boolean StdMeshers_CartesianParameters3D_i::GetToConsiderInternalFaces()
{
return GetImpl()->GetToConsiderInternalFaces();
}
//=======================================================================
//function : SetToUseThresholdForInternalFaces
//purpose : Enables applying size threshold to grid cells cut by internal geom faces.
//=======================================================================
void StdMeshers_CartesianParameters3D_i::SetToUseThresholdForInternalFaces(CORBA::Boolean toUse)
{
if ( GetToUseThresholdForInternalFaces() == toUse )
return;
GetImpl()->SetToUseThresholdForInternalFaces( toUse );
SMESH::TPythonDump() << _this() << ".SetToUseThresholdForInternalFaces( " << toUse << " )";
}
//=======================================================================
//function : GetToUseThresholdForInternalFaces
//purpose : Return true if applying size threshold to grid cells cut by
// internal geom faces is enabled
//=======================================================================
CORBA::Boolean StdMeshers_CartesianParameters3D_i::GetToUseThresholdForInternalFaces()
{
return GetImpl()->GetToUseThresholdForInternalFaces();
}
//=======================================================================
//function : SetToCreateFaces
//purpose : Enables creation of mesh faces.
//=======================================================================
void StdMeshers_CartesianParameters3D_i::SetToCreateFaces(CORBA::Boolean toCreate)
{
if ( GetToCreateFaces() == toCreate )
return;
GetImpl()->SetToCreateFaces( toCreate );
SMESH::TPythonDump() << _this() << ".SetToCreateFaces( " << toCreate << " )";
}
//=======================================================================
//function : GetToCreateFaces
//purpose : Check if creation of mesh faces enabled
//=======================================================================
CORBA::Boolean StdMeshers_CartesianParameters3D_i::GetToCreateFaces()
{
return GetImpl()->GetToCreateFaces();
}
//=======================================================================
//function : IsGridBySpacing
//purpose : Return true if the grid is defined by spacing functions and

View File

@ -100,7 +100,7 @@ class STDMESHERS_I_EXPORT StdMeshers_CartesianParameters3D_i:
/*!
* \brief Enables implementation of geometrical edges into the mesh. If this feature
* \brief Enable implementation of geometrical edges into the mesh. If this feature
* is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
* they don't coincide with the grid lines
*/
@ -108,13 +108,32 @@ class STDMESHERS_I_EXPORT StdMeshers_CartesianParameters3D_i:
CORBA::Boolean GetToAddEdges();
/*!
* \brief Return true if the grid is defined by spacing functions and
* Enable treatment of geom faces, either shared by solids or internal.
*/
void SetToConsiderInternalFaces(CORBA::Boolean toTreat);
CORBA::Boolean GetToConsiderInternalFaces();
/*!
* Enable applying size threshold to grid cells cut by internal geom faces.
*/
void SetToUseThresholdForInternalFaces(CORBA::Boolean toUse);
CORBA::Boolean GetToUseThresholdForInternalFaces();
/*!
* Enable creation of mesh faces.
*/
void SetToCreateFaces(CORBA::Boolean toCreate);
CORBA::Boolean GetToCreateFaces();
/*!
* \brief Return true if the grid is defined by spacing functions and
* not by node coordinates
*/
CORBA::Boolean IsGridBySpacing(CORBA::Short axis);
/*!
* Returns axes at which number of hexahedra is maximal
* Return axes at which number of hexahedra is maximal
*/
void ComputeOptimalAxesDirs(GEOM::GEOM_Object_ptr shape,
CORBA::Boolean isOrthogonal,
@ -122,7 +141,7 @@ class STDMESHERS_I_EXPORT StdMeshers_CartesianParameters3D_i:
SMESH::DirStruct& y,
SMESH::DirStruct& z) throw (SALOME::SALOME_Exception);
/*!
* \brief Computes node coordinates by spacing functions
* \brief Compute node coordinates by spacing functions
* \param x0 - lower coordinate
* \param x1 - upper coordinate
* \param spaceFuns - space functions