Salome HOME
23617: EDF 14133 - Complete Merge Nodes / Merge Elements operations
[modules/smesh.git] / src / SMESH / SMESH_MeshEditor.cxx
index d06ce73062e66f972b1c4fb3220c5b04e0fb1362..81db6b65f296d5cd3ed12332810c2732bd98efcc 100644 (file)
@@ -97,7 +97,6 @@
 
 #include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx>
-#include <OSD_Parallel.hxx>
 
 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
 
@@ -1423,7 +1422,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
     const SMDS_MeshElement* newElem1 = 0;
     const SMDS_MeshElement* newElem2 = 0;
 
-    if ( !elem->IsQuadratic() ) // split liner quadrangle
+    if ( !elem->IsQuadratic() ) // split linear quadrangle
     {
       // for MaxElementLength2D functor we return minimum diagonal for splitting,
       // because aBadRate1=2*len(diagonal 1-3); aBadRate2=2*len(diagonal 2-4)
@@ -6354,7 +6353,7 @@ SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet                  theElemSets
             gp_Vec aV01x( aP0x, aP1x );
             aTrsf.SetTranslation( aV01x );
 
-            // traslated point
+            // translated point
             aV1x = aV0x.Transformed( aTrsf );
             aPN1 = aPN0.Transformed( aTrsf );
 
@@ -6741,6 +6740,7 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem
                                                       const double       theValue,
                                                       SMESH_Mesh*        theTgtMesh,
                                                       const bool         theMakeGroups,
+                                                      const bool         theCopyElements,
                                                       const bool         theFixSelfIntersection)
 {
   SMESHDS_Mesh*    meshDS = GetMeshDS();
@@ -6751,15 +6751,27 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem
   if ( theElements.empty() ) eIt = meshDS->elementsIterator( SMDSAbs_Face );
   else                       eIt = SMESHUtils::elemSetIterator( theElements );
 
-  SMESH_MeshAlgos::TEPairVec new2OldFaces;
-  SMESH_MeshAlgos::TNPairVec new2OldNodes;
+  SMESH_MeshAlgos::TElemIntPairVec new2OldFaces;
+  SMESH_MeshAlgos::TNodeIntPairVec new2OldNodes;
   std::unique_ptr< SMDS_Mesh > offsetMesh
     ( SMESH_MeshAlgos::MakeOffset( eIt, *meshDS, theValue,
                                    theFixSelfIntersection,
                                    new2OldFaces, new2OldNodes ));
+  if ( offsetMesh->NbElements() == 0 )
+    return PGroupIDs(); // MakeOffset() failed
 
-  offsetMesh->Modified();
-  offsetMesh->CompactMesh(); // make IDs start from 1
+
+  if ( theTgtMesh == myMesh && !theCopyElements )
+  {
+    // clear the source elements
+    if ( theElements.empty() ) eIt = meshDS->elementsIterator( SMDSAbs_Face );
+    else                       eIt = SMESHUtils::elemSetIterator( theElements );
+    while ( eIt->more() )
+      meshDS->RemoveFreeElement( eIt->next(), 0 );
+  }
+
+  // offsetMesh->Modified();
+  // offsetMesh->CompactMesh(); // make IDs start from 1
 
   // source elements for each generated one
   SMESH_SequenceOfElemPtr srcElems, srcNodes;
@@ -6776,12 +6788,14 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem
   for ( size_t i = 0; i < new2OldNodes.size(); ++i )
     if ( const SMDS_MeshNode* n = new2OldNodes[ i ].first )
     {
+#ifndef _DEBUG_
       if ( n->NbInverseElements() > 0 )
+#endif
       {
         const SMDS_MeshNode* n2 =
           tgtMeshDS->AddNodeWithID( n->X(), n->Y(), n->Z(), idShift + n->GetID() );
         myLastCreatedNodes.push_back( n2 );
-        srcNodes.push_back( new2OldNodes[ i ].second );
+        srcNodes.push_back( meshDS->FindNode( new2OldNodes[ i ].second ));
       }
     }
 
@@ -6797,7 +6811,7 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem
         elemType.myNodes.push_back( tgtMeshDS->FindNode( idShift + n2->GetID() ));
       }
       tgtEditor.AddElement( elemType.myNodes, elemType );
-      srcElems.push_back( new2OldFaces[ i ].second );
+      srcElems.push_back( meshDS->FindElement( new2OldFaces[ i ].second ));
     }
 
   myLastCreatedElems.swap( tgtEditor.myLastCreatedElems );
@@ -8486,6 +8500,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
     {
       const SMDS_MeshElement* elem = (*insertMapIt).first;
       list<const SMDS_MeshNode*> & nodeList = (*insertMapIt).second;
+      if ( nodeList.size() < 3 ) continue;
       const SMDS_MeshNode* n1 = nodeList.front(); nodeList.pop_front();
       const SMDS_MeshNode* n2 = nodeList.front(); nodeList.pop_front();
 
@@ -10926,7 +10941,7 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements )
   }
   else
   {
-    type = (*theElements.begin())->GetType();
+    //type = (*theElements.begin())->GetType();
     elemIt = SMESHUtils::elemSetIterator( theElements );
   }
 
@@ -10941,7 +10956,8 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements )
   while ( elemIt->more() )
   {
     const SMDS_MeshElement* elem = elemIt->next();
-    if ( elem->GetType() != type || elem->isMarked() )
+    if (( type != SMDSAbs_All && elem->GetType() != type ) ||
+        ( elem->isMarked() ))
       continue;
 
     elemType.Init( elem, /*basicOnly=*/false );
@@ -11214,8 +11230,8 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl
   else
   {
     const double aTol = Precision::Confusion();
-    auto_ptr< BRepClass3d_SolidClassifier> bsc3d;
-    auto_ptr<_FaceClassifier>              aFaceClassifier;
+    std::unique_ptr< BRepClass3d_SolidClassifier> bsc3d;
+    std::unique_ptr<_FaceClassifier>              aFaceClassifier;
     if ( theShape.ShapeType() == TopAbs_SOLID )
     {
       bsc3d.reset( new BRepClass3d_SolidClassifier(theShape));;
@@ -11735,12 +11751,11 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   //MESSAGE(".. Creation of elements: simple junction");
   if (createJointElems)
   {
-    int idg;
     string joints2DName = "joints2D";
-    mapOfJunctionGroups[joints2DName] = this->myMesh->AddGroup(SMDSAbs_Face, joints2DName.c_str(), idg);
+    mapOfJunctionGroups[joints2DName] = this->myMesh->AddGroup(SMDSAbs_Face, joints2DName.c_str());
     SMESHDS_Group *joints2DGrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[joints2DName]->GetGroupDS());
     string joints3DName = "joints3D";
-    mapOfJunctionGroups[joints3DName] = this->myMesh->AddGroup(SMDSAbs_Volume, joints3DName.c_str(), idg);
+    mapOfJunctionGroups[joints3DName] = this->myMesh->AddGroup(SMDSAbs_Volume, joints3DName.c_str());
     SMESHDS_Group *joints3DGrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[joints3DName]->GetGroupDS());
 
     itface = faceDomains.begin();
@@ -11768,7 +11783,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
         grpname << dom2 << "_" << dom1;
       string namegrp = grpname.str();
       if (!mapOfJunctionGroups.count(namegrp))
-        mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(vol->GetType(), namegrp.c_str(), idg);
+        mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(vol->GetType(), namegrp.c_str());
       SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
       if (sgrp)
         sgrp->Add(vol->GetID());
@@ -11801,10 +11816,9 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
       stringstream grpname;
       grpname << "m2j_";
       grpname << 0 << "_" << 0;
-      int idg;
       string namegrp = grpname.str();
       if (!mapOfJunctionGroups.count(namegrp))
-        mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Face, namegrp.c_str(), idg);
+        mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Face, namegrp.c_str());
       SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
       if (sgrp)
         sgrp->Add(face->GetID());
@@ -11830,10 +11844,9 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
               orderedNodes.push_back( nodeDomains[ nodes[ ino ]][ orderDom[ idom ]]);
         SMDS_MeshVolume* vol = this->GetMeshDS()->AddVolumeFromVtkIds(orderedNodes);
 
-        int idg;
         string namegrp = "jointsMultiples";
         if (!mapOfJunctionGroups.count(namegrp))
-          mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
+          mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str());
         SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
         if (sgrp)
           sgrp->Add(vol->GetID());
@@ -12091,10 +12104,9 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSort
         stringstream grpname;
         grpname << "jf_";
         grpname << idom;
-        int idg;
         string namegrp = grpname.str();
         if (!mapOfJunctionGroups.count(namegrp))
-          mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
+          mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str());
         SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
         if (sgrp)
           sgrp->Add(vol->GetID());
@@ -12165,10 +12177,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
 
   // --- define groups to build
 
-  int idg; // --- group of SMDS volumes
+  // --- group of SMDS volumes
   string grpvName = groupName;
   grpvName += "_vol";
-  SMESH_Group *grp = this->myMesh->AddGroup(SMDSAbs_Volume, grpvName.c_str(), idg);
+  SMESH_Group *grp = this->myMesh->AddGroup(SMDSAbs_Volume, grpvName.c_str());
   if (!grp)
   {
     MESSAGE("group not created " << grpvName);
@@ -12176,10 +12188,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   }
   SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(grp->GetGroupDS());
 
-  int idgs; // --- group of SMDS faces on the skin
+  // --- group of SMDS faces on the skin
   string grpsName = groupName;
   grpsName += "_skin";
-  SMESH_Group *grps = this->myMesh->AddGroup(SMDSAbs_Face, grpsName.c_str(), idgs);
+  SMESH_Group *grps = this->myMesh->AddGroup(SMDSAbs_Face, grpsName.c_str());
   if (!grps)
   {
     MESSAGE("group not created " << grpsName);
@@ -12187,10 +12199,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   }
   SMESHDS_Group *sgrps = dynamic_cast<SMESHDS_Group*>(grps->GetGroupDS());
 
-  int idgi; // --- group of SMDS faces internal (several shapes)
+  // --- group of SMDS faces internal (several shapes)
   string grpiName = groupName;
   grpiName += "_internalFaces";
-  SMESH_Group *grpi = this->myMesh->AddGroup(SMDSAbs_Face, grpiName.c_str(), idgi);
+  SMESH_Group *grpi = this->myMesh->AddGroup(SMDSAbs_Face, grpiName.c_str());
   if (!grpi)
   {
     MESSAGE("group not created " << grpiName);
@@ -12198,10 +12210,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   }
   SMESHDS_Group *sgrpi = dynamic_cast<SMESHDS_Group*>(grpi->GetGroupDS());
 
-  int idgei; // --- group of SMDS faces internal (several shapes)
+  // --- group of SMDS faces internal (several shapes)
   string grpeiName = groupName;
   grpeiName += "_internalEdges";
-  SMESH_Group *grpei = this->myMesh->AddGroup(SMDSAbs_Edge, grpeiName.c_str(), idgei);
+  SMESH_Group *grpei = this->myMesh->AddGroup(SMDSAbs_Edge, grpeiName.c_str());
   if (!grpei)
   {
     MESSAGE("group not created " << grpeiName);
@@ -12683,7 +12695,7 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D()
       // add new face based on volume nodes
       if (aMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false) )
       {
-        nbExisted++; // face already exsist
+        nbExisted++; // face already exists
       }
       else
       {
@@ -12883,7 +12895,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
         tgtNodes.resize( srcNodes.size() );
         for ( inode = 0; inode < srcNodes.size(); ++inode )
           tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] );
-        if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( tgtNodes,
+        if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( tgtNodes,
                                                                    missType,
                                                                    /*noMedium=*/false))
           continue;
@@ -12894,7 +12906,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
       for ( size_t i = 0; i < missingBndElems.size(); ++i )
       {
         TConnectivity& nodes = missingBndElems[ i ];
-        if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes,
+        if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( nodes,
                                                                    missType,
                                                                    /*noMedium=*/false))
           continue;
@@ -13025,482 +13037,3 @@ void SMESH_MeshEditor::copyPosition( const SMDS_MeshNode* from,
   default:;
   }
 }
-
-namespace // utils for MakePolyLine
-{
-  //================================================================================
-  /*!
-   * \brief Sequence of found points and a current point data
-   */
-  struct Path
-  {
-    std::vector< gp_XYZ >   myPoints;
-    double                  myLength;
-
-    int                     mySrcPntInd; //!< start point index
-    const SMDS_MeshElement* myFace;
-    SMESH_NodeXYZ           myNode1;
-    SMESH_NodeXYZ           myNode2;
-    int                     myNodeInd1;
-    int                     myNodeInd2;
-    double                  myDot1;
-    double                  myDot2;
-    TIDSortedElemSet        myElemSet, myAvoidSet;
-
-    Path(): myLength(0.0), myFace(0) {}
-
-    bool SetCutAtCorner( const SMESH_NodeXYZ&    cornerNode,
-                         const SMDS_MeshElement* face,
-                         const gp_XYZ&           plnNorm,
-                         const gp_XYZ&           plnOrig );
-
-    void AddPoint( const gp_XYZ& p );
-
-    bool Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig );
-
-    bool ReachSamePoint( const Path& other );
-
-    static void Remove( std::vector< Path > & paths, size_t& i );
-  };
-
-  //================================================================================
-  /*!
-   * \brief Return true if this Path meats another
-   */
-  //================================================================================
-
-  bool Path::ReachSamePoint( const Path& other )
-  {
-    return ( mySrcPntInd != other.mySrcPntInd &&
-             myFace == other.myFace );
-  }
-
-  //================================================================================
-  /*!
-   * \brief Remove a path from a vector
-   */
-  //================================================================================
-
-  void Path::Remove( std::vector< Path > & paths, size_t& i )
-  {
-    if ( paths.size() > 1 )
-    {
-      size_t j = paths.size() - 1; // last item to be removed
-      if ( i < j )
-      {
-        paths[ i ].myPoints.swap( paths[ j ].myPoints );
-        paths[ i ].myLength    = paths[ j ].myLength;
-        paths[ i ].mySrcPntInd = paths[ j ].mySrcPntInd;
-        paths[ i ].myFace      = paths[ j ].myFace;
-        paths[ i ].myNode1     = paths[ j ].myNode1;
-        paths[ i ].myNode2     = paths[ j ].myNode2;
-        paths[ i ].myNodeInd1  = paths[ j ].myNodeInd1;
-        paths[ i ].myNodeInd2  = paths[ j ].myNodeInd2;
-        paths[ i ].myDot1      = paths[ j ].myDot1;
-        paths[ i ].myDot2      = paths[ j ].myDot2;
-      }
-    }
-    paths.pop_back();
-    if ( i > 0 )
-      --i;
-  }
-
-  //================================================================================
-  /*!
-   * \brief Store a point that is at a node of a face if the face is intersected by plane.
-   *        Return false if the node is a sole intersection point of the face and the plane
-   */
-  //================================================================================
-
-  bool Path::SetCutAtCorner( const SMESH_NodeXYZ&    cornerNode,
-                             const SMDS_MeshElement* face,
-                             const gp_XYZ&           plnNorm,
-                             const gp_XYZ&           plnOrig )
-  {
-    if ( face == myFace )
-      return false;
-    myNodeInd1 = face->GetNodeIndex( cornerNode._node );
-    myNodeInd2 = ( myNodeInd1 + 1 ) % face->NbCornerNodes();
-    int   ind3 = ( myNodeInd1 + 2 ) % face->NbCornerNodes();
-    myNode1.Set( face->GetNode( ind3 ));
-    myNode2.Set( face->GetNode( myNodeInd2 ));
-
-    myDot1 = plnNorm * ( myNode1 - plnOrig );
-    myDot2 = plnNorm * ( myNode2 - plnOrig );
-
-    bool ok = ( myDot1 * myDot2 < 0 );
-    if ( !ok && myDot1 * myDot2 == 0 )
-    {
-      ok = ( myDot1 != myDot2 );
-      if ( ok && myFace )
-        ok = ( myFace->GetNodeIndex(( myDot1 == 0 ? myNode1 : myNode2 )._node ) < 0 );
-    }
-    if ( ok )
-    {
-      myFace = face;
-      myDot1 = 0;
-      AddPoint( cornerNode );
-    }
-    return ok;
-  }
-
-  //================================================================================
-  /*!
-   * \brief Store a point and update myLength
-   */
-  //================================================================================
-
-  void Path::AddPoint( const gp_XYZ& p )
-  {
-    if ( !myPoints.empty() )
-      myLength += ( p - myPoints.back() ).Modulus();
-    else
-      myLength = 0;
-    myPoints.push_back( p );
-  }
-
-  //================================================================================
-  /*!
-   * \brief Try to find the next point
-   *  \param [in] plnNorm - cutting plane normal
-   *  \param [in] plnOrig - cutting plane origin
-   */
-  //================================================================================
-
-  bool Path::Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig )
-  {
-    int nodeInd3 = ( myNodeInd1 + 1 ) % myFace->NbCornerNodes();
-    if ( myNodeInd2 == nodeInd3 )
-      nodeInd3 = ( myNodeInd1 + 2 ) % myFace->NbCornerNodes();
-
-    SMESH_NodeXYZ node3 = myFace->GetNode( nodeInd3 );
-    double         dot3 = plnNorm * ( node3 - plnOrig );
-
-    if ( dot3 * myDot1 < 0. )
-    {
-      myNode2    = node3;
-      myNodeInd2 = nodeInd3;
-      myDot2     = dot3;
-    }
-    else if ( dot3 * myDot2 < 0. )
-    {
-      myNode1    = node3;
-      myNodeInd1 = nodeInd3;
-      myDot1     = dot3;
-    }
-    else if ( dot3 == 0. )
-    {
-      SMDS_ElemIteratorPtr fIt = node3._node->GetInverseElementIterator(SMDSAbs_Face);
-      while ( fIt->more() )
-        if ( SetCutAtCorner( node3, fIt->next(), plnNorm, plnOrig ))
-          return true;
-      return false;
-    }
-    else if ( myDot2 == 0. )
-    {
-      SMESH_NodeXYZ node2 = myNode2; // copy as myNode2 changes in SetCutAtCorner()
-      SMDS_ElemIteratorPtr fIt = node2._node->GetInverseElementIterator(SMDSAbs_Face);
-      while ( fIt->more() )
-        if ( SetCutAtCorner( node2, fIt->next(), plnNorm, plnOrig ))
-          return true;
-      return false;
-    }
-
-    double r = Abs( myDot1 / ( myDot2 - myDot1 ));
-    AddPoint( myNode1 * ( 1 - r ) + myNode2 * r );
-
-    myAvoidSet.clear();
-    myAvoidSet.insert( myFace );
-    myFace = SMESH_MeshAlgos::FindFaceInSet( myNode1._node, myNode2._node,
-                                             myElemSet,   myAvoidSet,
-                                             &myNodeInd1, &myNodeInd2 );
-    return myFace;
-  }
-
-  //================================================================================
-  /*!
-   * \brief Compute a path between two points of PolySegment
-   */
-  struct PolyPathCompute
-  {
-    SMESH_MeshEditor::TListOfPolySegments& mySegments; //!< inout PolySegment's
-    std::vector< Path >&                   myPaths;    //!< path of each of segments to compute
-    SMESH_Mesh*                            myMesh;
-    mutable std::vector< std::string >     myErrors;
-
-    PolyPathCompute( SMESH_MeshEditor::TListOfPolySegments& theSegments,
-                     std::vector< Path >&                   thePaths,
-                     SMESH_Mesh*                            theMesh):
-      mySegments( theSegments ),
-      myPaths( thePaths ),
-      myMesh( theMesh ),
-      myErrors( theSegments.size() )
-    {
-    }
-#undef SMESH_CAUGHT
-#define SMESH_CAUGHT myErrors[i] =
-    void operator() ( const int i ) const
-    {
-      SMESH_TRY;
-      const_cast< PolyPathCompute* >( this )->Compute( i );
-      SMESH_CATCH( SMESH::returnError );
-    }
-#undef SMESH_CAUGHT
-    //================================================================================
-    /*!
-     * \brief Compute a path of a given segment
-     */
-    //================================================================================
-
-    void Compute( const int iSeg )
-    {
-      SMESH_MeshEditor::PolySegment& polySeg = mySegments[ iSeg ];
-
-      // get a cutting plane
-
-      gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] );
-      gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] );
-      if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
-      if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
-
-      gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
-      gp_XYZ plnOrig = p2;
-
-      // find paths connecting the 2 end points of polySeg
-
-      std::vector< Path > paths; paths.reserve(10);
-
-      // initialize paths
-
-      for ( int iP = 0; iP < 2; ++iP ) // loop on the polySeg end points
-      {
-        Path path;
-        path.mySrcPntInd = iP;
-        size_t nbPaths = paths.size();
-
-        if ( polySeg.myNode2[ iP ] && polySeg.myNode2[ iP ] != polySeg.myNode1[ iP ] )
-        {
-          while (( path.myFace = SMESH_MeshAlgos::FindFaceInSet( polySeg.myNode1[ iP ],
-                                                                 polySeg.myNode2[ iP ],
-                                                                 path.myElemSet,
-                                                                 path.myAvoidSet,
-                                                                 &path.myNodeInd1,
-                                                                 &path.myNodeInd2 )))
-          {
-            path.myNode1.Set( polySeg.myNode1[ iP ]);
-            path.myNode2.Set( polySeg.myNode2[ iP ]);
-            path.myDot1 = plnNorm * ( path.myNode1 - plnOrig );
-            path.myDot2 = plnNorm * ( path.myNode2 - plnOrig );
-            path.myPoints.clear();
-            path.AddPoint( 0.5 * ( path.myNode1 + path.myNode2 ));
-            path.myAvoidSet.insert( path.myFace );
-            paths.push_back( path );
-          }
-          if ( nbPaths == paths.size() )
-            throw SALOME_Exception ( SMESH_Comment("No face edge found by point ") << iP+1
-                                     << " in a PolySegment " << iSeg );
-        }
-        else // an end point is at node
-        {
-          std::set<const SMDS_MeshNode* > nodes;
-          SMDS_ElemIteratorPtr fIt = polySeg.myNode1[ iP ]->GetInverseElementIterator(SMDSAbs_Face);
-          while ( fIt->more() )
-          {
-            path.myPoints.clear();
-            if ( path.SetCutAtCorner( polySeg.myNode1[ iP ], fIt->next(), plnNorm, plnOrig ))
-            {
-              if (( path.myDot1 * path.myDot2 != 0 ) ||
-                  ( nodes.insert( path.myDot1 == 0 ? path.myNode1._node : path.myNode2._node ).second ))
-                paths.push_back( path );
-            }
-          }
-        }
-
-        // look for a one-segment path
-        for ( size_t i = 0; i < nbPaths; ++i )
-          for ( size_t j = nbPaths; j < paths.size(); ++j )
-            if ( paths[i].myFace == paths[j].myFace )
-            {
-              myPaths[ iSeg ].myPoints.push_back( paths[i].myPoints[0] );
-              myPaths[ iSeg ].myPoints.push_back( paths[j].myPoints[0] );
-              paths.clear();
-            }
-      }
-
-      // extend paths
-
-      myPaths[ iSeg ].myLength = 1e100;
-
-      while ( paths.size() >= 2 )
-      {
-        for ( size_t i = 0; i < paths.size(); ++i )
-        {
-          Path& path = paths[ i ];
-          if ( !path.Extend( plnNorm, plnOrig ) ||         // path reached a mesh boundary
-               path.myLength > myPaths[ iSeg ].myLength ) // path is longer than others
-          {
-            Path::Remove( paths, i );
-            continue;
-          }
-
-          // join paths that reach same point
-          for ( size_t j = 0; j < paths.size(); ++j )
-          {
-            if ( i != j && paths[i].ReachSamePoint( paths[j] ))
-            {
-              double   distLast = ( paths[i].myPoints.back() - paths[j].myPoints.back() ).Modulus();
-              double fullLength = ( paths[i].myLength + paths[j].myLength + distLast );
-              if ( fullLength < myPaths[ iSeg ].myLength )
-              {
-                myPaths[ iSeg ].myLength = fullLength;
-                std::vector< gp_XYZ > & allPoints = myPaths[ iSeg ].myPoints;
-                allPoints.swap( paths[i].myPoints );
-                allPoints.insert( allPoints.end(),
-                                  paths[j].myPoints.rbegin(),
-                                  paths[j].myPoints.rend() );
-              }
-              Path::Remove( paths, i );
-              Path::Remove( paths, j );
-            }
-          }
-        }
-        if ( !paths.empty() && (int) paths[0].myPoints.size() > myMesh->NbFaces() )
-          throw SALOME_Exception(LOCALIZED( "Infinite loop in MakePolyLine()"));
-      }
-
-      if ( myPaths[ iSeg ].myPoints.empty() )
-        throw SALOME_Exception( SMESH_Comment("Can't find a full path for PolySegment #") << iSeg );
-
-    } // PolyPathCompute::Compute()
-
-  }; // struct PolyPathCompute
-
-} // namespace
-
-//=======================================================================
-//function : MakePolyLine
-//purpose  : Create a polyline consisting of 1D mesh elements each lying on a 2D element of
-//           the initial mesh
-//=======================================================================
-
-void SMESH_MeshEditor::MakePolyLine( TListOfPolySegments&   theSegments,
-                                     SMESHDS_Group*         theGroup,
-                                     SMESH_ElementSearcher* theSearcher)
-{
-  std::vector< Path > segPaths( theSegments.size() ); // path of each of segments
-
-  SMESH_ElementSearcher* searcher = theSearcher;
-  SMESHUtils::Deleter<SMESH_ElementSearcher> delSearcher;
-  if ( !searcher )
-  {
-    searcher = SMESH_MeshAlgos::GetElementSearcher( *GetMeshDS() );
-    delSearcher._obj = searcher;
-  }
-
-  // get cutting planes
-
-  std::vector< bool > isVectorOK( theSegments.size(), true );
-  const double planarCoef = 0.333; // plane height in planar case
-
-  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
-  {
-    PolySegment& polySeg = theSegments[ iSeg ];
-
-    gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] );
-    gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] );
-    if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
-    if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
-
-    gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
-
-    isVectorOK[ iSeg ] = ( plnNorm.Modulus() > std::numeric_limits<double>::min() );
-    if ( !isVectorOK[ iSeg ])
-    {
-      gp_XYZ pMid = 0.5 * ( p1 + p2 );
-      const SMDS_MeshElement* face;
-      polySeg.myMidProjPoint = searcher->Project( pMid, SMDSAbs_Face, &face );
-      polySeg.myVector       = polySeg.myMidProjPoint.XYZ() - pMid;
-
-      gp_XYZ faceNorm;
-      SMESH_MeshAlgos::FaceNormal( face, faceNorm );
-
-      if ( polySeg.myVector.Magnitude() < Precision::Confusion() ||
-           polySeg.myVector * faceNorm  < Precision::Confusion() )
-      {
-        polySeg.myVector = faceNorm;
-        polySeg.myMidProjPoint = pMid + faceNorm * ( p1 - p2 ).Modulus() * planarCoef;
-      }
-    }
-    else
-    {
-      polySeg.myVector = plnNorm ^ ( p1 - p2 );
-    }
-  }
-
-  // assure that inverse elements are constructed, avoid their concurrent building in threads
-  GetMeshDS()->nodesIterator()->next()->NbInverseElements();
-
-  // find paths
-
-  PolyPathCompute algo( theSegments, segPaths, myMesh );
-  OSD_Parallel::For( 0, theSegments.size(), algo, theSegments.size() == 1 );
-
-  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
-    if ( !algo.myErrors[ iSeg ].empty() )
-      throw SALOME_Exception( algo.myErrors[ iSeg ].c_str() );
-
-  // create an 1D mesh
-
-  const SMDS_MeshNode *n, *nPrev = 0;
-  SMESHDS_Mesh* mesh = GetMeshDS();
-
-  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
-  {
-    const Path& path = segPaths[iSeg];
-    if ( path.myPoints.size() < 2 )
-      continue;
-
-    double tol = path.myLength / path.myPoints.size() / 1000.;
-    if ( !nPrev || ( SMESH_NodeXYZ( nPrev ) - path.myPoints[0] ).SquareModulus() > tol*tol )
-    {
-      nPrev = mesh->AddNode( path.myPoints[0].X(), path.myPoints[0].Y(), path.myPoints[0].Z() );
-      myLastCreatedNodes.push_back( nPrev );
-    }
-    for ( size_t iP = 1; iP < path.myPoints.size(); ++iP )
-    {
-      n = mesh->AddNode( path.myPoints[iP].X(), path.myPoints[iP].Y(), path.myPoints[iP].Z() );
-      myLastCreatedNodes.push_back( n );
-
-      const SMDS_MeshElement* elem = mesh->AddEdge( nPrev, n );
-      myLastCreatedElems.push_back( elem );
-      if ( theGroup )
-        theGroup->Add( elem );
-
-      nPrev = n;
-    }
-
-    // return a vector
-
-    gp_XYZ pMid = 0.5 * ( path.myPoints[0] + path.myPoints.back() );
-    if ( isVectorOK[ iSeg ])
-    {
-      // find the most distance point of a path
-      double maxDist = 0;
-      for ( size_t iP = 1; iP < path.myPoints.size(); ++iP )
-      {
-        double dist = Abs( theSegments[iSeg].myVector * ( path.myPoints[iP] - path.myPoints[0] ));
-        if ( dist > maxDist )
-        {
-          maxDist = dist;
-          theSegments[iSeg].myMidProjPoint = path.myPoints[iP];
-        }
-      }
-      if ( maxDist < Precision::Confusion() ) // planar case
-        theSegments[iSeg].myMidProjPoint =
-          pMid + theSegments[iSeg].myVector.XYZ().Normalized() * path.myLength * planarCoef;
-    }
-    theSegments[iSeg].myVector = gp_Vec( pMid, theSegments[iSeg].myMidProjPoint );
-  }
-
-  return;
-}