#16648 [CEA] RadialQuadrangle algorithm hypothesis change requires a Clear Mesh Data beforehand

+
1) Optimize FreeEdges::IsFreeEdge()
2) Fix SMESH_MeshEditor::FindFreeBorder() for the case of multi-continuation
3) Improve Mesh.GetLength() to accept groups and list of IDs
This commit is contained in:
eap 2019-03-05 19:35:52 +03:00
parent 385d4cede5
commit d2248790d7
6 changed files with 121 additions and 74 deletions

View File

@ -2565,18 +2565,14 @@ void FreeEdges::SetMesh( const SMDS_Mesh* theMesh )
bool FreeEdges::IsFreeEdge( const SMDS_MeshNode** theNodes, const int theFaceId ) bool FreeEdges::IsFreeEdge( const SMDS_MeshNode** theNodes, const int theFaceId )
{ {
TColStd_MapOfInteger aMap; SMDS_ElemIteratorPtr anElemIter = theNodes[ 0 ]->GetInverseElementIterator(SMDSAbs_Face);
for ( int i = 0; i < 2; i++ ) while( anElemIter->more() )
{ {
SMDS_ElemIteratorPtr anElemIter = theNodes[ i ]->GetInverseElementIterator(SMDSAbs_Face); if ( const SMDS_MeshElement* anElem = anElemIter->next())
while( anElemIter->more() )
{ {
if ( const SMDS_MeshElement* anElem = anElemIter->next()) const int anId = anElem->GetID();
{ if ( anId != theFaceId && anElem->GetNodeIndex( theNodes[1] ) >= 0 )
const int anId = anElem->GetID(); return false;
if ( anId != theFaceId && !aMap.Add( anId ))
return false;
}
} }
} }
return true; return true;

View File

@ -7681,9 +7681,9 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirst
// push_back the best free border // push_back the best free border
cNL = & contNodes[ contNodes[0].empty() ? 1 : 0 ]; cNL = & contNodes[ contNodes[0].empty() ? 1 : 0 ];
cFL = & contFaces[ contFaces[0].empty() ? 1 : 0 ]; cFL = & contFaces[ contFaces[0].empty() ? 1 : 0 ];
theNodes.pop_back(); // remove nIgnore //theNodes.pop_back(); // remove nIgnore
theNodes.pop_back(); // remove nStart theNodes.pop_back(); // remove nStart
theFaces.pop_back(); // remove curElem //theFaces.pop_back(); // remove curElem
theNodes.splice( theNodes.end(), *cNL ); theNodes.splice( theNodes.end(), *cNL );
theFaces.splice( theFaces.end(), *cFL ); theFaces.splice( theFaces.end(), *cFL );
return true; return true;

View File

@ -494,28 +494,37 @@ namespace
<< " in a PolySegment " << iSeg ); << " in a PolySegment " << iSeg );
if ( path.myDot1 == 0. && if ( path.myDot1 == 0. &&
path.myDot2 == 0. && path.myDot2 == 0. )
paths.size() - nbPaths >= 2 ) // use a face non-parallel to the plane
{ {
const SMDS_MeshElement* goodFace = 0; if ( paths.size() - nbPaths >= 2 ) // use a face non-parallel to the plane
for ( size_t j = nbPaths; j < paths.size(); ++j )
{ {
path = paths[j]; const SMDS_MeshElement* goodFace = 0;
if ( path.Extend( plnNorm, plnOrig )) for ( size_t j = nbPaths; j < paths.size(); ++j )
goodFace = paths[j].myFace;
else
paths[j].myFace = 0;
}
if ( !goodFace )
throw SALOME_Exception ( SMESH_Comment("Cant move from point ") << iP+1
<< " of a PolySegment " << iSeg );
for ( size_t j = nbPaths; j < paths.size(); ++j )
if ( !paths[j].myFace )
{ {
paths[j].myFace = goodFace; path = paths[j];
paths[j].myNodeInd1 = goodFace->GetNodeIndex( paths[j].myNode1.Node() ); if ( path.Extend( plnNorm, plnOrig ))
paths[j].myNodeInd2 = goodFace->GetNodeIndex( paths[j].myNode2.Node() ); goodFace = paths[j].myFace;
else
paths[j].myFace = 0;
} }
if ( !goodFace )
throw SALOME_Exception ( SMESH_Comment("Cant move from point ") << iP+1
<< " of a PolySegment " << iSeg );
for ( size_t j = nbPaths; j < paths.size(); ++j )
if ( !paths[j].myFace )
{
paths[j].myFace = goodFace;
paths[j].myNodeInd1 = goodFace->GetNodeIndex( paths[j].myNode1.Node() );
paths[j].myNodeInd2 = goodFace->GetNodeIndex( paths[j].myNode2.Node() );
}
}
else // use the sole found face
{
path = paths.back();
std::swap( path.myNode1, path.myNode2 );
std::swap( path.myNodeInd1, path.myNodeInd2 );
paths.push_back( path );
}
} }
} }

View File

@ -456,7 +456,7 @@ bool SMESH_PreMeshInfo::readPreInfoFromHDF()
mapOfNames ); mapOfNames );
} }
} }
infoHdfGroup->CloseOnDisk(); infoHdfGroup->CloseOnDisk();
} }
aFile->CloseOnDisk(); aFile->CloseOnDisk();
@ -841,8 +841,9 @@ void SMESH_PreMeshInfo::FullLoadFromFile() const
meshDS->Modified(); meshDS->Modified();
// load dependent meshes referring/referred via hypotheses // load dependent meshes referring/referred via hypotheses
mesh.GetSubMesh( mesh.GetShapeToMesh() )-> SMESH_subMesh* mainSub = mesh.GetSubMesh( mesh.GetShapeToMesh() );
ComputeStateEngine (SMESH_subMesh::SUBMESH_LOADED); mainSub->ComputeStateEngine (SMESH_subMesh::SUBMESH_RESTORED); // #16648
mainSub->ComputeStateEngine (SMESH_subMesh::SUBMESH_LOADED);
MYDEBUGOUT( "END FullLoadFromFile()" ); MYDEBUGOUT( "END FullLoadFromFile()" );
} }

View File

@ -1235,8 +1235,6 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
def GetMeshInfo(self, obj): def GetMeshInfo(self, obj):
""" """
Get the mesh statistic. Get the mesh statistic.
Use :meth:`smeshBuilder.EnumToLong` to get an integer from
an item of :class:`SMESH.EntityType`.
Returns: Returns:
dictionary { :class:`SMESH.EntityType` - "count of elements" } dictionary { :class:`SMESH.EntityType` - "count of elements" }
@ -3091,8 +3089,6 @@ class Mesh(metaclass = MeshMeta):
def GetMeshInfo(self, obj = None): def GetMeshInfo(self, obj = None):
""" """
Get the mesh statistic. Get the mesh statistic.
Use :meth:`smeshBuilder.EnumToLong` to get an integer from
an item of :class:`SMESH.EntityType`.
Returns: Returns:
dictionary { :class:`SMESH.EntityType` - "count of elements" } dictionary { :class:`SMESH.EntityType` - "count of elements" }
@ -6951,52 +6947,90 @@ class Mesh(metaclass = MeshMeta):
def GetLength(self, elemId=None): def GetLength(self, elemId=None):
""" """
Get length of 1D element or sum of lengths of all 1D mesh elements Get length of all given 1D elements or sum length of all 1D mesh elements
Parameters: Parameters:
elemId: mesh element ID (if not defined - sum of length of all 1D elements will be calculated) elemId: either a mesh element ID or a list of IDs or :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`. By default sum length of all 1D elements will be calculated.
Returns: Returns:
element's length value if *elemId* is specified or sum of all 1D mesh elements' lengths otherwise Sum of lengths of given elements
""" """
length = 0 length = 0
if elemId == None: if elemId == None:
length = self.smeshpyD.GetLength(self) length = self.smeshpyD.GetLength(self)
elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
length = self.smeshpyD.GetLength(elemId)
elif elemId == []:
length = 0
elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
for obj in elemId:
length += self.smeshpyD.GetLength(obj)
elif isinstance(elemId, list) and isinstance(elemId[0], int):
unRegister = genObjUnRegister()
obj = self.GetIDSource( elemId )
unRegister.set( obj )
length = self.smeshpyD.GetLength( obj )
else: else:
length = self.FunctorValue(SMESH.FT_Length, elemId) length = self.FunctorValue(SMESH.FT_Length, elemId)
return length return length
def GetArea(self, elemId=None): def GetArea(self, elemId=None):
""" """
Get area of 2D element or sum of areas of all 2D mesh elements Get area of given 2D elements or sum area of all 2D mesh elements
elemId mesh element ID (if not defined - sum of areas of all 2D elements will be calculated)
Parameters:
elemId: either a mesh element ID or a list of IDs or :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`. By default sum area of all 2D elements will be calculated.
Returns: Returns:
element's area value if *elemId* is specified or sum of all 2D mesh elements' areas otherwise Area of given element's if *elemId* is specified or sum of all 2D mesh elements' areas otherwise
""" """
area = 0 area = 0
if elemId == None: if elemId == None:
area = self.smeshpyD.GetArea(self) area = self.smeshpyD.GetArea(self)
elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
area = self.smeshpyD.GetArea(elemId)
elif elemId == []:
area = 0
elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
for obj in elemId:
area += self.smeshpyD.GetArea(obj)
elif isinstance(elemId, list) and isinstance(elemId[0], int):
unRegister = genObjUnRegister()
obj = self.GetIDSource( elemId )
unRegister.set( obj )
area = self.smeshpyD.GetArea( obj )
else: else:
area = self.FunctorValue(SMESH.FT_Area, elemId) area = self.FunctorValue(SMESH.FT_Area, elemId)
return area return area
def GetVolume(self, elemId=None): def GetVolume(self, elemId=None):
""" """
Get volume of 3D element or sum of volumes of all 3D mesh elements Get volume of a 3D element or sum of volumes of all 3D mesh elements
Parameters: Parameters:
elemId: mesh element ID (if not defined - sum of volumes of all 3D elements will be calculated) elemId: either a mesh element ID or a list of IDs or :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`. By default sum volume of all 3D elements will be calculated.
Returns: Returns:
element's volume value if *elemId* is specified or sum of all 3D mesh elements' volumes otherwise Sum element's volume value if *elemId* is specified or sum of all 3D mesh elements' volumes otherwise
""" """
volume = 0 volume = 0
if elemId == None: if elemId == None:
volume = self.smeshpyD.GetVolume(self) volume= self.smeshpyD.GetVolume(self)
elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
volume= self.smeshpyD.GetVolume(elemId)
elif elemId == []:
volume = 0
elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
for obj in elemId:
volume+= self.smeshpyD.GetVolume(obj)
elif isinstance(elemId, list) and isinstance(elemId[0], int):
unRegister = genObjUnRegister()
obj = self.GetIDSource( elemId )
unRegister.set( obj )
volume= self.smeshpyD.GetVolume( obj )
else: else:
volume = self.FunctorValue(SMESH.FT_Volume3D, elemId) volume = self.FunctorValue(SMESH.FT_Volume3D, elemId)
return volume return volume

View File

@ -163,39 +163,46 @@ namespace
static TEdgeMarker theEdgeMarker; static TEdgeMarker theEdgeMarker;
return &theEdgeMarker; return &theEdgeMarker;
} }
//! Clear face sumbesh if something happens on edges //! Clear edge sumbesh if something happens on face
void ProcessEvent(const int event, void ProcessEvent(const int event,
const int eventType, const int eventType,
SMESH_subMesh* edgeSubMesh, SMESH_subMesh* faceSubMesh,
EventListenerData* data, EventListenerData* edgesHolder,
const SMESH_Hypothesis* /*hyp*/) const SMESH_Hypothesis* /*hyp*/)
{ {
if ( data && !data->mySubMeshes.empty() && eventType == SMESH_subMesh::ALGO_EVENT) if ( edgesHolder && eventType == SMESH_subMesh::ALGO_EVENT)
{ {
ASSERT( data->mySubMeshes.front() != edgeSubMesh ); std::list<SMESH_subMesh*>::iterator smIt = edgesHolder->mySubMeshes.begin();
SMESH_subMesh* faceSubMesh = data->mySubMeshes.front(); for ( ; smIt != edgesHolder->mySubMeshes.end(); ++smIt )
faceSubMesh->ComputeStateEngine( SMESH_subMesh::CLEAN ); {
SMESH_subMesh* edgeSM = *smIt;
edgeSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
}
}
}
//! Store edge SMESH_subMesh'es computed by the algo
static void markEdge( const TopoDS_Edge& edge, SMESH_subMesh* faceSM )
{
if ( SMESH_subMesh* edgeSM = faceSM->GetFather()->GetSubMeshContaining( edge ))
{
EventListenerData* edgesHolder = faceSM->GetEventListenerData( getListener() );
if ( edgesHolder )
{
std::list<SMESH_subMesh*>::iterator smIt = std::find( edgesHolder->mySubMeshes.begin(),
edgesHolder->mySubMeshes.end(),
edgeSM );
if ( smIt == edgesHolder->mySubMeshes.end() )
edgesHolder->mySubMeshes.push_back( edgeSM );
}
else
{
edgesHolder = SMESH_subMeshEventListenerData::MakeData( edgeSM );
faceSM->SetEventListener( TEdgeMarker::getListener(), edgesHolder, faceSM );
}
} }
} }
}; };
//================================================================================
/*!
* \brief Mark an edge as computed by StdMeshers_RadialQuadrangle_1D2D
*/
//================================================================================
void markEdgeAsComputedByMe(const TopoDS_Edge& edge, SMESH_subMesh* faceSubMesh)
{
if ( SMESH_subMesh* edgeSM = faceSubMesh->GetFather()->GetSubMeshContaining( edge ))
{
if ( !edgeSM->GetEventListenerData( TEdgeMarker::getListener() ))
faceSubMesh->SetEventListener( TEdgeMarker::getListener(),
SMESH_subMeshEventListenerData::MakeData(faceSubMesh),
edgeSM);
}
}
//================================================================================ //================================================================================
/*! /*!
* \brief Return sides of the face connected in the order: aCircEdge, aLinEdge1, aLinEdge2 * \brief Return sides of the face connected in the order: aCircEdge, aLinEdge1, aLinEdge2
@ -744,7 +751,7 @@ protected:
* \brief Allow algo to do something after persistent restoration * \brief Allow algo to do something after persistent restoration
* \param subMesh - restored submesh * \param subMesh - restored submesh
* *
* call markEdgeAsComputedByMe() * call TEdgeMarker::markEdge()
*/ */
//======================================================================= //=======================================================================
@ -754,7 +761,7 @@ void StdMeshers_RadialQuadrangle_1D2D::SubmeshRestored(SMESH_subMesh* faceSubMes
{ {
for ( TopExp_Explorer e( faceSubMesh->GetSubShape(), TopAbs_EDGE ); e.More(); e.Next() ) for ( TopExp_Explorer e( faceSubMesh->GetSubShape(), TopAbs_EDGE ); e.More(); e.Next() )
{ {
markEdgeAsComputedByMe( TopoDS::Edge( e.Current() ), faceSubMesh ); TEdgeMarker::markEdge( TopoDS::Edge( e.Current() ), faceSubMesh );
} }
} }
} }
@ -963,7 +970,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh& aMesh,
list< TopoDS_Edge >::iterator ee = emptyEdges.begin(); list< TopoDS_Edge >::iterator ee = emptyEdges.begin();
for ( ; ee != emptyEdges.end(); ++ee ) for ( ; ee != emptyEdges.end(); ++ee )
markEdgeAsComputedByMe( *ee, aMesh.GetSubMesh( F )); TEdgeMarker::markEdge( *ee, aMesh.GetSubMesh( F ));
circSide->GetUVPtStruct(); // let sides take into account just computed nodes circSide->GetUVPtStruct(); // let sides take into account just computed nodes
linSide1->GetUVPtStruct(); linSide1->GetUVPtStruct();