Salome HOME
021346: EDF 1938 SMESH: "Use existing elements" functionality
authoreap <eap@opencascade.com>
Mon, 22 Aug 2011 08:44:59 +0000 (08:44 +0000)
committereap <eap@opencascade.com>
Mon, 22 Aug 2011 08:44:59 +0000 (08:44 +0000)
   fix the bug that edges on the seam edges are not created

src/StdMeshers/StdMeshers_Import_1D2D.cxx

index 7b3aed36884faf181f63eef3d5272edb998378de..121c258ccc9d3a653962d4b712c2685bec7c10cd 100644 (file)
@@ -144,6 +144,12 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
   if ( srcGroups.empty() )
     return error("Invalid source groups");
 
+  bool allGroupsEmpty = true;
+  for ( size_t iG = 0; iG < srcGroups.size() && allGroupsEmpty; ++iG )
+    allGroupsEmpty = srcGroups[iG]->GetGroupDS()->IsEmpty();
+  if ( allGroupsEmpty )
+    return error("No faces in source groups");
+
   SMESH_MesherHelper helper(theMesh);
   helper.SetSubShape(theShape);
   SMESHDS_Mesh* tgtMesh = theMesh.GetMeshDS();
@@ -192,7 +198,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
   StdMeshers_Import_1D::TNodeNodeMap* n2n;
   StdMeshers_Import_1D::TElemElemMap* e2e;
   vector<const SMDS_MeshNode*> newNodes;
-  for ( int iG = 0; iG < srcGroups.size(); ++iG )
+  for ( size_t iG = 0; iG < srcGroups.size(); ++iG )
   {
     const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
 
@@ -212,7 +218,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
       newNodes.back() = 0;
       int nbCreatedNodes = 0;
       SMDS_MeshElement::iterator node = face->begin_nodes();
-      for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
+      for ( size_t i = 0; i < newNodes.size(); ++i, ++node )
       {
         StdMeshers_Import_1D::TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
         if ( n2nIt->second )
@@ -342,7 +348,8 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
   const double projTol = 1e-3 * sqrt( minLinkLen2 );
 
   bool isFaceMeshed = false;
-  if ( SMESHDS_SubMesh* tgtSM = tgtMesh->MeshElements( theShape ))
+  SMESHDS_SubMesh* tgtFaceSM = tgtMesh->MeshElements( theShape );
+  if ( tgtFaceSM )
   {
     // the imported mesh is valid if all external links (encountered once)
     // lie on geom edges
@@ -354,7 +361,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
       int nbFaces = link2Nb->second;
       if ( nbFaces == 1 )
       {
-        // check if a not shared link lie on face boundary
+        // check if a not shared link lies on face boundary
         bool nodesOnBoundary = true;
         list< TopoDS_Shape > bndShapes;
         for ( int is1stN = 0; is1stN < 2 && nodesOnBoundary; ++is1stN )
@@ -362,14 +369,14 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
           const SMDS_MeshNode* n = is1stN ? link.node1() : link.node2();
           if ( !subShapeIDs.count( n->getshapeId() ))
           {
-            for ( unsigned iE = 0; iE < edges.size(); ++iE )
+            for ( size_t iE = 0; iE < edges.size(); ++iE )
               if ( helper.CheckNodeU( edges[iE], n, u=0, projTol, /*force=*/true ))
               {
                 BRep_Tool::Range(edges[iE],f,l);
                 if ( Abs(u-f) < 2 * faceTol || Abs(u-l) < 2 * faceTol )
                   // duplicated node on vertex
                   return error("Source elements overlap one another");
-                tgtSM->RemoveNode( n, /*isNodeDeleted=*/false );
+                tgtFaceSM->RemoveNode( n, /*isNodeDeleted=*/false );
                 tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)n, edges[iE], u );
                 break;
               }
@@ -421,7 +428,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
 
           TopoDS_Edge geomEdge = TopoDS::Edge(bndShapes.back());
           helper.CheckNodeU( geomEdge, link._medium, u, 10*faceTol, /*force=*/true );
-          tgtSM->RemoveNode( link._medium, /*isNodeDeleted=*/false );
+          tgtFaceSM->RemoveNode( link._medium, /*isNodeDeleted=*/false );
           tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)link._medium, geomEdge, u );
         }
         else
@@ -468,16 +475,97 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
   if ( !isFaceMeshed )
     return error( "Source elements don't cover totally the geometrical face" );
 
+  if ( helper.HasSeam() )
+  {
+    // links on seam edges are shared by two faces, so no edges were created on them
+    // by the previous detection of 2D mesh boundary
+    for ( size_t iE = 0; iE < edges.size(); ++iE )
+    {
+      if ( !helper.IsRealSeam( edges[iE] )) continue;
+      const TopoDS_Edge& seamEdge = edges[iE];
+      // to find nodes lying on the seamEdge we check nodes of mesh faces sharing a node on one
+      // of its vertices; after finding another node on seamEdge we continue the same way
+      // until finding all nodes.
+      TopoDS_Vertex      seamVertex = helper.IthVertex( 0, seamEdge );
+      const SMDS_MeshNode* vertNode = SMESH_Algo::VertexNode( seamVertex, tgtMesh );
+      set< const SMDS_MeshNode* > checkedNodes; checkedNodes.insert( vertNode );
+      set< const SMDS_MeshElement* > checkedFaces;
+      // as a face can have more than one node on the seamEdge, there is a difficulty in selecting
+      // one of those nodes to treat next; so we simply find all nodes on the seamEdge and
+      // then sort them by U on edge
+      typedef list< pair< double, const SMDS_MeshNode* > > TUNodeList;
+      TUNodeList nodesOnSeam;
+      double u = helper.GetNodeU( seamEdge, vertNode );
+      nodesOnSeam.push_back( make_pair( u, vertNode ));
+      TUNodeList::iterator u2nIt = nodesOnSeam.begin();
+      for ( ; u2nIt != nodesOnSeam.end(); ++u2nIt )
+      {
+        const SMDS_MeshNode* startNode = (*u2nIt).second;
+        SMDS_ElemIteratorPtr faceIt = startNode->GetInverseElementIterator( SMDSAbs_Face );
+        while ( faceIt->more() )
+        {
+          const SMDS_MeshElement* face = faceIt->next();
+          if ( !checkedFaces.insert( face ).second ) continue;
+          for ( int i = 0, nbNodes = face->NbCornerNodes(); i < nbNodes; ++i )
+          {
+            const SMDS_MeshNode* n = face->GetNode( i );
+            if ( n == startNode || !checkedNodes.insert( n ).second ) continue;
+            if ( helper.CheckNodeU( seamEdge, n, u=0, projTol, /*force=*/true ))
+              nodesOnSeam.push_back( make_pair( u, n ));
+          }
+        }
+      }
+      // sort the found nodes by U on the seamEdge; most probably they are in a good order,
+      // so we can use the hint to spead-up map filling
+      map< double, const SMDS_MeshNode* > u2nodeMap;
+      for ( u2nIt = nodesOnSeam.begin(); u2nIt != nodesOnSeam.end(); ++u2nIt )
+        u2nodeMap.insert( u2nodeMap.end(), *u2nIt );
+
+      // create edges
+      {
+        SMESH_MesherHelper seamHelper( theMesh );
+        seamHelper.SetSubShape( edges[ iE ]);
+        seamHelper.SetElementsOnShape( true );
+
+        if ( (*checkedFaces.begin())->IsQuadratic() )
+          for ( set< const SMDS_MeshElement* >::iterator fIt = checkedFaces.begin();
+                fIt != checkedFaces.end(); ++fIt )
+            seamHelper.AddTLinks( static_cast<const SMDS_MeshFace*>( *fIt ));
+
+        map< double, const SMDS_MeshNode* >::iterator n1, n2, u2nEnd = u2nodeMap.end();
+        for ( n2 = u2nodeMap.begin(), n1 = n2++; n2 != u2nEnd; ++n1, ++n2 )
+        {
+          const SMDS_MeshNode* node1 = n1->second;
+          const SMDS_MeshNode* node2 = n2->second;
+          seamHelper.AddEdge( node1, node2 );
+          if ( node2->getshapeId() == helper.GetSubShapeID() )
+          {
+            tgtFaceSM->RemoveNode( node2, /*isNodeDeleted=*/false );
+            tgtMesh->SetNodeOnEdge( const_cast<SMDS_MeshNode*>( node2 ), seamEdge, n2->first );
+          }
+        }
+      }
+    } // loop on edges to find seam ones
+  } // if ( helper.HasSeam() )
+
   // notify sub-meshes of edges on computation
-  for ( unsigned iE = 0; iE < edges.size(); ++iE )
-    theMesh.GetSubMesh( edges[iE] )->ComputeStateEngine(SMESH_subMesh::CHECK_COMPUTE_STATE);
+  for ( size_t iE = 0; iE < edges.size(); ++iE )
+  {
+    SMESH_subMesh * sm = theMesh.GetSubMesh( edges[iE] );
+    if ( BRep_Tool::Degenerated( edges[iE] ))
+      sm->SetIsAlwaysComputed( true );
+    sm->ComputeStateEngine(SMESH_subMesh::CHECK_COMPUTE_STATE);
+    if ( sm->GetComputeState() != SMESH_subMesh::COMPUTE_OK )
+      return error(SMESH_Comment("Failed to create segments on the edge ")
+                   << tgtMesh->ShapeToIndex( edges[iE ]));
+  }
 
   // ============
   // Copy meshes
   // ============
 
   vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
-  for ( unsigned i = 0; i < srcMeshes.size(); ++i )
+  for ( size_t i = 0; i < srcMeshes.size(); ++i )
     StdMeshers_Import_1D::importMesh( srcMeshes[i], theMesh, _sourceHyp, theShape );
 
   return true;