Salome HOME
52566]: TC7.5.0: Empty group of Balls at Diameter Equal to filter
[modules/smesh.git] / src / StdMeshers / StdMeshers_Import_1D2D.cxx
index 8180f0a027ff93a692f6e7155cd949443c4f0902..636cd73ec006e4eec21bdfd1a88121e092febb41 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -6,7 +6,7 @@
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -38,6 +38,7 @@
 #include "SMESH_Group.hxx"
 #include "SMESH_Mesh.hxx"
 #include "SMESH_MesherHelper.hxx"
+#include "SMESH_OctreeNode.hxx"
 #include "SMESH_subMesh.hxx"
 
 #include "Utils_SALOME_Exception.hxx"
@@ -96,6 +97,7 @@ StdMeshers_Import_1D2D::StdMeshers_Import_1D2D(int hypId, int studyId, SMESH_Gen
 
   _compatibleHypothesis.push_back("ImportSource2D");
   _requireDiscreteBoundary = false;
+  _supportSubmeshes = true;
 }
 
 //=============================================================================
@@ -164,7 +166,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
 {
   if ( !_sourceHyp ) return false;
 
-  const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
+  const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups(/*loaded=*/true);
   if ( srcGroups.empty() )
     return error("Invalid source groups");
 
@@ -191,9 +193,10 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
   set<int> subShapeIDs;
   subShapeIDs.insert( shapeID );
 
-  // get nodes on vertices
-  list < SMESH_TNodeXYZ > vertexNodes;
-  list < SMESH_TNodeXYZ >::iterator vNIt;
+  // nodes already existing on sub-shapes of the FACE
+  TIDSortedNodeSet existingNodes;
+
+  // get/make nodes on vertices and add them to existingNodes
   TopExp_Explorer exp( theShape, TopAbs_VERTEX );
   for ( ; exp.More(); exp.Next() )
   {
@@ -207,8 +210,28 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
       n = SMESH_Algo::VertexNode( v, tgtMesh );
       if ( !n ) return false; // very strange
     }
-    vertexNodes.push_back( SMESH_TNodeXYZ( n ));
+    existingNodes.insert( n );
+  }
+
+  // get EDGESs and their ids and get existing nodes on EDGEs
+  vector< TopoDS_Edge > edges;
+  for ( exp.Init( theShape, TopAbs_EDGE ); exp.More(); exp.Next() )
+  {
+    const TopoDS_Edge & edge = TopoDS::Edge( exp.Current() );
+    if ( !SMESH_Algo::isDegenerated( edge ))
+      if ( subShapeIDs.insert( tgtMesh->ShapeToIndex( edge )).second )
+      {
+        edges.push_back( edge );
+        if ( SMESHDS_SubMesh* eSM = tgtMesh->MeshElements( edge ))
+        {
+          typedef SMDS_StdIterator< const SMDS_MeshNode*, SMDS_NodeIteratorPtr > iterator;
+          existingNodes.insert( iterator( eSM->GetNodes() ), iterator() );
+        }
+      }
   }
+  // octree to find existing nodes
+  SMESH_OctreeNode existingNodeOcTr( existingNodes );
+  std::map<double, const SMDS_MeshNode*> dist2foundNodes;
 
   // to count now many times a link between nodes encounters
   map<TLink, int> linkCount;
@@ -247,22 +270,20 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
       SMDS_MeshElement::iterator node = face->begin_nodes();
       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;
+        StdMeshers_Import_1D::TNodeNodeMap::iterator n2nIt =
+          n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
         if ( n2nIt->second )
         {
-          if ( !subShapeIDs.count( n2nIt->second->getshapeId() ))
+          if ( !subShapeIDs.count( n2nIt->second->getshapeId() )) // node already on an EDGE
             break;
         }
         else
         {
-          // find an existing vertex node
-          for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt)
-            if ( vNIt->SquareDistance( *node ) < groupTol * groupTol)
-            {
-              (*n2nIt).second = vNIt->_node;
-              vertexNodes.erase( vNIt );
-              break;
-            }
+          // find a pre-existing node
+          dist2foundNodes.clear();
+          existingNodeOcTr.NodesAround( SMESH_TNodeXYZ( *node ), dist2foundNodes, groupTol );
+          if ( !dist2foundNodes.empty() )
+            (*n2nIt).second = dist2foundNodes.begin()->second;
         }
         if ( !n2nIt->second )
         {
@@ -290,6 +311,8 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
         continue; // repeated face in source groups already created 
 
       // check future face orientation
+      const int nbCorners = face->NbCornerNodes();
+      const bool isQuad   = ( nbCorners != (int) newNodes.size() );
       if ( toCheckOri )
       {
         int iNode = -1;
@@ -300,10 +323,10 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
           surface->D1( uv.X(),uv.Y(), p, du,dv );
           geomNorm = reverse ? dv^du : du^dv;
         }
-        while ( geomNorm.SquareMagnitude() < 1e-6 && iNode+1 < face->NbCornerNodes());
+        while ( geomNorm.SquareMagnitude() < 1e-6 && iNode+1 < nbCorners );
 
-        int iNext = helper.WrapIndex( iNode+1, face->NbCornerNodes() );
-        int iPrev = helper.WrapIndex( iNode-1, face->NbCornerNodes() );
+        int iNext = helper.WrapIndex( iNode+1, nbCorners );
+        int iPrev = helper.WrapIndex( iNode-1, nbCorners );
 
         SMESH_TNodeXYZ prevNode( newNodes[iPrev] );
         SMESH_TNodeXYZ curNode ( newNodes[iNode] );
@@ -313,40 +336,43 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
         gp_Vec meshNorm = n1n2 ^ n1n0;
 
         if ( geomNorm * meshNorm < 0 )
-          std::reverse( newNodes.begin(), newNodes.end() );
+          SMDS_MeshCell::applyInterlace
+            ( SMDS_MeshCell::reverseSmdsOrder( face->GetEntityType() ), newNodes );
       }
 
       // make a new face
-      switch ( newNodes.size() )
-      {
-      case 3:
-        newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] );
-        break;
-      case 4:
-        newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] );
-        break;
-      case 6:
-        newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2],
-                                    newNodes[3], newNodes[4], newNodes[5]);
-        break;
-      case 8:
-        newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3],
-                                    newNodes[4], newNodes[5], newNodes[6], newNodes[7]);
-        break;
-      default: continue;
-      }
+      if ( face->IsPoly() )
+        newFace = tgtMesh->AddPolygonalFace( newNodes );
+      else
+        switch ( newNodes.size() )
+        {
+        case 3:
+          newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] );
+          break;
+        case 4:
+          newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] );
+          break;
+        case 6:
+          newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2],
+                                      newNodes[3], newNodes[4], newNodes[5]);
+          break;
+        case 8:
+          newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3],
+                                      newNodes[4], newNodes[5], newNodes[6], newNodes[7]);
+          break;
+        default: continue;
+        }
       tgtMesh->SetMeshElementOnShape( newFace, shapeID );
       e2e->insert( make_pair( face, newFace ));
 
       // collect links
-      int nbNodes = face->NbCornerNodes();
       const SMDS_MeshNode* medium = 0;
-      for ( int i = 0; i < nbNodes; ++i )
+      for ( int i = 0; i < nbCorners; ++i )
       {
         const SMDS_MeshNode* n1 = newNodes[i];
-        const SMDS_MeshNode* n2 = newNodes[ (i+1)%nbNodes ];
-        if ( newFace->IsQuadratic() )
-          medium = newNodes[i+nbNodes];
+        const SMDS_MeshNode* n2 = newNodes[ (i+1)%nbCorners ];
+        if ( isQuad ) // quadratic face
+          medium = newNodes[i+nbCorners];
         link2Nb = linkCount.insert( make_pair( TLink( n1, n2, medium ), 0)).first;
         ++link2Nb->second;
         // if ( link2Nb->second == 1 )
@@ -366,11 +392,6 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
   // check if the whole geom face is covered by imported faces
   // ==========================================================
 
-  vector< TopoDS_Edge > edges;
-  for ( exp.Init( theShape, TopAbs_EDGE ); exp.More(); exp.Next() )
-    if ( subShapeIDs.insert( tgtMesh->ShapeToIndex( exp.Current() )).second )
-      edges.push_back( TopoDS::Edge( exp.Current() ));
-
   // use large tolerance for projection of nodes to edges because of
   // BLSURF mesher specifics (issue 0020918, Study2.hdf)
   const double projTol = minGroupTol;
@@ -395,7 +416,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
         for ( int is1stN = 0; is1stN < 2 && nodesOnBoundary; ++is1stN )
         {
           const SMDS_MeshNode* n = is1stN ? link.node1() : link.node2();
-          if ( !subShapeIDs.count( n->getshapeId() ))
+          if ( !subShapeIDs.count( n->getshapeId() )) // n is assigned to FACE
           {
             for ( size_t iE = 0; iE < edges.size(); ++iE )
               if ( helper.CheckNodeU( edges[iE], n, u=0, projTol, /*force=*/true ))
@@ -405,7 +426,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
                   // duplicated node on vertex
                   return error("Source elements overlap one another");
                 tgtFaceSM->RemoveNode( n, /*isNodeDeleted=*/false );
-                tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)n, edges[iE], u );
+                tgtMesh->SetNodeOnEdge( n, edges[iE], u );
                 break;
               }
             nodesOnBoundary = subShapeIDs.count( n->getshapeId());
@@ -424,13 +445,13 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
           error("free internal link"); // just for an easier debug
           break;
         }
-        if ( bndShapes.front().ShapeType() == TopAbs_EDGE &&
+        if ( bndShapes.front().ShapeType() == TopAbs_EDGE && // all link nodes are on EDGEs
              bndShapes.front() != bndShapes.back() )
           // link nodes on different geom edges
           return error(COMPERR_BAD_INPUT_MESH, "Source nodes mismatch target vertices");
 
         // find geom edge the link is on
-        if ( bndShapes.back().ShapeType() != TopAbs_EDGE )
+        if ( bndShapes.back().ShapeType() != TopAbs_EDGE ) // all link nodes are on VERTEXes
         {
           // find geom edge by two vertices
           TopoDS_Shape geomEdge = helper.GetCommonAncestor( bndShapes.back(),
@@ -453,8 +474,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
         if ( link._reversed ) std::swap( newNodes[0], newNodes[1] );
         if ( link._medium )
         {
-          newNodes.push_back( link._medium );
-          edge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] );
+          edge = tgtMesh->AddEdge( newNodes[0], newNodes[1], link._medium );
 
           TopoDS_Edge geomEdge = TopoDS::Edge(bndShapes.back());
           helper.CheckNodeU( geomEdge, link._medium, u, projTol, /*force=*/true );
@@ -495,7 +515,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
           int sId = editor.FindShape( edge );
           nbEdges += subShapeIDs.count( sId );
         }
-        if ( nbEdges < 2 )
+        if ( nbEdges < 2 && !helper.IsRealSeam( s ))
           return false; // weird
         if ( nbEdges > 2 )
           return error( COMPERR_BAD_INPUT_MESH, "Source elements overlap one another");
@@ -583,8 +603,8 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
   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 );
+    // if ( SMESH_Algo::isDegenerated( 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 ")