Salome HOME
52566]: TC7.5.0: Empty group of Balls at Diameter Equal to filter
[modules/smesh.git] / src / StdMeshers / StdMeshers_Projection_2D.cxx
index d2b943b5bacee02c9184ede2cc0aaecf8434118d..66e7834aec0cf2846de4d283b1309f30f899284c 100644 (file)
@@ -51,6 +51,7 @@
 #include <BRep_Tool.hxx>
 #include <Bnd_B2d.hxx>
 #include <GeomAPI_ProjectPointOnSurf.hxx>
+#include <GeomLib_IsPlanarSurface.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
@@ -438,8 +439,11 @@ namespace {
       TopTools_IndexedMapOfShape edgeMap; // to detect seam edges
       for ( int iE = 0; iE < srcWire->NbEdges(); ++iE )
       {
-        TopoDS_Edge srcE = srcWire->Edge( iE );
-        TopoDS_Edge tgtE = TopoDS::Edge( shape2ShapeMap( srcE, /*isSrc=*/true));
+        TopoDS_Edge     srcE = srcWire->Edge( iE );
+        TopoDS_Edge     tgtE = TopoDS::Edge( shape2ShapeMap( srcE, /*isSrc=*/true));
+        TopoDS_Shape srcEbis = shape2ShapeMap( tgtE, /*isSrc=*/false );
+        if ( srcE.Orientation() != srcEbis.Orientation() )
+          tgtE.Reverse();
         // reverse a seam edge encountered for the second time
         const int index = edgeMap.Add( tgtE );
         if ( index < edgeMap.Extent() ) // E is a seam
@@ -482,15 +486,10 @@ namespace {
         }
         else
         {
+          const bool skipMediumNodes = true;
           map< double, const SMDS_MeshNode* > srcNodes, tgtNodes;
-          if (( ! SMESH_Algo::GetSortedNodesOnEdge( srcMeshDS, TopoDS::Edge( srcE ),
-                                                    /*ignoreMediumNodes = */true,
-                                                    srcNodes ))
-              ||
-              ( ! SMESH_Algo::GetSortedNodesOnEdge( tgtMeshDS, TopoDS::Edge( tgtE ),
-                                                    /*ignoreMediumNodes = */true,
-                                                    tgtNodes ))
-              )
+          if ( !SMESH_Algo::GetSortedNodesOnEdge( srcMeshDS, srcE, skipMediumNodes, srcNodes) ||
+               !SMESH_Algo::GetSortedNodesOnEdge( tgtMeshDS, tgtE, skipMediumNodes, tgtNodes ))
             return SMESH_ComputeError::New( COMPERR_BAD_INPUT_MESH,
                                             "Invalid node parameters on edges");
 
@@ -500,10 +499,18 @@ namespace {
           if ( !tgtNodes.empty() )
           {
             map< double, const SMDS_MeshNode* >::iterator u_tn = tgtNodes.begin();
-            map< double, const SMDS_MeshNode* >::iterator u_sn = srcNodes.begin();
-            for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn)
-              src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second ));
-
+            if ( srcE.Orientation() == tgtE.Orientation() )
+            {
+              map< double, const SMDS_MeshNode* >::iterator u_sn = srcNodes.begin();
+              for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn)
+                src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second ));
+            }
+            else
+            {
+              map< double, const SMDS_MeshNode* >::reverse_iterator u_sn = srcNodes.rbegin();
+              for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn)
+                src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second ));
+            }
             is1DComputed = true;
           }
         }
@@ -547,6 +554,11 @@ namespace {
       gp_Trsf srcTrsf = srcFace.Location();
       gp_Trsf tgtTrsf = tgtFace.Location();
       trsf.Set( srcTrsf.Inverted() * tgtTrsf );
+      // check
+      gp_Pnt srcP = BRep_Tool::Pnt( srcWires[0]->FirstVertex() );
+      gp_Pnt tgtP = BRep_Tool::Pnt( tgtWires[0]->FirstVertex() );
+      if ( tgtP.Distance( trsf.Transform( srcP )) > tol )
+        trsf.Set( tgtTrsf.Inverted() * srcTrsf );
     }
     else
     {
@@ -908,69 +920,24 @@ namespace {
   //================================================================================
 
   void fixDistortedFaces( SMESH_MesherHelper& helper,
-                          TSideVector&        )
+                          TSideVector&        tgtWires )
   {
-    // Detect bad faces
-
-    bool haveBadFaces = false;
-
-    const TopoDS_Face&  F = TopoDS::Face( helper.GetSubShape() );
-    SMESHDS_SubMesh* smDS = helper.GetMeshDS()->MeshElements( F );
-    if ( !smDS || smDS->NbElements() == 0 ) return;
+    SMESH_subMesh* faceSM = helper.GetMesh()->GetSubMesh( helper.GetSubShape() );
 
-    SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
-    double prevArea2D = 0;
-    vector< const SMDS_MeshNode* > nodes;
-    vector< gp_XY >                uv;
-    while ( faceIt->more() && !haveBadFaces )
-    {
-      const SMDS_MeshElement* face = faceIt->next();
-
-      // get nodes
-      nodes.resize( face->NbCornerNodes() );
-      SMDS_MeshElement::iterator n = face->begin_nodes();
-      for ( size_t i = 0; i < nodes.size(); ++n, ++i )
-        nodes[ i ] = *n;
-
-      // get UVs
-      const SMDS_MeshNode* inFaceNode = 0;
-      if ( helper.HasSeam() )
-        for ( size_t i = 0; ( i < nodes.size() && !inFaceNode ); ++i )
-          if ( !helper.IsSeamShape( nodes[ i ]->getshapeId() ))
-            inFaceNode = nodes[ i ];
-
-      uv.resize( nodes.size() );
-      for ( size_t i = 0; i < nodes.size(); ++i )
-        uv[ i ] = helper.GetNodeUV( F, nodes[ i ], inFaceNode );
-
-      // compare orientation of triangles
-      for ( int iT = 0, nbT = nodes.size()-2; iT < nbT; ++iT )
-      {
-        gp_XY v1 = uv[ iT+1 ] - uv[ 0 ];
-        gp_XY v2 = uv[ iT+2 ] - uv[ 0 ];
-        double area2D = v2 ^ v1;
-        if (( haveBadFaces = ( area2D * prevArea2D < 0 )))
-          break;
-        prevArea2D = area2D;
-      }
-    }
-
-    // Fix faces
-
-    if ( haveBadFaces )
+    if ( helper.IsDistorted2D( faceSM ))
     {
       SMESH_MeshEditor editor( helper.GetMesh() );
+      SMESHDS_SubMesh* smDS = faceSM->GetSubMeshDS();
+      const TopoDS_Face&  F = TopoDS::Face( faceSM->GetSubShape() );
 
       TIDSortedElemSet faces;
+      SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
       for ( faceIt = smDS->GetElements(); faceIt->more(); )
         faces.insert( faces.end(), faceIt->next() );
 
       // choose smoothing algo
       //SMESH_MeshEditor:: SmoothMethod algo = SMESH_MeshEditor::CENTROIDAL;
       bool isConcaveBoundary = false;
-      TError err;
-      TSideVector tgtWires =
-        StdMeshers_FaceSide::GetFaceWires( F, *helper.GetMesh(),/*skipMediumNodes=*/0, err);
       for ( size_t iW = 0; iW < tgtWires.size() && !isConcaveBoundary; ++iW )
       {
         TopoDS_Edge prevEdge = tgtWires[iW]->Edge( tgtWires[iW]->NbEdges() - 1 );
@@ -986,10 +953,15 @@ namespace {
       SMESH_MeshEditor:: SmoothMethod algo =
         isConcaveBoundary ? SMESH_MeshEditor::CENTROIDAL : SMESH_MeshEditor::LAPLACIAN;
 
+      // smooth in 2D or 3D?
+      TopLoc_Location loc;
+      Handle(Geom_Surface) surface = BRep_Tool::Surface( F, loc );
+      bool isPlanar = GeomLib_IsPlanarSurface( surface ).IsPlanar();
+
       // smoothing
       set<const SMDS_MeshNode*> fixedNodes;
       editor.Smooth( faces, fixedNodes, algo, /*nbIterations=*/ 10,
-                     /*theTgtAspectRatio=*/1.0, /*the2D=*/false);
+                     /*theTgtAspectRatio=*/1.0, /*the2D=*/!isPlanar);
     }
   }
 
@@ -1075,7 +1047,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
 
   bool done = false;
 
- if ( !done )
 if ( !done )
   {
     // try to project from the same face with different location
     done = projectPartner( tgtFace, srcFace, tgtWires, srcWires,