X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH_I%2FSMESH_MeshEditor_i.cxx;h=f11615845c1dc4769cec4336ce6b4747885c9f6e;hb=HEAD;hp=d96c5c99e22847b2bf173ea69fe6865630028480;hpb=a11ec0f515b86d30e1617e522a2294d3320cb3c7;p=modules%2Fsmesh.git diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index d96c5c99e..eea74a454 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -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 @@ -102,7 +102,7 @@ namespace MeshEditor_I { //!< 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 @@ -155,8 +155,8 @@ namespace MeshEditor_I { //!< 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() { @@ -279,13 +279,13 @@ namespace MeshEditor_I { SMDS_MeshElement::Filter & filter = *aFilter; if ( aType == SMDSAbs_Node ) - for ( SMESH::smIdType 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 ( SMESH::smIdType i = 0; iFindElement( IDs[i] ); if ( filter( elem )) aMap.insert( aMap.end(), elem ); @@ -789,7 +789,7 @@ SMESH_MeshEditor_i::RemoveElements(const SMESH::smIdType_array & IDsOfElements) list< smIdType > IdList; - for ( SMESH::smIdType i = 0; i < IDsOfElements.length(); i++ ) + for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ ) IdList.push_back( IDsOfElements[i] ); // Update Python script @@ -817,7 +817,7 @@ CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::smIdType_array & IDs initData(); list< smIdType > IdList; - for ( SMESH::smIdType i = 0; i < IDsOfNodes.length(); i++) + for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++) IdList.push_back( IDsOfNodes[i] ); // Update Python script @@ -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 ); +} + //============================================================================= /*! * @@ -1578,7 +1745,7 @@ CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::smIdType_array & IDsOfE SMESH_TRY; initData(); - for ( SMESH::smIdType i = 0; i < IDsOfElements.length(); i++ ) + for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ ) { SMESH::smIdType index = IDsOfElements[i]; const SMDS_MeshElement * elem = getMeshDS()->FindElement(index); @@ -1696,7 +1863,8 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup, 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 ); @@ -1713,6 +1881,64 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup, 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. @@ -2006,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(); @@ -2252,7 +2478,7 @@ SMESH_MeshEditor_i::smooth(const SMESH::smIdType_array & IDsOfElements, arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face); set fixedNodes; - for ( SMESH::smIdType i = 0; i < IDsOfFixedNodes.length(); i++) { + for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) { SMESH::smIdType index = IDsOfFixedNodes[i]; const SMDS_MeshNode * node = aMesh->FindNode(index); if ( node ) @@ -3438,7 +3664,7 @@ SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::smIdType_array& theIDsOfEle << theIDsOfElements << ", " << theVector << " )"; } - return aGroups; + return aGroups ? aGroups : new SMESH::ListOfGroups(); } //======================================================================= @@ -3463,7 +3689,7 @@ SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObjec << theObject << ", " << theVector << " )"; } - return aGroups; + return aGroups ? aGroups : new SMESH::ListOfGroups(); } //======================================================================= @@ -3688,7 +3914,7 @@ SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::smIdType_array& theIDsOfElemen << theAxis << ", " << TVar( theAngle ) << " )"; } - return aGroups; + return aGroups ? aGroups : new SMESH::ListOfGroups(); } //======================================================================= @@ -3715,7 +3941,7 @@ SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject, << theAxis << ", " << TVar( theAngle ) << " )"; } - return aGroups; + return aGroups ? aGroups : new SMESH::ListOfGroups(); } //======================================================================= @@ -4342,7 +4568,7 @@ void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& theGrou if ( elemTypes->length() == 1 && elemTypes[0] == SMESH::NODE ) continue; SMESH::smIdType_array_var elementsId = theElementsToKeep[i]->GetIDs(); - for ( SMESH::smIdType j = 0; j < elementsId->length(); ++j ) + for ( CORBA::ULong j = 0; j < elementsId->length(); ++j ) idsToKeep.Add( elementsId[ j ]); } @@ -4353,7 +4579,7 @@ void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& theGrou const SMESH::long_array& anElemsIDGroup = theGroupsOfElementsID[ i ]; aListOfListOfElementsID.push_back( list< smIdType >() ); list< smIdType >& aListOfElemsID = aListOfListOfElementsID.back(); - for ( SMESH::smIdType j = 0; j < anElemsIDGroup.length(); j++ ) + for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) { SMESH::smIdType id = anElemsIDGroup[ j ]; if ( idsToKeep.Contains( id )) aListOfElemsID.push_front( id ); @@ -4430,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 )); @@ -7081,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 @@ -7092,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) @@ -7129,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 ); } @@ -7156,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; @@ -7168,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 ) @@ -7185,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); } } } @@ -7197,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(); @@ -7212,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();