From d2248790d7e9f3862ac49798c4c55eeff28df18a Mon Sep 17 00:00:00 2001 From: eap Date: Tue, 5 Mar 2019 19:35:52 +0300 Subject: [PATCH] #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 --- src/Controls/SMESH_Controls.cxx | 16 ++--- src/SMESH/SMESH_MeshEditor.cxx | 4 +- src/SMESHUtils/SMESH_PolyLine.cxx | 45 ++++++++------ src/SMESH_I/SMESH_PreMeshInfo.cxx | 7 ++- src/SMESH_SWIG/smeshBuilder.py | 62 ++++++++++++++----- .../StdMeshers_RadialQuadrangle_1D2D.cxx | 59 ++++++++++-------- 6 files changed, 120 insertions(+), 73 deletions(-) diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index ecd12a0b5..69f3adaa6 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -2565,18 +2565,14 @@ void FreeEdges::SetMesh( const SMDS_Mesh* theMesh ) bool FreeEdges::IsFreeEdge( const SMDS_MeshNode** theNodes, const int theFaceId ) { - TColStd_MapOfInteger aMap; - for ( int i = 0; i < 2; i++ ) + SMDS_ElemIteratorPtr anElemIter = theNodes[ 0 ]->GetInverseElementIterator(SMDSAbs_Face); + while( anElemIter->more() ) { - SMDS_ElemIteratorPtr anElemIter = theNodes[ i ]->GetInverseElementIterator(SMDSAbs_Face); - while( anElemIter->more() ) + if ( const SMDS_MeshElement* anElem = anElemIter->next()) { - if ( const SMDS_MeshElement* anElem = anElemIter->next()) - { - const int anId = anElem->GetID(); - if ( anId != theFaceId && !aMap.Add( anId )) - return false; - } + const int anId = anElem->GetID(); + if ( anId != theFaceId && anElem->GetNodeIndex( theNodes[1] ) >= 0 ) + return false; } } return true; diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 284e83277..12e01cd2a 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -7681,9 +7681,9 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirst // push_back the best free border cNL = & contNodes[ contNodes[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 - theFaces.pop_back(); // remove curElem + //theFaces.pop_back(); // remove curElem theNodes.splice( theNodes.end(), *cNL ); theFaces.splice( theFaces.end(), *cFL ); return true; diff --git a/src/SMESHUtils/SMESH_PolyLine.cxx b/src/SMESHUtils/SMESH_PolyLine.cxx index c252afb2c..b244a7560 100644 --- a/src/SMESHUtils/SMESH_PolyLine.cxx +++ b/src/SMESHUtils/SMESH_PolyLine.cxx @@ -494,28 +494,37 @@ namespace << " in a PolySegment " << iSeg ); if ( path.myDot1 == 0. && - path.myDot2 == 0. && - paths.size() - nbPaths >= 2 ) // use a face non-parallel to the plane + path.myDot2 == 0. ) { - const SMDS_MeshElement* goodFace = 0; - for ( size_t j = nbPaths; j < paths.size(); ++j ) + if ( paths.size() - nbPaths >= 2 ) // use a face non-parallel to the plane { - path = paths[j]; - if ( path.Extend( plnNorm, plnOrig )) - 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 ) + const SMDS_MeshElement* goodFace = 0; + for ( size_t j = nbPaths; j < paths.size(); ++j ) { - paths[j].myFace = goodFace; - paths[j].myNodeInd1 = goodFace->GetNodeIndex( paths[j].myNode1.Node() ); - paths[j].myNodeInd2 = goodFace->GetNodeIndex( paths[j].myNode2.Node() ); + path = paths[j]; + if ( path.Extend( plnNorm, plnOrig )) + 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 ); + } } } diff --git a/src/SMESH_I/SMESH_PreMeshInfo.cxx b/src/SMESH_I/SMESH_PreMeshInfo.cxx index c92372a96..58701b123 100644 --- a/src/SMESH_I/SMESH_PreMeshInfo.cxx +++ b/src/SMESH_I/SMESH_PreMeshInfo.cxx @@ -456,7 +456,7 @@ bool SMESH_PreMeshInfo::readPreInfoFromHDF() mapOfNames ); } } - infoHdfGroup->CloseOnDisk(); + infoHdfGroup->CloseOnDisk(); } aFile->CloseOnDisk(); @@ -841,8 +841,9 @@ void SMESH_PreMeshInfo::FullLoadFromFile() const meshDS->Modified(); // load dependent meshes referring/referred via hypotheses - mesh.GetSubMesh( mesh.GetShapeToMesh() )-> - ComputeStateEngine (SMESH_subMesh::SUBMESH_LOADED); + SMESH_subMesh* mainSub = mesh.GetSubMesh( mesh.GetShapeToMesh() ); + mainSub->ComputeStateEngine (SMESH_subMesh::SUBMESH_RESTORED); // #16648 + mainSub->ComputeStateEngine (SMESH_subMesh::SUBMESH_LOADED); MYDEBUGOUT( "END FullLoadFromFile()" ); } diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 381bb20ca..64ee3091f 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -1235,8 +1235,6 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): def GetMeshInfo(self, obj): """ Get the mesh statistic. - Use :meth:`smeshBuilder.EnumToLong` to get an integer from - an item of :class:`SMESH.EntityType`. Returns: dictionary { :class:`SMESH.EntityType` - "count of elements" } @@ -3091,8 +3089,6 @@ class Mesh(metaclass = MeshMeta): def GetMeshInfo(self, obj = None): """ Get the mesh statistic. - Use :meth:`smeshBuilder.EnumToLong` to get an integer from - an item of :class:`SMESH.EntityType`. Returns: dictionary { :class:`SMESH.EntityType` - "count of elements" } @@ -6951,52 +6947,90 @@ class Mesh(metaclass = MeshMeta): 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: - 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 `. By default sum length of all 1D elements will be calculated. 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 if elemId == None: 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: length = self.FunctorValue(SMESH.FT_Length, elemId) return length def GetArea(self, elemId=None): """ - Get area of 2D element or sum of areas of all 2D mesh elements - elemId mesh element ID (if not defined - sum of areas of all 2D elements will be calculated) + Get area of given 2D elements or sum area of all 2D mesh elements + + Parameters: + elemId: either a mesh element ID or a list of IDs or :class:`sub-mesh, group or filter `. By default sum area of all 2D elements will be calculated. 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 if elemId == None: 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: area = self.FunctorValue(SMESH.FT_Area, elemId) return area 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: - 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 `. By default sum volume of all 3D elements will be calculated. 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 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: volume = self.FunctorValue(SMESH.FT_Volume3D, elemId) return volume diff --git a/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx b/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx index e96c2a7ee..8c5869107 100644 --- a/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx @@ -163,38 +163,45 @@ namespace static TEdgeMarker theEdgeMarker; return &theEdgeMarker; } - //! Clear face sumbesh if something happens on edges + //! Clear edge sumbesh if something happens on face void ProcessEvent(const int event, const int eventType, - SMESH_subMesh* edgeSubMesh, - EventListenerData* data, + SMESH_subMesh* faceSubMesh, + EventListenerData* edgesHolder, 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 ); - SMESH_subMesh* faceSubMesh = data->mySubMeshes.front(); - faceSubMesh->ComputeStateEngine( SMESH_subMesh::CLEAN ); + std::list::iterator smIt = edgesHolder->mySubMeshes.begin(); + for ( ; smIt != edgesHolder->mySubMeshes.end(); ++smIt ) + { + SMESH_subMesh* edgeSM = *smIt; + edgeSM->ComputeStateEngine( SMESH_subMesh::CLEAN ); + } } } - }; - - //================================================================================ - /*! - * \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 )) + //! Store edge SMESH_subMesh'es computed by the algo + static void markEdge( const TopoDS_Edge& edge, SMESH_subMesh* faceSM ) { - if ( !edgeSM->GetEventListenerData( TEdgeMarker::getListener() )) - faceSubMesh->SetEventListener( TEdgeMarker::getListener(), - SMESH_subMeshEventListenerData::MakeData(faceSubMesh), - edgeSM); + if ( SMESH_subMesh* edgeSM = faceSM->GetFather()->GetSubMeshContaining( edge )) + { + EventListenerData* edgesHolder = faceSM->GetEventListenerData( getListener() ); + if ( edgesHolder ) + { + std::list::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 ); + } + } } - } + }; //================================================================================ /*! @@ -744,7 +751,7 @@ protected: * \brief Allow algo to do something after persistent restoration * \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() ) { - 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(); 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 linSide1->GetUVPtStruct(); -- 2.30.2