Salome HOME
52618: Import_1D2D fails to import from a mesh group onto a group of geom faces
[modules/smesh.git] / src / StdMeshers / StdMeshers_ProjectionUtils.cxx
index 58b69838b8d43161d18c8e1e138025c41b893b6d..faeb9b706a01f9098c3d9d80e3a7afaff8559cc1 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015  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
@@ -51,6 +51,7 @@
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
 #include <Bnd_Box.hxx>
+#include <Geom2d_Curve.hxx>
 #include <TopAbs.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
@@ -549,7 +550,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
       // ----------------------------------------------------------------------
     case TopAbs_EDGE: { // TopAbs_EDGE
       // ----------------------------------------------------------------------
-      if ( theMap.Extent() != 2 )
+      if ( theMap.Extent() != 1 )
         RETURN_BAD_RESULT("Wrong map extent " << theMap.Extent() );
       TopoDS_Edge edge1 = TopoDS::Edge( theShape1 );
       TopoDS_Edge edge2 = TopoDS::Edge( theShape2 );
@@ -657,7 +658,6 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
       TopoDS_Shape F1, F2;
 
       // get a face sharing edge1 (F1)
-      TopoDS_Shape FF2[2];
       TopTools_ListIteratorOfListOfShape ancestIt1( edgeToFace1.FindFromKey( edge1 ));
       for ( ; F1.IsNull() && ancestIt1.More(); ancestIt1.Next() )
         if ( ancestIt1.Value().ShapeType() == TopAbs_FACE )
@@ -667,6 +667,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
         RETURN_BAD_RESULT(" Face1 not found");
 
       // get 2 faces sharing edge2 (one of them is F2)
+      TopoDS_Shape FF2[2];
       TopTools_ListIteratorOfListOfShape ancestIt2( edgeToFace2.FindFromKey( edge2 ));
       for ( int i = 0; FF2[1].IsNull() && ancestIt2.More(); ancestIt2.Next() )
         if ( ancestIt2.Value().ShapeType() == TopAbs_FACE )
@@ -1452,8 +1453,10 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face&    face1,
         edge1End = edge1Beg;
         std::advance( edge1End, *nbE1 );
         // UV on face1 to find on face2
-        v0f1UV = BRep_Tool::Parameters( TopExp::FirstVertex(*edge1Beg,true), face1 );
-        v1f1UV = BRep_Tool::Parameters( TopExp::LastVertex (*edge1Beg,true), face1 );
+        TopoDS_Vertex v01 = SMESH_MesherHelper::IthVertex(0,*edge1Beg);
+        TopoDS_Vertex v11 = SMESH_MesherHelper::IthVertex(1,*edge1Beg);
+        v0f1UV = BRep_Tool::Parameters( v01, face1 );
+        v1f1UV = BRep_Tool::Parameters( v11, face1 );
         v0f1UV.ChangeCoord() += dUV;
         v1f1UV.ChangeCoord() += dUV;
         //
@@ -1478,9 +1481,30 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face&    face1,
                  sameVertexUV( *edge2Beg, face2, 0, v0f1UV, vTolUV ))
             {
               if ( iW1 == 0 ) OK = true; // OK is for the first wire
+
               // reverse edges2 if needed
-              if ( !sameVertexUV( *edge2Beg, face2, 1, v1f1UV, vTolUV ))
-                reverseEdges( edges2 , *nbE2, std::distance( edges2.begin(),edge2Beg ));
+              if ( SMESH_MesherHelper::IsClosedEdge( *edge1Beg ))
+              {
+                double f,l;
+                Handle(Geom2d_Curve) c1 = BRep_Tool::CurveOnSurface( *edge1Beg, face1,f,l );
+                if (  edge1Beg->Orientation() == TopAbs_REVERSED )
+                  std::swap( f,l );
+                gp_Pnt2d uv1 = dUV + c1->Value( f * 0.8 + l * 0.2 ).XY();
+
+                Handle(Geom2d_Curve) c2 = BRep_Tool::CurveOnSurface( *edge2Beg, face2,f,l );
+                if (  edge2Beg->Orientation() == TopAbs_REVERSED )
+                  std::swap( f,l );
+                gp_Pnt2d uv2 = c2->Value( f * 0.8 + l * 0.2 );
+
+                if ( uv1.Distance( uv2 ) > vTolUV )
+                  edge2Beg->Reverse();
+              }
+              else
+              {
+                if ( !sameVertexUV( *edge2Beg, face2, 1, v1f1UV, vTolUV ))
+                  reverseEdges( edges2 , *nbE2, std::distance( edges2.begin(),edge2Beg ));
+              }
+
               // put wire2 at a right place within edges2
               if ( iW1 != iW2 ) {
                 list< TopoDS_Edge >::iterator place2 = edges2.begin();
@@ -1918,97 +1942,109 @@ FindMatchingNodesOnFaces( const TopoDS_Face&     face1,
 
   // 2. face sets
 
-  set<const SMDS_MeshElement*> Elems1, Elems2;
-  for ( int is2 = 0; is2 < 2; ++is2 )
+  int assocRes;
+  for ( int iAttempt = 0; iAttempt < 2; ++iAttempt )
   {
-    set<const SMDS_MeshElement*> & elems = is2 ? Elems2 : Elems1;
-    SMESHDS_SubMesh*                  sm = is2 ? SM2 : SM1;
-    SMESH_MesherHelper*           helper = is2 ? &helper2 : &helper1;
-    const TopoDS_Face &             face = is2 ? face2 : face1;
-    SMDS_ElemIteratorPtr eIt = sm->GetElements();
-
-    if ( !helper->IsRealSeam( is2 ? edge2 : edge1 ))
-    {
-      while ( eIt->more() ) elems.insert( eIt->next() );
-    }
-    else
+    set<const SMDS_MeshElement*> Elems1, Elems2;
+    for ( int is2 = 0; is2 < 2; ++is2 )
     {
-      // the only suitable edge is seam, i.e. it is a sphere.
-      // FindMatchingNodes() will not know which way to go from any edge.
-      // So we ignore all faces having nodes on edges or vertices except
-      // one of faces sharing current start nodes
-
-      // find a face to keep
-      const SMDS_MeshElement* faceToKeep = 0;
-      const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
-      const SMDS_MeshNode* eNode = is2 ? eNode2[0] : eNode1[0];
-      TIDSortedElemSet inSet, notInSet;
-
-      const SMDS_MeshElement* f1 =
-        SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
-      if ( !f1 ) RETURN_BAD_RESULT("The first face on seam not found");
-      notInSet.insert( f1 );
-
-      const SMDS_MeshElement* f2 =
-        SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
-      if ( !f2 ) RETURN_BAD_RESULT("The second face on seam not found");
-
-      // select a face with less UV of vNode
-      const SMDS_MeshNode* notSeamNode[2] = {0, 0};
-      for ( int iF = 0; iF < 2; ++iF ) {
-        const SMDS_MeshElement* f = ( iF ? f2 : f1 );
-        for ( int i = 0; !notSeamNode[ iF ] && i < f->NbNodes(); ++i ) {
-          const SMDS_MeshNode* node = f->GetNode( i );
-          if ( !helper->IsSeamShape( node->getshapeId() ))
-            notSeamNode[ iF ] = node;
-        }
+      set<const SMDS_MeshElement*> & elems = is2 ? Elems2 : Elems1;
+      SMESHDS_SubMesh*                  sm = is2 ? SM2 : SM1;
+      SMESH_MesherHelper*           helper = is2 ? &helper2 : &helper1;
+      const TopoDS_Face &             face = is2 ? face2 : face1;
+      SMDS_ElemIteratorPtr eIt = sm->GetElements();
+
+      if ( !helper->IsRealSeam( is2 ? edge2 : edge1 ))
+      {
+        while ( eIt->more() ) elems.insert( elems.end(), eIt->next() );
       }
-      gp_Pnt2d uv1 = helper->GetNodeUV( face, vNode, notSeamNode[0] );
-      gp_Pnt2d uv2 = helper->GetNodeUV( face, vNode, notSeamNode[1] );
-      if ( uv1.X() + uv1.Y() > uv2.X() + uv2.Y() )
-        faceToKeep = f2;
       else
-        faceToKeep = f1;
-
-      // fill elem set
-      elems.insert( faceToKeep );
-      while ( eIt->more() ) {
-        const SMDS_MeshElement* f = eIt->next();
-        int nbNodes = f->NbNodes();
-        if ( f->IsQuadratic() )
-          nbNodes /= 2;
-        bool onBnd = false;
-        for ( int i = 0; !onBnd && i < nbNodes; ++i ) {
-          const SMDS_MeshNode* node = f->GetNode( i );
-          onBnd = ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE);
+      {
+        // the only suitable edge is seam, i.e. it is a sphere.
+        // FindMatchingNodes() will not know which way to go from any edge.
+        // So we ignore all faces having nodes on edges or vertices except
+        // one of faces sharing current start nodes
+
+        // find a face to keep
+        const SMDS_MeshElement* faceToKeep = 0;
+        const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
+        const SMDS_MeshNode* eNode = is2 ? eNode2[0] : eNode1[0];
+        TIDSortedElemSet inSet, notInSet;
+
+        const SMDS_MeshElement* f1 =
+          SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
+        if ( !f1 ) RETURN_BAD_RESULT("The first face on seam not found");
+        notInSet.insert( f1 );
+
+        const SMDS_MeshElement* f2 =
+          SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
+        if ( !f2 ) RETURN_BAD_RESULT("The second face on seam not found");
+
+        // select a face with less UV of vNode
+        const SMDS_MeshNode* notSeamNode[2] = {0, 0};
+        for ( int iF = 0; iF < 2; ++iF ) {
+          const SMDS_MeshElement* f = ( iF ? f2 : f1 );
+          for ( int i = 0; !notSeamNode[ iF ] && i < f->NbNodes(); ++i ) {
+            const SMDS_MeshNode* node = f->GetNode( i );
+            if ( !helper->IsSeamShape( node->getshapeId() ))
+              notSeamNode[ iF ] = node;
+          }
         }
-        if ( !onBnd )
-          elems.insert( f );
-      }
-      // add also faces adjacent to faceToKeep
-      int nbNodes = faceToKeep->NbNodes();
-      if ( faceToKeep->IsQuadratic() ) nbNodes /= 2;
-      notInSet.insert( f1 );
-      notInSet.insert( f2 );
-      for ( int i = 0; i < nbNodes; ++i ) {
-        const SMDS_MeshNode* n1 = faceToKeep->GetNode( i );
-        const SMDS_MeshNode* n2 = faceToKeep->GetNode(( i+1 ) % nbNodes );
-        f1 = SMESH_MeshAlgos::FindFaceInSet( n1, n2, inSet, notInSet );
-        if ( f1 )
-          elems.insert( f1 );
-      }
-    } // case on a sphere
-  } // loop on 2 faces
-
-  //  int quadFactor = (*Elems1.begin())->IsQuadratic() ? 2 : 1;
-
-  node1To2Map.clear();
-  int res = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2,
-                                                 vNode1, vNode2,
-                                                 eNode1[0], eNode2[0],
-                                                 node1To2Map);
-  if ( res != SMESH_MeshEditor::SEW_OK )
-    RETURN_BAD_RESULT("FindMatchingNodes() result " << res );
+        gp_Pnt2d uv1 = helper->GetNodeUV( face, vNode, notSeamNode[0] );
+        gp_Pnt2d uv2 = helper->GetNodeUV( face, vNode, notSeamNode[1] );
+        if ( uv1.X() + uv1.Y() > uv2.X() + uv2.Y() )
+          faceToKeep = f2;
+        else
+          faceToKeep = f1;
+
+        // fill elem set
+        elems.insert( faceToKeep );
+        while ( eIt->more() ) {
+          const SMDS_MeshElement* f = eIt->next();
+          int nbNodes = f->NbNodes();
+          if ( f->IsQuadratic() )
+            nbNodes /= 2;
+          bool onBnd = false;
+          for ( int i = 0; !onBnd && i < nbNodes; ++i ) {
+            const SMDS_MeshNode* node = f->GetNode( i );
+            onBnd = ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE);
+          }
+          if ( !onBnd )
+            elems.insert( f );
+        }
+        // add also faces adjacent to faceToKeep
+        int nbNodes = faceToKeep->NbNodes();
+        if ( faceToKeep->IsQuadratic() ) nbNodes /= 2;
+        notInSet.insert( f1 );
+        notInSet.insert( f2 );
+        for ( int i = 0; i < nbNodes; ++i ) {
+          const SMDS_MeshNode* n1 = faceToKeep->GetNode( i );
+          const SMDS_MeshNode* n2 = faceToKeep->GetNode(( i+1 ) % nbNodes );
+          f1 = SMESH_MeshAlgos::FindFaceInSet( n1, n2, inSet, notInSet );
+          if ( f1 )
+            elems.insert( f1 );
+        }
+      } // case on a sphere
+    } // loop on 2 faces
+
+    node1To2Map.clear();
+    assocRes = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2,
+                                                    vNode1, vNode2,
+                                                    eNode1[0], eNode2[0],
+                                                    node1To2Map);
+    if (( assocRes != SMESH_MeshEditor::SEW_OK ) &&
+        ( eNode1[1] || eNode2[1] )) // there is another node to try (on a closed EDGE)
+    {
+      node1To2Map.clear();
+      if ( eNode1[1] ) std::swap( eNode1[0], eNode1[1] );
+      else             std::swap( eNode2[0], eNode2[1] );
+      continue; // one more attempt
+    }
+
+    break;
+  }
+  if ( assocRes != SMESH_MeshEditor::SEW_OK )
+    RETURN_BAD_RESULT("FindMatchingNodes() result " << assocRes );
 
   // On a sphere, add matching nodes on the edge