Salome HOME
#16648 [CEA] RadialQuadrangle algorithm hypothesis change requires a Clear Mesh Data...
authoreap <eap@opencascade.com>
Tue, 5 Mar 2019 16:35:52 +0000 (19:35 +0300)
committereap <eap@opencascade.com>
Tue, 5 Mar 2019 16:35:52 +0000 (19:35 +0300)
+
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
src/SMESH/SMESH_MeshEditor.cxx
src/SMESHUtils/SMESH_PolyLine.cxx
src/SMESH_I/SMESH_PreMeshInfo.cxx
src/SMESH_SWIG/smeshBuilder.py
src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx

index ecd12a0b5d493ef48d1f6c28a1cc4a912620bc73..69f3adaa693843ec53e8f5a16b0b36a8863715ec 100644 (file)
@@ -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;
index 284e83277a16a8bd6d0944383ba4387163b8fac0..12e01cd2adac78e1c810a8bb3c1b19d1bbafa2ab 100644 (file)
@@ -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;
index c252afb2c77515a5c4eb68cead4d9ed37a375f9b..b244a7560e99a2a3227776a50b61fd61e40ffa03 100644 (file)
@@ -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 );
+            }
           }
         }
 
index c92372a9634476886bcaf59b33338ce2e5125ecb..58701b12364f4d179e4ece3be0b8763e77838e79 100644 (file)
@@ -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()" );
 }
index 381bb20ca6dfb8b08b35c35e6c2bc758dbf3f0e3..64ee3091fac4d11ff59c6b0682d2f9bfb3cc2865 100644 (file)
@@ -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 <SMESH.SMESH_IDSource>`. 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 <SMESH.SMESH_IDSource>`. 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 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 <SMESH.SMESH_IDSource>`. 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
index e96c2a7ee2e5634d1ebce13c0baa8541f8d0d37d..8c5869107d5e0cc5859628bd117bbc22ae3b71bf 100644 (file)
@@ -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<SMESH_subMesh*>::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<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 );
+        }
+      }
     }
-  }
+  };
 
   //================================================================================
   /*!
@@ -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();