Salome HOME
Merge branch 'OCCT780'
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
index 323a6603adf24d1994d9f0635c9964bc8c757539..eea74a45445027150db035bc5a46929aeaf6b6ac 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -834,7 +834,7 @@ CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::smIdType_array & IDs
 
 //=============================================================================
 /*!
- *
+ * Remove orphan nodes
  */
 //=============================================================================
 
@@ -865,6 +865,58 @@ SMESH::smIdType SMESH_MeshEditor_i::RemoveOrphanNodes()
   return 0;
 }
 
+//=============================================================================
+/*!
+ * Remove a node and fill a hole appeared by changing surrounding faces
+ */
+//=============================================================================
+
+void SMESH_MeshEditor_i::RemoveNodeWithReconnection( SMESH::smIdType nodeID )
+{
+  SMESH_TRY;
+  initData();
+
+  const SMDS_MeshNode * node = getMeshDS()->FindNode( nodeID );
+  if ( ! node )
+    THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID ") << nodeID,
+                                  SALOME::BAD_PARAM);
+  if ( node->NbInverseElements( SMDSAbs_Volume ) > 0 )
+    THROW_SALOME_CORBA_EXCEPTION( "RemoveNodeWithReconnection() applies to 2D mesh only",
+                                  SALOME::BAD_PARAM);
+
+  if ( myIsPreviewMode ) // make preview data
+  {
+    // in a preview mesh, make edges linked to a node
+    TPreviewMesh& tmpMesh = *getPreviewMesh( SMDSAbs_Edge );
+    TIDSortedElemSet linkedNodes;
+    ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
+    SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy( node );
+    for ( const SMDS_MeshElement* n : linkedNodes )
+    {
+      SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( n ));
+      tmpMesh.GetMeshDS()->AddEdge( nodeCpy1, nodeCpy2 );
+    }
+    // copy surrounding faces
+    for ( SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator( SMDSAbs_Face ); fIt->more(); )
+      tmpMesh.Copy ( fIt->next() );
+    
+    // remove copied node
+    if ( nodeCpy1 )
+      getEditor().RemoveNodeWithReconnection( nodeCpy1 );
+  }
+  else
+  {
+    getEditor().RemoveNodeWithReconnection( node );
+
+    // Update Python script
+    TPythonDump() << this << ".RemoveNodeWithReconnection( " << nodeID << " )";
+
+    declareMeshModified( /*isReComputeSafe=*/ true );
+  }
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+}
+
 //=============================================================================
 /*!
  * Add a new node.
@@ -1567,6 +1619,121 @@ CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(SMESH::smIdType NodeID1,
   return 0;
 }
 
+//=============================================================================
+/*!
+ * \brief Split a diagonal of a quadrangle formed by two adjacent triangles
+ *        so that four new triangles appear in place of the two triangles
+ */
+//=============================================================================
+
+void SMESH_MeshEditor_i::AddNodeOnSegment(SMESH::smIdType nodeID1,
+                                          SMESH::smIdType nodeID2,
+                                          CORBA::Double   position)
+{
+  SMESH_TRY;
+  initData();
+
+  const SMDS_MeshNode * n1 = getMeshDS()->FindNode( nodeID1 );
+  const SMDS_MeshNode * n2 = getMeshDS()->FindNode( nodeID2 );
+  if ( !n1 )
+    THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << nodeID1,
+                                  SALOME::BAD_PARAM);
+  if ( !n2 )
+    THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << nodeID2,
+                                  SALOME::BAD_PARAM);
+
+  if ( myIsPreviewMode ) // make preview data
+  {
+    TPreviewMesh* tmpMesh = getPreviewMesh();
+    TIDSortedElemSet elemSet, avoidSet;
+    TopoDS_Shape shape;
+    while ( const SMDS_MeshElement* face = SMESH_MeshAlgos::FindFaceInSet( n1, n2,
+                                                                           elemSet, avoidSet ))
+    {
+      if ( avoidSet.empty() )
+      {
+        shape = getMeshDS()->IndexToShape( face->GetShapeID() );
+        if ( !shape.IsNull() )
+        {
+          tmpMesh->ShapeToMesh( TopoDS_Shape() );
+          tmpMesh->ShapeToMesh( shape );
+        }
+      }
+      SMDS_MeshElement* faceCopy = tmpMesh->Copy ( face );
+      avoidSet.insert( face );
+
+      if ( !shape.IsNull() )
+        tmpMesh->GetMeshDS()->SetMeshElementOnShape( faceCopy, shape );
+    }
+    n1 = tmpMesh->GetMeshDS()->FindNode( nodeID1 );
+    n2 = tmpMesh->GetMeshDS()->FindNode( nodeID2 );
+
+    if ( !shape.IsNull() )
+    {
+      tmpMesh->GetMeshDS()->SetMeshElementOnShape( n1, shape );
+      tmpMesh->GetMeshDS()->SetMeshElementOnShape( n2, shape );
+    }
+  }
+
+  getEditor().SplitEdge( n1, n2, position );
+
+  if ( !myIsPreviewMode )
+  {
+    // Update Python script
+    TPythonDump() << this << ".AddNodeOnSegment( "
+                  << nodeID1 << ", " << nodeID2 << ", " << position << " )";
+
+    declareMeshModified( /*isReComputeSafe=*/true );
+  }
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+}
+
+//=============================================================================
+/*!
+ * \brief Split a face into triangles by adding a new node onto the face
+ *        and connecting the new node with face nodes
+ */
+//=============================================================================
+
+void  SMESH_MeshEditor_i::AddNodeOnFace(SMESH::smIdType theFaceID,
+                                        CORBA::Double   theX,
+                                        CORBA::Double   theY,
+                                        CORBA::Double   theZ)
+{
+  SMESH_TRY;
+  initData();
+
+  const SMDS_MeshElement * face = getMeshDS()->FindElement( theFaceID );
+  if ( !face )
+    THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid face ID: ") << theFaceID,
+                                  SALOME::BAD_PARAM);
+  if ( face->GetType() != SMDSAbs_Face )
+    THROW_SALOME_CORBA_EXCEPTION( "The element is not a face ", SALOME::BAD_PARAM );
+
+  if ( myIsPreviewMode ) // make preview data
+  {
+    TPreviewMesh* tmpMesh = getPreviewMesh();
+    face = tmpMesh->Copy ( face );
+  }
+
+  getEditor().SplitFace( face, theX, theY, theZ );
+
+  if ( !myIsPreviewMode )
+  {
+    // Update Python script
+    TPythonDump() << this << ".AddNodeOnFace( "
+                  << theFaceID << ", "
+                  << theX << ", "
+                  << theY << ", "
+                  << theZ << " )";
+
+    declareMeshModified( /*isReComputeSafe=*/true );
+  }
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+}
+
 //=============================================================================
 /*!
  *
@@ -2065,8 +2232,8 @@ CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr th
  */
 //=============================================================================
 
-CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
-                                           SMESH::NumericalFunctor_ptr Criterion)
+CORBA::Short SMESH_MeshEditor_i::BestSplit (SMESH::smIdType             IDOfQuad,
+                                            SMESH::NumericalFunctor_ptr Criterion)
 {
   SMESH_TRY;
   initData();
@@ -3497,7 +3664,7 @@ SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::smIdType_array& theIDsOfEle
                 << theIDsOfElements << ", "
                 << theVector        << " )";
   }
-  return aGroups;
+  return aGroups ? aGroups : new SMESH::ListOfGroups();
 }
 
 //=======================================================================
@@ -3522,7 +3689,7 @@ SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObjec
                 << theObject << ", "
                 << theVector << " )";
   }
-  return aGroups;
+  return aGroups ? aGroups : new SMESH::ListOfGroups();
 }
 
 //=======================================================================
@@ -3747,7 +3914,7 @@ SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::smIdType_array& theIDsOfElemen
                 << theAxis          << ", "
                 << TVar( theAngle ) << " )";
   }
-  return aGroups;
+  return aGroups ? aGroups : new SMESH::ListOfGroups();
 }
 
 //=======================================================================
@@ -3774,7 +3941,7 @@ SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
                 << theAxis          << ", "
                 << TVar( theAngle ) << " )";
   }
-  return aGroups;
+  return aGroups ? aGroups : new SMESH::ListOfGroups();
 }
 
 //=======================================================================
@@ -4489,7 +4656,6 @@ CORBA::Boolean SMESH_MeshEditor_i::MoveNode(SMESH::smIdType NodeID,
     // move copied node
     if ( nodeCpy1 )
       tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
-    // fill preview data
   }
   else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
     theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
@@ -7140,6 +7306,7 @@ SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
  *    mesh + created boundary elements; "" means not to create the new mesh
  *  \param toCopyAll - if true, the whole initial mesh will be copied into
  *    the new mesh else only boundary elements will be copied into the new mesh
+ *  \param toCreateAllElements - if true all the dim element are created from the mesh
  *  \param groups - optional groups of elements to make boundary around
  *  \param mesh - returns the mesh where elements were added to
  *  \param group - returns the created group, if any
@@ -7151,6 +7318,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
                                                      const char* groupName,
                                                      const char* meshName,
                                                      CORBA::Boolean toCopyAll,
+                                                     CORBA::Boolean toCreateAllElements,
                                                      const SMESH::ListOfIDSources& groups,
                                                      SMESH::SMESH_Mesh_out mesh,
                                                      SMESH::SMESH_Group_out group)
@@ -7188,7 +7356,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
     // process groups belonging to another mesh
     SMESH::SMESH_Mesh_var    otherMesh = groupsOfOtherMesh[0]->GetMesh();
     SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
-    nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
+    nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll, toCreateAllElements,
                                              groupsOfOtherMesh, mesh, group );
   }
 
@@ -7215,6 +7383,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
   SMESH_Mesh*     srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
   SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
 
+
   // group of boundary elements
   SMESH_Group* smesh_group = 0;
   SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
@@ -7227,7 +7396,6 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
   }
 
   TIDSortedElemSet elements;
-
   if ( groups.length() > 0 )
   {
     for ( int i = 0; i < nbGroups; ++i )
@@ -7244,7 +7412,8 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
                                                  /*toCopyElements=*/false,
                                                  /*toCopyExistingBondary=*/srcMesh != tgtMesh,
                                                  /*toAddExistingBondary=*/true,
-                                                 /*aroundElements=*/true);
+                                                 /*aroundElements=*/true,
+                                                 /*toCreateAllElements=*/toCreateAllElements);
       }
     }
   }
@@ -7256,7 +7425,8 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
                                              tgtMesh,
                                              /*toCopyElements=*/false,
                                              /*toCopyExistingBondary=*/srcMesh != tgtMesh,
-                                             /*toAddExistingBondary=*/true);
+                                             /*toAddExistingBondary=*/true,
+                                             /*aroundElements=*/toCreateAllElements);
   }
   tgtMesh->GetMeshDS()->Modified();
 
@@ -7271,13 +7441,21 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
   if ( group_var->_is_nil() )
     pyDump << "_NoneGroup = "; // assignment to None is forbidden
   else
+
     pyDump << group_var << " = ";
-  pyDump << this << ".MakeBoundaryElements( "
-         << "SMESH." << dimName[int(dim)] << ", "
-         << "'" << groupName << "', "
-         << "'" << meshName<< "', "
-         << toCopyAll << ", "
-         << groups << ")";
+  
+  if ( toCreateAllElements )
+    pyDump << this << ".MakeBoundaryOfEachElement( ";
+  else
+  {
+    pyDump << this << ".MakeBoundaryElements( "
+           << "SMESH." << dimName[int(dim)] << ", ";
+  }
+
+  pyDump<< "'" << groupName << "', "
+        << "'" << meshName<< "', "
+        << toCopyAll << ", "
+        << groups << ")";
 
   mesh  = mesh_var._retn();
   group = group_var._retn();