Salome HOME
23305: [EDF 10301] Extrusion with scaling
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
index 1c6f60200661b3dbf22012cd7ea917bd1f2bc510..f9fb06334cc561f588da2a1262c7a2f9ca49bfab 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  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
@@ -285,13 +285,13 @@ namespace MeshEditor_I {
     SMDS_MeshElement::Filter & filter = *aFilter;
 
     if ( aType == SMDSAbs_Node )
-      for (int i=0; i<IDs.length(); i++) {
+      for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
         const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
         if ( filter( elem ))
           aMap.insert( aMap.end(), elem );
       }
     else
-      for (int i=0; i<IDs.length(); i++) {
+      for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
         const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
         if ( filter( elem ))
           aMap.insert( aMap.end(), elem );
@@ -315,7 +315,7 @@ namespace MeshEditor_I {
     SMESH::long_array_var     aElementsId = theObject->GetIDs();
     if ( types->length() == 1 && types[0] == SMESH::NODE)
     {
-      for(int i = 0; i < aElementsId->length(); i++)
+      for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
         if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
           theNodeSet.insert( theNodeSet.end(), n);
     }
@@ -323,13 +323,13 @@ namespace MeshEditor_I {
     {
       SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
       while ( nIt->more( ))
-        if( const SMDS_MeshElement * elem = nIt->next() )
+        if ( const SMDS_MeshElement * elem = nIt->next() )
           theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
     }
     else
     {
-      for(int i = 0; i < aElementsId->length(); i++)
-        if( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
+      for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
+        if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
           theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
     }
   }
@@ -349,7 +349,7 @@ namespace MeshEditor_I {
     SMDSAbs_ElementType elemType    = (*theElements.begin())->GetType();
     bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
     if ( sameElemType &&
-         theMeshDS->GetMeshInfo().NbElements( elemType ) == theElements.size() )
+         theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
       return; // all the elements are in theElements
 
     if ( !sameElemType )
@@ -794,7 +794,7 @@ SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
 
   list< int > IdList;
 
-  for (int i = 0; i < IDsOfElements.length(); i++)
+  for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
     IdList.push_back( IDsOfElements[i] );
 
   // Update Python script
@@ -823,7 +823,7 @@ CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNo
   initData();
 
   list< int > IdList;
-  for (int i = 0; i < IDsOfNodes.length(); i++)
+  for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
     IdList.push_back( IDsOfNodes[i] );
 
   // Update Python script
@@ -859,9 +859,7 @@ CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
   SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
 
   // remove orphan nodes (if there are any)
-  list< int > IdList;
-  for ( int i = 0; i < seq.size(); i++ )
-    IdList.push_back( seq[i] );
+  list< int > IdList( seq.begin(), seq.end() );
 
   int nbNodesBefore = myMesh->NbNodes();
   getEditor().Remove( IdList, true );
@@ -1063,7 +1061,8 @@ CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsO
   int NbNodes = IDsOfNodes.length();
   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
   for (int i = 0; i < NbNodes; i++)
-    nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
+    if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
+      return 0;
 
   const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
 
@@ -1583,7 +1582,7 @@ CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfEleme
   SMESH_TRY;
   initData();
 
-  for (int i = 0; i < IDsOfElements.length(); i++)
+  for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
   {
     CORBA::Long index = IDsOfElements[i];
     const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
@@ -2272,7 +2271,7 @@ SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
   arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
 
   set<const SMDS_MeshNode*> fixedNodes;
-  for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
+  for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
     CORBA::Long index = IDsOfFixedNodes[i];
     const SMDS_MeshNode * node = aMesh->FindNode(index);
     if ( node )
@@ -2485,6 +2484,7 @@ namespace MeshEditor_I
     bool myIsExtrusionByNormal;
 
     static int makeFlags( CORBA::Boolean MakeGroups,
+                          CORBA::Boolean LinearVariation = false,
                           CORBA::Boolean ByAverageNormal = false,
                           CORBA::Boolean UseInputElemsOnly = false,
                           CORBA::Long    Flags = 0,
@@ -2493,18 +2493,24 @@ namespace MeshEditor_I
       if ( MakeGroups       ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
       if ( ByAverageNormal  ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
       if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
+      if ( LinearVariation  ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
       if ( MakeBoundary     ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
       return Flags;
     }
     // standard params
-    ExtrusionParams(const SMESH::DirStruct &  theDir,
-                    CORBA::Long               theNbOfSteps,
-                    CORBA::Boolean            theMakeGroups):
+    ExtrusionParams(const SMESH::DirStruct &    theDir,
+                    CORBA::Long                 theNbOfSteps,
+                    const SMESH::double_array & theScaleFactors,
+                    CORBA::Boolean              theLinearVariation,
+                    const SMESH::double_array & theBasePoint,
+                    CORBA::Boolean              theMakeGroups):
       ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
                                                 theDir.PS.y,
                                                 theDir.PS.z ),
                                         theNbOfSteps,
-                                        makeFlags( theMakeGroups )),
+                                        toList( theScaleFactors ),
+                                        TBasePoint( theBasePoint ),
+                                        makeFlags( theMakeGroups, theLinearVariation )),
       myIsExtrusionByNormal( false )
     {
     }
@@ -2518,7 +2524,9 @@ namespace MeshEditor_I
                                                 theDir.PS.y,
                                                 theDir.PS.z ),
                                         theNbOfSteps,
-                                        makeFlags( theMakeGroups, false, false,
+                                        std::list<double>(),
+                                        0,
+                                        makeFlags( theMakeGroups, false, false, false,
                                                    theExtrFlags, false ),
                                         theSewTolerance ),
       myIsExtrusionByNormal( false )
@@ -2533,7 +2541,7 @@ namespace MeshEditor_I
                     CORBA::Boolean theMakeGroups ):
       ::SMESH_MeshEditor::ExtrusParam ( theStepSize, 
                                         theNbOfSteps,
-                                        makeFlags( theMakeGroups,
+                                        makeFlags( theMakeGroups, false,
                                                    theByAverageNormal, theUseInputElemsOnly ),
                                         theDim),
       myIsExtrusionByNormal( true )
@@ -2544,6 +2552,32 @@ namespace MeshEditor_I
     {
       Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
     }
+
+  private:
+
+    static std::list<double> toList( const SMESH::double_array & theScaleFactors )
+    {
+      std::list<double> scales;
+      for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
+        scales.push_back( theScaleFactors[i] );
+      return scales;
+    }
+
+    // structure used to convert SMESH::double_array to gp_XYZ*
+    struct TBasePoint
+    {
+      gp_XYZ *pp, p;
+      TBasePoint( const SMESH::double_array & theBasePoint )
+      {
+        pp = 0;
+        if ( theBasePoint.length() == 3 )
+        {
+          p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
+          pp = &p;
+        }
+      }
+      operator const gp_XYZ*() const { return pp; }
+    };
   };
 }
 
@@ -2567,13 +2601,17 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode
                                           const SMESH::ListOfIDSources & theFaces,
                                           const SMESH::DirStruct &       theStepVector,
                                           CORBA::Long                    theNbOfSteps,
+                                          const SMESH::double_array &    theScaleFactors,
+                                          CORBA::Boolean                 theLinearVariation,
+                                          const SMESH::double_array &    theBasePoint,
                                           CORBA::Boolean                 theToMakeGroups)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
   initData();
 
-  ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
+  ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
+                          theLinearVariation, theBasePoint, theToMakeGroups );
 
   TIDSortedElemSet elemsNodes[2];
   for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
@@ -2843,7 +2881,7 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
     if ( !aMeshImp ) return aGroups._retn();
     TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
     aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
-    if ( !aSubMesh || !aSubMesh->GetSubMeshDS() )
+    if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
       return aGroups._retn();
   }
 
@@ -2865,7 +2903,7 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
     idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
 
   list<double> angles;
-  for (int i = 0; i < theAngles.length(); i++) {
+  for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) {
     angles.push_back( theAngles[i] );
   }
 
@@ -2917,13 +2955,13 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
                 << thePathShape        << ", "
                 << theNodeStart        << ", "
                 << theHasAngles        << ", "
-                << theAngles           << ", "
+                << TVar( theAngles )   << ", "
                 << theLinearVariation  << ", "
                 << theHasRefPoint      << ", "
                 << "SMESH.PointStruct( "
-                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
+                << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
+                << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
+                << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
                 << theMakeGroups       << " )";
   }
   else
@@ -4090,7 +4128,7 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
   TIDSortedNodeSet nodes;
   idSourceToNodeSet( theObject, getMeshDS(), nodes );
 
-  for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
+  for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
   {
     SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
                                                          SMESH::NODE );
@@ -4126,7 +4164,7 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
   aTPythonDump << this << ".MergeNodes([";
 
   TIDSortedNodeSet setOfNodesToKeep;
-  for ( int i = 0; i < NodesToKeep.length(); ++i )
+  for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
   {
     prepareIdSource( NodesToKeep[i] );
     SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
@@ -4135,12 +4173,12 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
   }
 
   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
-  for (int i = 0; i < GroupsOfNodes.length(); i++)
+  for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
   {
     const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
     aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
     list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
-    for ( int j = 0; j < aNodeGroup.length(); j++ )
+    for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
     {
       CORBA::Long index = aNodeGroup[ j ];
       if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
@@ -4226,11 +4264,11 @@ void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsO
 
   ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
 
-  for (int i = 0; i < GroupsOfElementsID.length(); i++) {
+  for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) {
     const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
     aListOfListOfElementsID.push_back( list< int >() );
     list< int >& aListOfElemsID = aListOfListOfElementsID.back();
-    for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
+    for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) {
       CORBA::Long id = anElemsIDGroup[ j ];
       aListOfElemsID.push_back( id );
     }
@@ -4455,7 +4493,7 @@ SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
                                            SMDSAbs_ElementType( type ),
                                            foundElems);
   res->length( foundElems.size() );
-  for ( int i = 0; i < foundElems.size(); ++i )
+  for ( size_t i = 0; i < foundElems.size(); ++i )
     res[i] = foundElems[i]->GetID();
 
   return res._retn();
@@ -4481,13 +4519,15 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID
 {
   SMESH_TRY;
   SMESH::long_array_var res = new SMESH::long_array;
-  
-  SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
-  if ( types->length() == 1 && // a part contains only nodes or 0D elements
-       ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
-       type != types[0] ) // but search of elements of dim > 0
-    return res._retn();
 
+  if ( type != SMESH::NODE )
+  {
+    SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
+    if ( types->length() == 1 && // a part contains only nodes or 0D elements
+         ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
+         type != types[0] ) // but search of elements of dim > 0
+      return res._retn();
+  }
   if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh 
     return FindElementsByPoint( x,y,z, type );
 
@@ -4501,7 +4541,8 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID
     SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
 
     if ( !idSourceToSet( elementIDs, meshDS, elements,
-                         SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
+                         ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ),
+                         /*emptyIfIsMesh=*/true))
       return res._retn();
 
     typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
@@ -4516,7 +4557,7 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID
                                            SMDSAbs_ElementType( type ),
                                            foundElems);
   res->length( foundElems.size() );
-  for ( int i = 0; i < foundElems.size(); ++i )
+  for ( size_t i = 0; i < foundElems.size(); ++i )
     res[i] = foundElems[i]->GetID();
 
   return res._retn();
@@ -4567,10 +4608,230 @@ static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Se
     RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
     RETCASE( SEW_BAD_SIDE1_NODES );
     RETCASE( SEW_BAD_SIDE2_NODES );
+    RETCASE( SEW_INTERNAL_ERROR );
   }
   return SMESH::SMESH_MeshEditor::SEW_OK;
 }
 
+//=======================================================================
+/*!
+ * Returns groups of FreeBorder's coincident within the given tolerance.
+ * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
+ * to free borders being compared is used.
+ */
+//=======================================================================
+
+SMESH::CoincidentFreeBorders*
+SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
+{
+  SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
+
+  SMESH_TRY;
+
+  SMESH_MeshAlgos::CoincidentFreeBorders cfb;
+  SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
+
+  // copy free borders
+  aCFB->borders.length( cfb._borders.size() );
+  for ( size_t i = 0; i < cfb._borders.size(); ++i )
+  {
+    SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
+    SMESH::FreeBorder&             aBRD = aCFB->borders[i];
+    aBRD.nodeIDs.length( nodes.size() );
+    for ( size_t iN = 0; iN < nodes.size(); ++iN )
+      aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
+  }
+
+  // copy coincident parts
+  aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
+  for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
+  {
+    SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
+    SMESH::FreeBordersGroup&          aGRP = aCFB->coincidentGroups[i];
+    aGRP.length( grp.size() );
+    for ( size_t iP = 0; iP < grp.size(); ++iP )
+    {
+      SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
+      SMESH::FreeBorderPart&           aPART = aGRP[ iP ];
+      aPART.border   = part._border;
+      aPART.node1    = part._node1;
+      aPART.node2    = part._node2;
+      aPART.nodeLast = part._nodeLast;
+    }
+  }
+  SMESH_CATCH( SMESH::doNothing );
+
+  TPythonDump() << "CoincidentFreeBorders = "
+                << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
+
+  return aCFB._retn();
+}
+
+//=======================================================================
+/*!
+ * Sew FreeBorder's of each group
+ */
+//=======================================================================
+
+CORBA::Short SMESH_MeshEditor_i::
+SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
+                         CORBA::Boolean                      createPolygons,
+                         CORBA::Boolean                      createPolyhedra)
+  throw (SALOME::SALOME_Exception)
+{
+  CORBA::Short nbSewed = 0;
+
+  SMESH_MeshAlgos::TFreeBorderVec groups;
+  SMESH_MeshAlgos::TFreeBorder    borderNodes; // triples of nodes for every FreeBorderPart
+
+  // check the input and collect nodes
+  for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
+  {
+    borderNodes.clear();
+    const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
+    for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
+    {
+      const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
+      if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
+        THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
+
+      const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
+
+      if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
+        THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
+      if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
+        THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
+      if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
+        THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
+
+      // do not keep these nodes for further sewing as nodes can be removed by the sewing
+      const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1    ]);
+      const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2    ]);
+      const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
+      if ( !n1)
+        THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
+      if ( !n2 )
+        THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
+      if ( !n3 )
+        THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
+
+      borderNodes.push_back( n1 );
+      borderNodes.push_back( n2 );
+      borderNodes.push_back( n3 );
+    }
+    groups.push_back( borderNodes );
+  }
+
+  // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
+  // to get nodes that replace other nodes during merge we create 0D elements
+  // on each node and MergeNodes() will replace underlying nodes of 0D elements by
+  // new ones.
+
+  vector< const SMDS_MeshElement* > tmp0Delems;
+  for ( size_t i = 0; i < groups.size(); ++i )
+  {
+    SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
+    for ( size_t iN = 0; iN < nodes.size(); ++iN )
+    {
+      SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
+      if ( it0D->more() )
+        tmp0Delems.push_back( it0D->next() );
+      else
+        tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
+    }
+  }
+
+  // cout << endl << "INIT" << endl;
+  // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
+  // {
+  //   cout << i << " ";
+  //   if ( i % 3 == 0 ) cout << "^ ";
+  //   tmp0Delems[i]->GetNode(0)->Print( cout );
+  // }
+
+  SMESH_TRY;
+
+  ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
+  int i0D = 0;
+  for ( size_t i = 0; i < groups.size(); ++i )
+  {
+    bool isBordToBord = true;
+    bool   groupSewed = false;
+    SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
+    for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
+    {
+      const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
+      const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
+      const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
+
+      const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
+      const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
+      const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
+
+      if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
+        continue;
+
+      // TIDSortedElemSet emptySet, avoidSet;
+      // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
+      // {
+      //   cout << "WRONG 2nd 1" << endl;
+      //   n0->Print( cout );
+      //   n1->Print( cout );
+      // }
+      // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
+      // {
+      //   cout << "WRONG 2nd 2" << endl;
+      //   n3->Print( cout );
+      //   n4->Print( cout );
+      // }
+
+      if ( !isBordToBord )
+      {
+        n1 = n2; // at border-to-side sewing only last side node (n1) is needed
+        n2 = 0;  //  and n2 is not used
+      }
+      // 1st border moves to 2nd
+      res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
+                                       n0 ,n1 ,n2 ,// 2nd
+                                       /*2ndIsFreeBorder=*/ isBordToBord,
+                                       createPolygons, createPolyhedra);
+      groupSewed = ( res == ok );
+
+      isBordToBord = false;
+      // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
+      // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
+      // {
+      //   cout << t << " ";
+      //   if ( t % 3 == 0 ) cout << "^ ";
+      //   tmp0Delems[t]->GetNode(0)->Print( cout );
+      // }
+    }
+    i0D += nodes.size();
+    nbSewed += groupSewed;
+  }
+
+  TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
+                << freeBorders     << ", "
+                << createPolygons  << ", "
+                << createPolyhedra << " )";
+
+  SMESH_CATCH( SMESH::doNothing );
+
+  declareMeshModified( /*isReComputeSafe=*/false );
+
+  // remove tmp 0D elements
+  SMESH_TRY;
+  set< const SMDS_MeshElement* > removed0D;
+  for ( size_t i = 0; i < tmp0Delems.size(); ++i )
+  {
+    if ( removed0D.insert( tmp0Delems[i] ).second )
+      getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
+  }
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  return nbSewed;
+}
+
 //=======================================================================
 //function : SewFreeBorders
 //purpose  :
@@ -4620,14 +4881,14 @@ SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
 
   SMESH::SMESH_MeshEditor::Sew_Error error =
     convError( getEditor().SewFreeBorder (aBorderFirstNode,
-                                       aBorderSecondNode,
-                                       aBorderLastNode,
-                                       aSide2FirstNode,
-                                       aSide2SecondNode,
-                                       aSide2ThirdNode,
-                                       true,
-                                       CreatePolygons,
-                                       CreatePolyedrs) );
+                                          aBorderSecondNode,
+                                          aBorderLastNode,
+                                          aSide2FirstNode,
+                                          aSide2SecondNode,
+                                          aSide2ThirdNode,
+                                          true,
+                                          CreatePolygons,
+                                          CreatePolyedrs) );
 
 
   declareMeshModified( /*isReComputeSafe=*/false );
@@ -4680,13 +4941,13 @@ SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
 
   SMESH::SMESH_MeshEditor::Sew_Error error =
     convError( getEditor().SewFreeBorder (aBorderFirstNode,
-                                       aBorderSecondNode,
-                                       aBorderLastNode,
-                                       aSide2FirstNode,
-                                       aSide2SecondNode,
-                                       aSide2ThirdNode,
-                                       true,
-                                       false, false) );
+                                          aBorderSecondNode,
+                                          aBorderLastNode,
+                                          aSide2FirstNode,
+                                          aSide2SecondNode,
+                                          aSide2ThirdNode,
+                                          true,
+                                          false, false) );
 
   declareMeshModified( /*isReComputeSafe=*/false );
   return error;
@@ -4742,14 +5003,14 @@ SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
 
   SMESH::SMESH_MeshEditor::Sew_Error error =
     convError( getEditor().SewFreeBorder (aBorderFirstNode,
-                                       aBorderSecondNode,
-                                       aBorderLastNode,
-                                       aSide2FirstNode,
-                                       aSide2SecondNode,
-                                       aSide2ThirdNode,
-                                       false,
-                                       CreatePolygons,
-                                       CreatePolyedrs) );
+                                          aBorderSecondNode,
+                                          aBorderLastNode,
+                                          aSide2FirstNode,
+                                          aSide2SecondNode,
+                                          aSide2ThirdNode,
+                                          false,
+                                          CreatePolygons,
+                                          CreatePolyedrs) );
 
   declareMeshModified( /*isReComputeSafe=*/false );
   return error;
@@ -5030,10 +5291,10 @@ void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump &               theDumpPytho
 */
 //================================================================================
 
-string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
+std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix)
 {
   SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
-  set<string> groupNames;
+  set<std::string> groupNames;
 
   // Get existing group names
   for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
@@ -5046,7 +5307,7 @@ string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
   }
 
   // Find new name
-  string name = thePrefix;
+  std::string name = thePrefix;
   int index = 0;
 
   while (!groupNames.insert(name).second)
@@ -5085,7 +5346,7 @@ bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr  theIDSource,
 {
   if ( error ) *error = IDSource_OK;
 
-  if ( CORBA::is_nil( theIDSource ) )
+  if ( CORBA::is_nil( theIDSource ))
   {
     if ( error ) *error = IDSource_INVALID;
     return false;
@@ -5354,8 +5615,8 @@ SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
     // Create group with newly created nodes
     SMESH::long_array_var anIds = GetLastCreatedNodes();
     if (anIds->length() > 0) {
-      string anUnindexedName (theNodes->GetName());
-      string aNewName = generateGroupName(anUnindexedName + "_double");
+      std::string anUnindexedName (theNodes->GetName());
+      std::string aNewName = generateGroupName(anUnindexedName + "_double");
       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
       aNewGroup->Add(anIds);
       pyDump << aNewGroup << " = ";
@@ -5453,8 +5714,8 @@ SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
     // Create group with newly created nodes
     SMESH::long_array_var anIds = GetLastCreatedNodes();
     if (anIds->length() > 0) {
-      string anUnindexedName (theNodes[0]->GetName());
-      string aNewName = generateGroupName(anUnindexedName + "_double");
+      std::string anUnindexedName (theNodes[0]->GetName());
+      std::string aNewName = generateGroupName(anUnindexedName + "_double");
       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
       aNewGroup->Add(anIds);
       pyDump << aNewGroup << " = ";
@@ -5678,7 +5939,7 @@ SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
   {
     // Create group with newly created elements
     CORBA::String_var elemGroupName = theElems->GetName();
-    string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
+    std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
     if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
     {
       SMESH::long_array_var anIds = GetLastCreatedElems();
@@ -5910,7 +6171,7 @@ SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems
   {
     // Create group with newly created elements
     CORBA::String_var elemGroupName = theElems[0]->GetName();
-    string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
+    std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
     if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
     {
       SMESH::long_array_var anIds = GetLastCreatedElems();
@@ -6280,7 +6541,7 @@ void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double                  radius,
     theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
 
   vector<double> nodesCoords;
-  for (int i = 0; i < theNodesCoords.length(); i++)
+  for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
   {
     nodesCoords.push_back( theNodesCoords[i] );
   }
@@ -6441,12 +6702,12 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
 
   // separate groups belonging to this and other mesh
-  SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
+  SMESH::ListOfIDSources_var groupsOfThisMesh  = new SMESH::ListOfIDSources;
   SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
-  groupsOfThisMesh->length( groups.length() );
+  groupsOfThisMesh ->length( groups.length() );
   groupsOfOtherMesh->length( groups.length() );
   int nbGroups = 0, nbGroupsOfOtherMesh = 0;
-  for ( int i = 0; i < groups.length(); ++i )
+  for ( CORBA::ULong i = 0; i < groups.length(); ++i )
   {
     SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
     if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))