-// 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
//!< Constructor
TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
_isShapeToMesh = (_id = 0);
- _myMeshDS = new SMESHDS_Mesh( _id, true );
+ _meshDS = new SMESHDS_Mesh( _id, true );
myPreviewType = previewElements;
}
//!< Copy a set of elements
//!< Copy a node
SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
{
- return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
- anElemNode->GetID());
+ return _meshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
+ anElemNode->GetID());
}
void RemoveAll()
{
//=============================================================================
/*!
- *
+ * Remove orphan nodes
*/
//=============================================================================
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.
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 );
+}
+
//=============================================================================
/*!
*
if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
- int nbReori = getEditor().Reorient2D( elements, dirVec, face );
+ TIDSortedElemSet refFaces = { face };
+ int nbReori = getEditor().Reorient2D( elements, dirVec, refFaces, /*allowNonManifold=*/true );
if ( nbReori ) {
declareMeshModified( /*isReComputeSafe=*/false );
return 0;
}
+//=======================================================================
+//function : Reorient2DByNeighbours
+//purpose : Reorient faces contained in a list of objectFaces
+// equally to faces contained in a list of referenceFaces.
+//=======================================================================
+
+CORBA::Long
+SMESH_MeshEditor_i::Reorient2DByNeighbours(const SMESH::ListOfIDSources& theObjectFaces,
+ const SMESH::ListOfIDSources& theReferenceFaces)
+{
+ SMESH_TRY;
+ initData(/*deleteSearchers=*/false);
+
+ if ( theObjectFaces.length() == 0 )
+ return 0;
+
+ // get object faces
+ TIDSortedElemSet objFaces;
+ bool invalidObjFaces = false;
+ for ( CORBA::ULong i = 0; i < theObjectFaces.length(); ++i )
+ {
+ IDSource_Error err;
+ if ( !idSourceToSet( theObjectFaces[i], getMeshDS(), objFaces, SMDSAbs_Face,
+ /*emptyIfIsMesh=*/1, &err ) &&
+ err == IDSource_INVALID )
+ invalidObjFaces = true;
+ }
+ if ( objFaces.empty() && invalidObjFaces )
+ THROW_SALOME_CORBA_EXCEPTION("No valid faces in given groups", SALOME::BAD_PARAM);
+
+ // get reference faces
+ TIDSortedElemSet refFaces;
+ for ( CORBA::ULong i = 0; i < theReferenceFaces.length(); ++i )
+ {
+ idSourceToSet( theReferenceFaces[i], getMeshDS(), refFaces, SMDSAbs_Face, /*emptyIfIsMesh=*/1 );
+ }
+ if ( refFaces.empty() && theReferenceFaces.length() > 0 )
+ THROW_SALOME_CORBA_EXCEPTION("Reference faces are invalid", SALOME::BAD_PARAM);
+
+
+ gp_Vec zeroVec( 0,0,0 );
+
+ // reorient
+ int nbReori = getEditor().Reorient2D( objFaces, zeroVec, refFaces, /*allowNonManifold=*/false );
+
+ if ( nbReori )
+ declareMeshModified( /*isReComputeSafe=*/false );
+
+ TPythonDump() << this << ".Reorient2DByNeighbours("
+ << theObjectFaces << ", "
+ << theReferenceFaces << ")";
+
+ return nbReori;
+
+ SMESH_CATCH( SMESH::throwCorbaException );
+ return 0;
+}
+
//=======================================================================
//function : Reorient2DBy3D
//purpose : Reorient faces basing on orientation of adjacent volumes.
*/
//=============================================================================
-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();
<< theIDsOfElements << ", "
<< theVector << " )";
}
- return aGroups;
+ return aGroups ? aGroups : new SMESH::ListOfGroups();
}
//=======================================================================
<< theObject << ", "
<< theVector << " )";
}
- return aGroups;
+ return aGroups ? aGroups : new SMESH::ListOfGroups();
}
//=======================================================================
<< theAxis << ", "
<< TVar( theAngle ) << " )";
}
- return aGroups;
+ return aGroups ? aGroups : new SMESH::ListOfGroups();
}
//=======================================================================
<< theAxis << ", "
<< TVar( theAngle ) << " )";
}
- return aGroups;
+ return aGroups ? aGroups : new SMESH::ListOfGroups();
}
//=======================================================================
// 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 ));
* 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
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)
// 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 );
}
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;
}
TIDSortedElemSet elements;
-
if ( groups.length() > 0 )
{
for ( int i = 0; i < nbGroups; ++i )
/*toCopyElements=*/false,
/*toCopyExistingBondary=*/srcMesh != tgtMesh,
/*toAddExistingBondary=*/true,
- /*aroundElements=*/true);
+ /*aroundElements=*/true,
+ /*toCreateAllElements=*/toCreateAllElements);
}
}
}
tgtMesh,
/*toCopyElements=*/false,
/*toCopyExistingBondary=*/srcMesh != tgtMesh,
- /*toAddExistingBondary=*/true);
+ /*toAddExistingBondary=*/true,
+ /*aroundElements=*/toCreateAllElements);
}
tgtMesh->GetMeshDS()->Modified();
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();