Salome HOME
Merge V8_4_BR branch.
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
index a99acd2f68a0b38478bfde505718539e0204667b..9a0f20ff74e3dd97313b087219878de167a02d0c 100644 (file)
@@ -64,7 +64,6 @@
 #include <Utils_CorbaException.hxx>
 #include <SALOMEDS_wrap.hxx>
 #include <SALOME_GenericObj_i.hh>
-#include <Basics_OCCTVersion.hxx>
 
 #include <BRepAdaptor_Surface.hxx>
 #include <BRep_Tool.hxx>
 #include <gp_Ax2.hxx>
 #include <gp_Vec.hxx>
 
-#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
-#define NO_CAS_CATCH
-#endif
-
 #include <Standard_Failure.hxx>
-
-#ifdef NO_CAS_CATCH
 #include <Standard_ErrorHandler.hxx>
-#endif
 
 #include <sstream>
 #include <limits>
@@ -184,7 +176,7 @@ namespace MeshEditor_I {
 
   //=============================================================================
   /*!
-   * \brief Deleter of theNodeSearcher at any compute event occured
+   * \brief Deleter of theNodeSearcher at any compute event occurred
    */
   //=============================================================================
 
@@ -467,9 +459,9 @@ void SMESH_MeshEditor_i::initData(bool deleteSearchers)
 //================================================================================
 /*!
  * \brief Increment mesh modif time and optionally record that the performed
- *        modification may influence futher mesh re-compute.
+ *        modification may influence further mesh re-compute.
  *  \param [in] isReComputeSafe - true if the modification does not influence
- *              futher mesh re-compute
+ *              further mesh re-compute
  */
 //================================================================================
 
@@ -501,7 +493,7 @@ void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
  * \brief Initialize and return myPreviewMesh
  *  \param previewElements - type of elements to show in preview
  *
- *  WARNING: call it once par a method!
+ *  WARNING: call it once per method!
  */
 //================================================================================
 
@@ -669,7 +661,7 @@ void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
 
 //=======================================================================
 /*
- * Returns description of an error/warning occured during the last operation
+ * Returns description of an error/warning occurred during the last operation
  * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
  */
 //=======================================================================
@@ -1151,6 +1143,10 @@ CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
                                         n[15],n[16],n[17],n[18],n[19]);
     break;
+  case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
+                                        n[8],n[9],n[10],n[11],n[12],n[13],n[14],
+                                        n[15],n[16],n[17]);
+    break;
   case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
                                         n[15],n[16],n[17],n[18],n[19],
@@ -2952,8 +2948,9 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
   }
 
   if ( !myIsPreviewMode ) {
-    aPythonDump << "(" << aGroups << ", error) = "
-                << this << ".ExtrusionAlongPathObjects( "
+    if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
+    else                         aPythonDump << "(_noGroups, error) = ";
+    aPythonDump << this << ".ExtrusionAlongPathObjects( "
                 << theNodes            << ", "
                 << theEdges            << ", "
                 << theFaces            << ", "
@@ -3107,17 +3104,14 @@ SMESH_MeshEditor_i::mirror(TIDSortedElemSet &                  theElements,
   ::SMESH_MeshEditor::PGroupIDs groupIds =
       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
 
-  if ( theCopy && !myIsPreviewMode)
+  if ( !myIsPreviewMode )
   {
     if ( theTargetMesh )
-    {
       theTargetMesh->GetMeshDS()->Modified();
-    }
     else
-    {
       declareMeshModified( /*isReComputeSafe=*/false );
-    }
   }
+
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
 
   SMESH_CATCH( SMESH::throwCorbaException );
@@ -3374,16 +3368,12 @@ SMESH_MeshEditor_i::translate(TIDSortedElemSet        & theElements,
   ::SMESH_MeshEditor::PGroupIDs groupIds =
       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
 
-  if ( theCopy && !myIsPreviewMode )
+  if ( !myIsPreviewMode )
   {
     if ( theTargetMesh )
-    {
       theTargetMesh->GetMeshDS()->Modified();
-    }
     else
-    {
       declareMeshModified( /*isReComputeSafe=*/false );
-    }
   }
 
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
@@ -3631,7 +3621,7 @@ SMESH_MeshEditor_i::rotate(TIDSortedElemSet &        theElements,
   ::SMESH_MeshEditor::PGroupIDs groupIds =
       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
 
-  if ( theCopy && !myIsPreviewMode)
+  if ( !myIsPreviewMode)
   {
     if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
     else                 declareMeshModified( /*isReComputeSafe=*/false );
@@ -3892,7 +3882,6 @@ SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
   };
   gp_Trsf aTrsf;
 
-#if OCC_VERSION_LARGE > 0x06070100
   // fight against orthogonalization
   // aTrsf.SetValues( S[0], 0,    0,    thePoint.x * (1-S[0]),
   //                  0,    S[1], 0,    thePoint.y * (1-S[1]),
@@ -3905,13 +3894,6 @@ SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
                 thePoint.z * (1-S[2]));
   M.SetDiagonal( S[0], S[1], S[2] );
 
-#else
-  double tol = std::numeric_limits<double>::max();
-  aTrsf.SetValues( S[0], 0,    0,    thePoint.x * (1-S[0]),
-                   0,    S[1], 0,    thePoint.y * (1-S[1]),
-                   0,    0,    S[2], thePoint.z * (1-S[2]),   tol, tol);
-#endif
-
   TIDSortedElemSet  copyElements;
   TIDSortedElemSet* workElements = &elements;
   if ( myIsPreviewMode )
@@ -3931,7 +3913,7 @@ SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
   ::SMESH_MeshEditor::PGroupIDs groupIds =
       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
 
-  if ( theCopy && !myIsPreviewMode )
+  if ( !myIsPreviewMode )
   {
     if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
     else                 declareMeshModified( /*isReComputeSafe=*/false );
@@ -4008,7 +3990,7 @@ SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
     // and then "GetGroups" using SMESH_Mesh::GetGroups()
 
     TPythonDump pydump; // to prevent dump at mesh creation
-    mesh = makeMesh( theMeshName );
+    mesh   = makeMesh( theMeshName );
     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
 
     if ( mesh_i )
@@ -4158,7 +4140,8 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
 //=======================================================================
 
 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
-                                     const SMESH::ListOfIDSources&     NodesToKeep)
+                                     const SMESH::ListOfIDSources&     NodesToKeep,
+                                     CORBA::Boolean                    AvoidMakingHoles)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
@@ -4202,9 +4185,9 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
     aTPythonDump << aNodeGroup;
   }
 
-  getEditor().MergeNodes( aListOfListOfNodes );
+  getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
 
-  aTPythonDump << "], " << NodesToKeep << ")";
+  aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
 
   declareMeshModified( /*isReComputeSafe=*/false );
 
@@ -4594,6 +4577,151 @@ CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
   return 0;
 }
 
+//=======================================================================
+//function : IsManifold
+//purpose  : Check if a 2D mesh is manifold
+//=======================================================================
+
+CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
+  throw (SALOME::SALOME_Exception)
+{
+  bool isManifold = true;
+
+  SMESH_TRY;
+  SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
+  SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
+                                    foundFreeBordes,
+                                    /*closedOnly=*/true,
+                                    &isManifold );
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  return isManifold;
+}
+
+//=======================================================================
+//function : IsCoherentOrientation2D
+//purpose  : Check if orientation of 2D elements is coherent
+//=======================================================================
+
+CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
+  throw (SALOME::SALOME_Exception)
+{
+  bool isGoodOri = true;
+
+  SMESH_TRY;
+  SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
+  SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
+                                    foundFreeBordes,
+                                    /*closedOnly=*/true,
+                                    /*isManifold=*/0,
+                                    &isGoodOri);
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  return isGoodOri;
+}
+
+//=======================================================================
+//function : FindFreeBorders
+//purpose  : Returns all or only closed FreeBorder's.
+//=======================================================================
+
+SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
+  throw (SALOME::SALOME_Exception)
+{
+  SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
+  SMESH_TRY;
+
+  SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
+  SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
+
+  resBorders->length( foundFreeBordes.size() );
+  for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
+  {
+    const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
+    SMESH::FreeBorder&                    bordOut = resBorders[i];
+    bordOut.nodeIDs.length( bordNodes.size() );
+    for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
+      bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
+  }
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  return resBorders._retn();
+}
+
+//=======================================================================
+//function : FillHole
+//purpose  : Fill with 2D elements a hole defined by a FreeBorder.
+//=======================================================================
+
+void SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole)
+  throw (SALOME::SALOME_Exception)
+{
+  initData();
+
+  if ( theHole.nodeIDs.length() < 4 )
+    THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
+  if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
+    THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
+                                 "First and last nodes must be same", SALOME::BAD_PARAM);
+
+  SMESH_MeshAlgos::TFreeBorder bordNodes;
+  bordNodes.resize( theHole.nodeIDs.length() );
+  for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
+  {
+    bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
+    if ( !bordNodes[ iN ] )
+      THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
+                                   << " does not exist", SALOME::BAD_PARAM);
+  }
+
+  SMESH_TRY;
+
+  MeshEditor_I::TPreviewMesh* previewMesh = 0;
+  SMDS_Mesh* meshDS = getMeshDS();
+  if ( myIsPreviewMode )
+  {
+    // copy faces sharing nodes of theHole
+    TIDSortedElemSet holeFaces;
+    previewMesh = getPreviewMesh( SMDSAbs_Face );
+    for ( size_t i = 0; i < bordNodes.size(); ++i )
+    {
+      SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
+      while ( fIt->more() )
+      {
+        const SMDS_MeshElement* face = fIt->next();
+        if ( holeFaces.insert( face ).second )
+          previewMesh->Copy( face );
+      }
+      bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
+      ASSERT( bordNodes[i] );
+    }
+    meshDS = previewMesh->GetMeshDS();
+  }
+
+  std::vector<const SMDS_MeshElement*> newFaces;
+  SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
+
+  if ( myIsPreviewMode )
+  {
+    previewMesh->Clear();
+    for ( size_t i = 0; i < newFaces.size(); ++i )
+      previewMesh->Copy( newFaces[i] );
+  }
+  else
+  {
+    getEditor().ClearLastCreated();
+    SMESH_SequenceOfElemPtr& aSeq =
+      const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
+    for ( size_t i = 0; i < newFaces.size(); ++i )
+      aSeq.Append( newFaces[i] );
+
+    TPythonDump() << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
+  }
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+}
+
 //=======================================================================
 //function : convError
 //purpose  :
@@ -5116,7 +5244,6 @@ CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
                 << ide << ", " << newIDs << " )";
 
-  MESSAGE("ChangeElementNodes");
   bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
 
   declareMeshModified( /*isReComputeSafe=*/ !res );
@@ -6279,7 +6406,6 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
-  MESSAGE("AffectedElemGroupsInRegion");
   SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
   bool isEdgeGroup = false;
   bool isFaceGroup = false;
@@ -6308,7 +6434,6 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl
   if (aResult)
   {
     int lg = anAffected.size();
-    MESSAGE("lg="<< lg);
     SMESH::long_array_var volumeIds = new SMESH::long_array;
     volumeIds->length(lg);
     SMESH::long_array_var faceIds = new SMESH::long_array;
@@ -6657,7 +6782,7 @@ SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
   else
     pyDump << mesh_var << ", ";
   if ( group_var->_is_nil() )
-    pyDump << "_NoneGroup = "; // assignment to None is forbiden
+    pyDump << "_NoneGroup = "; // assignment to None is forbidden
   else
     pyDump << group_var << " = ";
   pyDump << this << ".MakeBoundaryMesh( "
@@ -6721,7 +6846,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
     else
       groupsOfThisMesh[ nbGroups++ ] = groups[i];
     if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
-      THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
+      THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
   }
   groupsOfThisMesh->length( nbGroups );
   groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
@@ -6815,7 +6940,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
   else
     pyDump << mesh_var << ", ";
   if ( group_var->_is_nil() )
-    pyDump << "_NoneGroup = "; // assignment to None is forbiden
+    pyDump << "_NoneGroup = "; // assignment to None is forbidden
   else
     pyDump << group_var << " = ";
   pyDump << this << ".MakeBoundaryElements( "