X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH_I%2FSMESH_MeshEditor_i.cxx;h=b813fc37b4bd10dce08a26bf9db49edab06af1f1;hp=6dfd0d61efad2b128085bfbe0c14785ef70580a1;hb=7cda93af4017eadf99cf109fc3cce1208c969b26;hpb=dbd1374aa8aeac32c368b8f6add841e0bd90f807 diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index 6dfd0d61e..b813fc37b 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2019 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 @@ -42,7 +42,6 @@ #include "SMDS_Mesh0DElement.hxx" #include "SMDS_MeshFace.hxx" #include "SMDS_MeshVolume.hxx" -#include "SMDS_PolyhedralVolumeOfNodes.hxx" #include "SMDS_SetIterator.hxx" #include "SMDS_VolumeTool.hxx" #include "SMESHDS_Group.hxx" @@ -64,7 +63,6 @@ #include #include #include -#include #include #include @@ -76,15 +74,8 @@ #include #include -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 -#define NO_CAS_CATCH -#endif - #include - -#ifdef NO_CAS_CATCH #include -#endif #include #include @@ -110,7 +101,7 @@ namespace MeshEditor_I { SMDSAbs_ElementType myPreviewType; // type to show //!< Constructor TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) { - _isShapeToMesh = (_id =_studyId = 0); + _isShapeToMesh = (_id = 0); _myMeshDS = new SMESHDS_Mesh( _id, true ); myPreviewType = previewElements; } @@ -173,7 +164,10 @@ namespace MeshEditor_I { } void Remove( SMDSAbs_ElementType type ) { - SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator( type ); + Remove( GetMeshDS()->elementsIterator( type )); + } + void Remove( SMDS_ElemIteratorPtr eIt ) + { while ( eIt->more() ) GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false ); } @@ -184,7 +178,7 @@ namespace MeshEditor_I { //============================================================================= /*! - * \brief Deleter of theNodeSearcher at any compute event occurred + * \brief Deleter of theNodeSearcher and theElementSearcher at any compute event occurred */ //============================================================================= @@ -304,33 +298,35 @@ namespace MeshEditor_I { */ //================================================================================ - void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject, - const SMESHDS_Mesh* theMeshDS, - TIDSortedNodeSet& theNodeSet) + void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject, + const SMESHDS_Mesh* theMeshDS, + TIDSortedNodeSet& theNodeSet) { if ( CORBA::is_nil( theObject ) ) return; - SMESH::array_of_ElementType_var types = theObject->GetTypes(); - SMESH::long_array_var aElementsId = theObject->GetIDs(); - if ( types->length() == 1 && types[0] == SMESH::NODE) + if ( SMESH::DownCast( theObject )) { - for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ ) - if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] )) - theNodeSet.insert( theNodeSet.end(), n); - } - else if ( SMESH::DownCast( theObject )) - { - SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator(); - while ( nIt->more( )) + for ( SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator(); nIt->more(); ) if ( const SMDS_MeshElement * elem = nIt->next() ) theNodeSet.insert( elem->begin_nodes(), elem->end_nodes()); } else { - 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()); + SMESH::array_of_ElementType_var types = theObject->GetTypes(); + SMESH::long_array_var aElementsId = theObject->GetIDs(); + if ( types->length() == 1 && types[0] == SMESH::NODE) + { + for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ ) + if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] )) + theNodeSet.insert( theNodeSet.end(), n); + } + else + { + 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()); + } } } @@ -387,8 +383,10 @@ namespace MeshEditor_I { */ //================================================================================ - string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type) + string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type = SMESH::ALL ) { + if ( SMESH::DownCast( theMeshPart )) + return ""; string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart ); if ( SMESH_Group_i* group_i = SMESH::DownCast( theMeshPart )) // take into account passible group modification @@ -530,16 +528,18 @@ SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData() SMESH_TRY; const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() ); - if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling --- - + if ( myIsPreviewMode || hasBadElems ) + { list aNodesConnectivity; typedef map TNodesMap; TNodesMap nodesMap; SMESHDS_Mesh* aMeshDS; - std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS; + std::unique_ptr< SMESH_MeshPartDS > aMeshPartDS; if ( hasBadElems ) { - aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements )); + const list& badElems = + static_cast( getEditor().GetError().get() )->myBadElements; + aMeshPartDS.reset( new SMESH_MeshPartDS( badElems )); aMeshDS = aMeshPartDS.get(); } else { @@ -623,9 +623,9 @@ SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes() SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array(); const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes(); - myLastCreatedNodes->length( aSeq.Length() ); - for (int i = 1; i <= aSeq.Length(); i++) - myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID(); + myLastCreatedNodes->length( aSeq.size() ); + for ( size_t i = 0; i < aSeq.size(); i++) + myLastCreatedNodes[i] = aSeq[i]->GetID(); return myLastCreatedNodes._retn(); SMESH_CATCH( SMESH::throwCorbaException ); @@ -646,9 +646,9 @@ SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems() SMESH::long_array_var myLastCreatedElems = new SMESH::long_array(); const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems(); - myLastCreatedElems->length( aSeq.Length() ); - for ( int i = 1; i <= aSeq.Length(); i++ ) - myLastCreatedElems[i-1] = aSeq.Value(i)->GetID(); + myLastCreatedElems->length( aSeq.size() ); + for ( size_t i = 0; i < aSeq.size(); i++ ) + myLastCreatedElems[i] = aSeq[i]->GetID(); return myLastCreatedElems._retn(); SMESH_CATCH( SMESH::throwCorbaException ); @@ -685,7 +685,7 @@ SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError() errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0 errOut->comment = errIn->myComment.c_str(); errOut->subShapeID = -1; - errOut->hasBadMesh = !errIn->myBadElements.empty(); + errOut->hasBadMesh = errIn->HasBadElems(); } else { @@ -1390,8 +1390,11 @@ void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID, Standard_Real f,l; BRep_Tool::Range( TopoDS::Edge( shape ), f,l); if ( paramOnEdge < f || paramOnEdge > l ) - THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM); - + { + SMESH_Comment txt("Invalid paramOnEdge. It must vary in range [ "); + txt << f << ", " << l << " ]"; + THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM); + } mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge ); myMesh->SetIsModified( true ); @@ -1434,14 +1437,11 @@ void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID, v > surf.LastVParameter() ); if ( isOut ) { -#ifdef _DEBUG_ - MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of " - << " u( " << surf.FirstUParameter() - << "," << surf.LastUParameter() - << ") v( " << surf.FirstVParameter() - << "," << surf.LastVParameter() << ")" ); -#endif - THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM); + SMESH_Comment txt("Invalid UV. U must vary in range [ "); + txt << surf.FirstUParameter() << ", " << surf.LastUParameter() << " ], "; + txt << "V must vary in range [ "; + txt << surf.FirstVParameter() << ", " << surf.LastVParameter() << " ]"; + THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM); } mesh->SetNodeOnFace( node, FaceID, u, v ); @@ -2021,7 +2021,7 @@ CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr th //============================================================================= /*! * Find better splitting of the given quadrangle. - * \param IDOfQuad ID of the quadrangle to be splitted. + * \param IDOfQuad ID of the quadrangle to be split. * \param Criterion A criterion to choose a diagonal for splitting. * \return 1 if 1-3 diagonal is better, 2 if 2-4 * diagonal is better, 0 if error occurs. @@ -2070,9 +2070,10 @@ void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems, ::SMESH_MeshEditor::TFacetOfElem elemSet; const int noneFacet = -1; - SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME ); - while( volIt->more() ) - elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet )); + prepareIdSource( elems ); + if ( SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME )) + while ( volIt->more() ) + elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet )); getEditor().SplitVolumes( elemSet, int( methodFlags )); declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute() @@ -2113,6 +2114,7 @@ void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr el facetToSplitNormal.PS.y, facetToSplitNormal.PS.z )); TIDSortedElemSet elemSet; + prepareIdSource( elems ); SMESH::long_array_var anElementsId = elems->GetIDs(); SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA ); arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter ); @@ -2427,8 +2429,8 @@ SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes TIDSortedElemSet elemsNodes[2]; for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) { - SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ); - while ( nIt->more() ) elemsNodes[1].insert( nIt->next() ); + if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE )) + while ( nIt->more() ) elemsNodes[1].insert( nIt->next() ); } for ( int i = 0, nb = theEdges.length(); i < nb; ++i ) idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge ); @@ -2494,7 +2496,8 @@ namespace MeshEditor_I bool myIsExtrusionByNormal; static int makeFlags( CORBA::Boolean MakeGroups, - CORBA::Boolean LinearVariation = false, + CORBA::Boolean ScaleVariation = false, + CORBA::Boolean AngleVariation = false, CORBA::Boolean ByAverageNormal = false, CORBA::Boolean UseInputElemsOnly = false, CORBA::Long Flags = 0, @@ -2503,7 +2506,8 @@ 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 ( ScaleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION; + if ( AngleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION; if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY; return Flags; } @@ -2511,7 +2515,9 @@ namespace MeshEditor_I ExtrusionParams(const SMESH::DirStruct & theDir, CORBA::Long theNbOfSteps, const SMESH::double_array & theScaleFactors, - CORBA::Boolean theLinearVariation, + CORBA::Boolean theScaleVariation, + const SMESH::double_array & theAngles, + CORBA::Boolean theAngleVariation, const SMESH::double_array & theBasePoint, CORBA::Boolean theMakeGroups): ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x, @@ -2519,8 +2525,9 @@ namespace MeshEditor_I theDir.PS.z ), theNbOfSteps, toList( theScaleFactors ), + toList( theAngles ), TBasePoint( theBasePoint ), - makeFlags( theMakeGroups, theLinearVariation )), + makeFlags( theMakeGroups, theScaleVariation, theAngleVariation )), myIsExtrusionByNormal( false ) { } @@ -2535,8 +2542,9 @@ namespace MeshEditor_I theDir.PS.z ), theNbOfSteps, std::list(), + std::list(), 0, - makeFlags( theMakeGroups, false, false, false, + makeFlags( theMakeGroups, false, false, false, false, theExtrFlags, false ), theSewTolerance ), myIsExtrusionByNormal( false ) @@ -2551,7 +2559,7 @@ namespace MeshEditor_I CORBA::Boolean theMakeGroups ): ::SMESH_MeshEditor::ExtrusParam ( theStepSize, theNbOfSteps, - makeFlags( theMakeGroups, false, + makeFlags( theMakeGroups, false, false, theByAverageNormal, theUseInputElemsOnly ), theDim), myIsExtrusionByNormal( true ) @@ -2563,8 +2571,6 @@ namespace MeshEditor_I Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS); } - private: - static std::list toList( const SMESH::double_array & theScaleFactors ) { std::list scales; @@ -2573,6 +2579,8 @@ namespace MeshEditor_I return scales; } + private: + // structure used to convert SMESH::double_array to gp_XYZ* struct TBasePoint { @@ -2601,7 +2609,7 @@ namespace MeshEditor_I * \param [in] nbOfSteps - number of elements to generate from one element * \param [in] toMakeGroups - if true, new elements will be included into new groups * corresponding to groups the input elements included in. - * \return ListOfGroups - new groups craeted if \a toMakeGroups is true + * \return ListOfGroups - new groups created if \a toMakeGroups is true */ //======================================================================= @@ -2611,22 +2619,24 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode const SMESH::ListOfIDSources & theFaces, const SMESH::DirStruct & theStepVector, CORBA::Long theNbOfSteps, + CORBA::Boolean theToMakeGroups, const SMESH::double_array & theScaleFactors, - CORBA::Boolean theLinearVariation, + CORBA::Boolean theScalesVariation, const SMESH::double_array & theBasePoint, - CORBA::Boolean theToMakeGroups) + const SMESH::double_array & theAngles, + CORBA::Boolean theAnglesVariation) throw (SALOME::SALOME_Exception) { SMESH_TRY; initData(); - ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, - theLinearVariation, theBasePoint, theToMakeGroups ); + ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, theScalesVariation, + theAngles, theAnglesVariation, theBasePoint, theToMakeGroups ); TIDSortedElemSet elemsNodes[2]; for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) { - SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ); - while ( nIt->more() ) elemsNodes[1].insert( nIt->next() ); + if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE )) + while ( nIt->more() ) elemsNodes[1].insert( nIt->next() ); } for ( int i = 0, nb = theEdges.length(); i < nb; ++i ) idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge ); @@ -2662,12 +2672,17 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode { dumpGroupsList( aPythonDump, aGroups ); aPythonDump << this<< ".ExtrusionSweepObjects( " - << theNodes << ", " - << theEdges << ", " - << theFaces << ", " - << theStepVector << ", " - << TVar( theNbOfSteps ) << ", " - << theToMakeGroups << " )"; + << theNodes << ", " + << theEdges << ", " + << theFaces << ", " + << theStepVector << ", " + << TVar( theNbOfSteps ) << ", " + << theToMakeGroups << ", " + << TVar( theScaleFactors ) << ", " + << theScalesVariation << ", " + << TVar( theBasePoint ) << ", " + << TVar( theAngles ) << ", " + << theAnglesVariation << " )"; } else { @@ -2845,15 +2860,17 @@ SMESH::ListOfGroups* SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes, const SMESH::ListOfIDSources & theEdges, const SMESH::ListOfIDSources & theFaces, - SMESH::SMESH_IDSource_ptr thePathMesh, + SMESH::SMESH_IDSource_ptr thePathObject, GEOM::GEOM_Object_ptr thePathShape, CORBA::Long theNodeStart, CORBA::Boolean theHasAngles, const SMESH::double_array & theAngles, - CORBA::Boolean theLinearVariation, + CORBA::Boolean theAnglesVariation, CORBA::Boolean theHasRefPoint, const SMESH::PointStruct & theRefPoint, bool theMakeGroups, + const SMESH::double_array & theScaleFactors, + CORBA::Boolean theScalesVariation, SMESH::SMESH_MeshEditor::Extrusion_Error& theError) throw (SALOME::SALOME_Exception) { @@ -2863,61 +2880,73 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups; theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE; - if ( thePathMesh->_is_nil() ) + if ( thePathObject->_is_nil() ) return aGroups._retn(); - // get a sub-mesh - SMESH_subMesh* aSubMesh = 0; - SMESH_Mesh_i* aMeshImp = SMESH::DownCast( thePathMesh ); - if ( thePathShape->_is_nil() ) + + SMDS_ElemIteratorPtr pathEdgesIterator; + + SMESH_Mesh_i* aMeshImp = SMESH::DownCast( thePathObject ); + if ( !CORBA::is_nil( thePathShape ) && aMeshImp ) { - // thePathMesh should be either a sub-mesh or a mesh with 1D elements only - if ( SMESH_subMesh_i* sm = SMESH::DownCast( thePathMesh )) + // get a sub-mesh of thePathShape + TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape ); + SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape ); + if ( !aSubMesh ) + return aGroups._retn(); + + if ( !aSubMesh->GetSubMeshDS() ) { - SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh(); - aMeshImp = SMESH::DownCast( mesh ); - if ( !aMeshImp ) return aGroups._retn(); - aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() ); - if ( !aSubMesh ) return aGroups._retn(); + SMESHDS_Mesh * meshDS = aMeshImp->GetImpl().GetMeshDS(); + meshDS->AddCompoundSubmesh( aShape, TopAbs_EDGE ); + if ( !aSubMesh->GetSubMeshDS() ) + return aGroups._retn(); } - else if ( !aMeshImp || - aMeshImp->NbEdges() != aMeshImp->NbElements() ) - { + theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE; + pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements(); + if ( !pathEdgesIterator->more() || + pathEdgesIterator->next()->GetType() != SMDSAbs_Edge ) return aGroups._retn(); - } + + pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements(); } else { - if ( !aMeshImp ) return aGroups._retn(); - TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape ); - aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape ); - if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ ) + theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE; + prepareIdSource( thePathObject ); + pathEdgesIterator = SMESH_Mesh_i::GetElements( thePathObject, SMESH::EDGE ); + if ( !pathEdgesIterator || !pathEdgesIterator->more() ) return aGroups._retn(); } - SMDS_MeshNode* nodeStart = - (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart); - if ( !nodeStart ) { - theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE; - return aGroups._retn(); + if ( !aMeshImp ) + { + SMESH::SMESH_Mesh_var pathMesh = thePathObject->GetMesh(); + aMeshImp = SMESH::DownCast( pathMesh ); } + + theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE; + const SMDS_MeshNode* nodeStart = aMeshImp->GetImpl().GetMeshDS()->FindNode( theNodeStart ); + if ( !nodeStart ) + return aGroups._retn(); + + TIDSortedElemSet elemsNodes[2]; for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) { - SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ); - while ( nIt->more() ) elemsNodes[1].insert( nIt->next() ); + if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE )) + while ( nIt->more() ) elemsNodes[1].insert( nIt->next() ); } for ( int i = 0, nb = theEdges.length(); i < nb; ++i ) idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge ); for ( int i = 0, nb = theFaces.length(); i < nb; ++i ) idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face ); - list angles; - for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) { - angles.push_back( theAngles[i] ); - } + list angles = ExtrusionParams::toList( theAngles ); + list scales = ExtrusionParams::toList( theScaleFactors ); gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z ); + const gp_Pnt *refPntPtr = theHasRefPoint ? &refPnt : 0; int nbOldGroups = myMesh->NbGroup(); @@ -2932,15 +2961,12 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the theMakeGroups = false; } - ::SMESH_MeshEditor::Extrusion_Error error; - if ( !aSubMesh ) - error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart, - theHasAngles, angles, theLinearVariation, - theHasRefPoint, refPnt, theMakeGroups ); - else - error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart, - theHasAngles, angles, theLinearVariation, - theHasRefPoint, refPnt, theMakeGroups ); + ::SMESH_MeshEditor::Extrusion_Error error = + getEditor().ExtrusionAlongTrack( workElements, + &(aMeshImp->GetImpl()), pathEdgesIterator, nodeStart, + angles, theAnglesVariation, + scales, theScalesVariation, + refPntPtr, theMakeGroups ); declareMeshModified( /*isReComputeSafe=*/true ); theError = convExtrError( error ); @@ -2962,18 +2988,20 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the << theNodes << ", " << theEdges << ", " << theFaces << ", " - << thePathMesh << ", " + << thePathObject << ", " << thePathShape << ", " << theNodeStart << ", " << theHasAngles << ", " << TVar( theAngles ) << ", " - << theLinearVariation << ", " + << theAnglesVariation << ", " << theHasRefPoint << ", " << "SMESH.PointStruct( " << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", " << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", " << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), " - << theMakeGroups << " )"; + << theMakeGroups << ", " + << TVar( theScaleFactors ) << ", " + << theScalesVariation << " )"; } else { @@ -3890,7 +3918,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]), @@ -3903,13 +3930,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::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 ) @@ -4006,7 +4026,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( mesh ); if ( mesh_i ) @@ -4030,6 +4050,101 @@ SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject, return mesh._retn(); } +//================================================================================ +/*! + * \brief Make an offset mesh from a source 2D mesh + * \param [inout] theObject - source mesh. New elements are added to this mesh + * if \a theMeshName is empty. + * \param [in] theValue - offset value + * \param [in] theCopyGroups - to generate groups + * \param [in] theMeshName - optional name of a new mesh + * \param [out] theGroups - new groups + * \return SMESH::SMESH_Mesh_ptr - the modified mesh + */ +//================================================================================ + +SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject, + CORBA::Double theValue, + CORBA::Boolean theCopyGroups, + CORBA::Boolean theCopyElements, + const char* theMeshName, + SMESH::ListOfGroups_out theGroups) + throw (SALOME::SALOME_Exception) +{ + SMESH_TRY; + initData(); + + SMESHDS_Mesh* aMeshDS = getMeshDS(); + + SMESH::SMESH_Mesh_var mesh_var; + ::SMESH_MeshEditor::PGroupIDs groupIds; + + TPythonDump pyDump; + + TIDSortedElemSet elements, copyElements; + if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face, + /*emptyIfIsMesh=*/ !myIsPreviewMode )) + { + // mesh to modify + SMESH_Mesh* tgtMesh = 0; + if ( myIsPreviewMode ) + { + TPreviewMesh * tmpMesh = getPreviewMesh(); + tgtMesh = tmpMesh; + tmpMesh->Copy( elements, copyElements ); + elements.swap( copyElements ); + theCopyGroups = false; + theCopyElements = false; + } + else + { + mesh_var = + *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() ); + SMESH_Mesh_i* mesh_i = SMESH::DownCast( mesh_var ); + tgtMesh = & mesh_i->GetImpl(); + } + groupIds = getEditor().Offset( elements, theValue, tgtMesh, + theCopyGroups, theCopyElements, !myIsPreviewMode ); + + tgtMesh->GetMeshDS()->Modified(); + } + + if ( myIsPreviewMode ) + { + //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements )); + } + else + { + if ( *theMeshName && mesh_var->NbFaces() == 0 ) + { + // new mesh empty, remove it + SALOMEDS::Study_var study = SMESH_Gen_i::getStudyServant(); + SALOMEDS::StudyBuilder_var builder = study->NewBuilder(); + SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::ObjectToSObject( mesh_var ); + builder->RemoveObjectWithChildren( meshSO ); + THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR); + } + if ( !groupIds ) // nothing changed in the current mesh + THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR); + + theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups; + + // result of Offset() is a tuple (mesh, groups) + if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", "; + else pyDump << mesh_var << ", "; + pyDump << theGroups << " = " << this << ".Offset( " + << theObject << ", " + << theValue << ", " + << theCopyGroups << ", " + << theCopyElements << ", " + << "'" << theMeshName<< "')"; + } + + return mesh_var._retn(); + + SMESH_CATCH( SMESH::throwCorbaException ); + return SMESH::SMESH_Mesh::_nil(); +} //======================================================================= //function : findCoincidentNodes @@ -4099,6 +4214,7 @@ FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject, initData(); TIDSortedNodeSet nodes; + prepareIdSource( theObject ); idSourceToNodeSet( theObject, getMeshDS(), nodes ); findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium ); @@ -4113,13 +4229,13 @@ FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject, //================================================================================ /*! - * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within + * \brief Finds nodes coincident with Tolerance within Objects excluding nodes within * ExceptSubMeshOrGroups */ //================================================================================ void SMESH_MeshEditor_i:: -FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject, +FindCoincidentNodesOnPartBut(const SMESH::ListOfIDSources& theObjects, CORBA::Double theTolerance, SMESH::array_of_long_array_out theGroupsOfNodes, const SMESH::ListOfIDSources& theExceptSubMeshOrGroups, @@ -4130,19 +4246,22 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject, initData(); TIDSortedNodeSet nodes; - idSourceToNodeSet( theObject, getMeshDS(), nodes ); - + for ( CORBA::ULong i = 0; i < theObjects.length(); ++i ) + { + prepareIdSource( theObjects[i] ); + idSourceToNodeSet( theObjects[i], getMeshDS(), nodes ); + } for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i ) { - SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i], - SMESH::NODE ); - while ( nodeIt->more() ) - nodes.erase( cast2Node( nodeIt->next() )); + if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i], + SMESH::NODE )) + while ( nodeIt->more() ) + nodes.erase( cast2Node( nodeIt->next() )); } findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium ); TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( " - << theObject<<", " + << theObjects <<", " << theTolerance << ", " << theExceptSubMeshOrGroups << ", " << theSeparateCornersAndMedium << " )"; @@ -4172,9 +4291,9 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i ) { prepareIdSource( NodesToKeep[i] ); - SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ); - while ( nodeIt->more() ) - setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() )); + if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE )) + while ( nodeIt->more() ) + setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() )); } ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes; @@ -4215,30 +4334,47 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN //purpose : //======================================================================= -void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject, - SMESH::array_of_long_array_out GroupsOfElementsID) +void SMESH_MeshEditor_i::FindEqualElements(const SMESH::ListOfIDSources& theObjects, + const SMESH::ListOfIDSources& theExceptObjects, + SMESH::array_of_long_array_out theGroupsOfElementsID) throw (SALOME::SALOME_Exception) { SMESH_TRY; initData(); - SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject); - if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) ) + theGroupsOfElementsID = new SMESH::array_of_long_array; + + TIDSortedElemSet elems; + bool hasOkObject = false; + bool emptyIfIsMesh= ( theObjects.length() == 1 && theExceptObjects.length() == 0 ); + + for ( CORBA::ULong i = 0; i < theObjects.length(); ++i ) + { + SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( theObjects[i] ); + if ( !( !group->_is_nil() && group->GetType() == SMESH::NODE )) + if ( idSourceToSet( theObjects[i], getMeshDS(), elems, SMDSAbs_All, emptyIfIsMesh )) + hasOkObject = true; + } + + if ( hasOkObject ) { - TIDSortedElemSet elems; - idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true); + for ( CORBA::ULong i = 0; i < theExceptObjects.length(); ++i ) + { + if ( SMDS_ElemIteratorPtr elemIt = myMesh_i->GetElements( theExceptObjects[i], SMESH::ALL )) + while ( elemIt->more() ) + elems.erase( elemIt->next() ); + } ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID; getEditor().FindEqualElements( elems, aListOfListOfElementsID ); - GroupsOfElementsID = new SMESH::array_of_long_array; - GroupsOfElementsID->length( aListOfListOfElementsID.size() ); + theGroupsOfElementsID->length( aListOfListOfElementsID.size() ); ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt = aListOfListOfElementsID.begin(); for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j) { - SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ]; + SMESH::long_array& aGroup = (*theGroupsOfElementsID)[ j ]; list& listOfIDs = *arraysIt; aGroup.length( listOfIDs.size() ); list::iterator idIt = listOfIDs.begin(); @@ -4247,7 +4383,8 @@ void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObj } TPythonDump() << "equal_elements = " << this << ".FindEqualElements( " - < idsToKeep; + for ( CORBA::ULong i = 0; i < theElementsToKeep.length(); i++ ) + { + if ( CORBA::is_nil( theElementsToKeep[i] )) + continue; + SMESH::array_of_ElementType_var elemTypes = theElementsToKeep[i]->GetTypes(); + if ( elemTypes->length() == 1 && elemTypes[0] == SMESH::NODE ) + continue; + SMESH::long_array_var elementsId = theElementsToKeep[i]->GetIDs(); + for ( CORBA::ULong j = 0; j < elementsId->length(); ++j ) + idsToKeep.Add( elementsId[ j ]); + } + ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID; - for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) { - const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ]; + for ( CORBA::ULong i = 0; i < theGroupsOfElementsID.length(); i++ ) + { + const SMESH::long_array& anElemsIDGroup = theGroupsOfElementsID[ i ]; aListOfListOfElementsID.push_back( list< int >() ); list< int >& aListOfElemsID = aListOfListOfElementsID.back(); - for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) { + for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) + { CORBA::Long id = anElemsIDGroup[ j ]; - aListOfElemsID.push_back( id ); + if ( idsToKeep.Contains( id )) aListOfElemsID.push_front( id ); + else aListOfElemsID.push_back( id ); } if ( aListOfElemsID.size() < 2 ) aListOfListOfElementsID.pop_back(); @@ -4287,7 +4441,7 @@ void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsO declareMeshModified( /*isReComputeSafe=*/true ); - aTPythonDump << "] )"; + aTPythonDump << "], " << theElementsToKeep << " )"; SMESH_CATCH( SMESH::throwCorbaException ); } @@ -4525,6 +4679,7 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID SMESH_TRY; SMESH::long_array_var res = new SMESH::long_array; + prepareIdSource( elementIDs ); if ( type != SMESH::NODE ) { SMESH::array_of_ElementType_var types = elementIDs->GetTypes(); @@ -4533,6 +4688,16 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID type != types[0] ) // but search of elements of dim > 0 return res._retn(); } + + SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh(); + SMESH_Mesh_i* mesh_i = SMESH::DownCast( mesh ); + if ( mesh_i != myMesh_i ) + { + SMESH::SMESH_MeshEditor_var editor= + myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor(); + return editor->FindAmongElementsByPoint( elementIDs, x,y,z, type ); + } + if ( SMESH::DownCast( elementIDs )) // elementIDs is the whole mesh return FindElementsByPoint( x,y,z, type ); @@ -4542,18 +4707,15 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID if ( !theElementSearcher ) { // create a searcher from elementIDs - SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh(); - SMESHDS_Mesh* meshDS = SMESH::DownCast( mesh )->GetImpl().GetMeshDS(); - - if ( !idSourceToSet( elementIDs, meshDS, elements, - ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ), - /*emptyIfIsMesh=*/true)) - return res._retn(); - - typedef SMDS_SetIterator TIter; - SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() )); - - theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt ); + SMDS_ElemIteratorPtr elemIt; + if ( ! SMESH::DownCast( elementIDs )) + { + //prepareIdSource( elementIDs ); + elemIt = myMesh_i->GetElements( elementIDs, type ); + if ( !elemIt ) + return res._retn(); + } + theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt ); } vector< const SMDS_MeshElement* > foundElems; @@ -4571,6 +4733,72 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID return 0; } +//======================================================================= +//function : ProjectPoint +//purpose : Project a point to a mesh object. +// Return ID of an element of given type where the given point is projected +// and coordinates of the projection point. +// In the case if nothing found, return -1 and [] +//======================================================================= + +CORBA::Long SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x, + CORBA::Double y, + CORBA::Double z, + SMESH::ElementType type, + SMESH::SMESH_IDSource_ptr meshObject, + SMESH::double_array_out projecton) + throw (SALOME::SALOME_Exception) +{ + if ( CORBA::is_nil( meshObject )) + THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM); + + SMESH_TRY; + + SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh(); + SMESH_Mesh_i* mesh_i = SMESH::DownCast( mesh ); + if ( mesh_i != myMesh_i ) + { + SMESH::SMESH_MeshEditor_var editor= + myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor(); + return editor->ProjectPoint( x,y,z, type, meshObject, projecton ); + } + + + theSearchersDeleter.Set( myMesh, getPartIOR( meshObject, type )); + if ( !theElementSearcher ) + { + // create a searcher from meshObject + + SMDS_ElemIteratorPtr elemIt; + if ( ! SMESH::DownCast( meshObject )) + { + prepareIdSource( meshObject ); + elemIt = myMesh_i->GetElements( meshObject, type ); + if ( !elemIt ) + return -1; + } + theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt ); + } + + const SMDS_MeshElement* elem = 0; + gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ), + SMDSAbs_ElementType( type ), + &elem ); + + projecton = new SMESH::double_array(); + if ( elem && !elem->IsNull() ) + { + projecton->length( 3 ); + projecton[0] = pProj.X(); + projecton[1] = pProj.Y(); + projecton[2] = pProj.Z(); + return elem->GetID(); + } + + SMESH_CATCH( SMESH::throwCorbaException ); + return -1; +} + //======================================================================= //function : GetPointState //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration. @@ -4593,6 +4821,298 @@ 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 : Get1DBranches +//purpose : Partition given 1D elements into groups of contiguous edges. +// A node where number of meeting edges != 2 is a group end. +// An optional startNode is used to orient groups it belongs to. +//return : a list of edge groups and a list of corresponding node groups. +// If a group is closed, the first and last nodes of the group are same. +//======================================================================= + +SMESH::array_of_long_array* +SMESH_MeshEditor_i::Get1DBranches( SMESH::SMESH_IDSource_ptr theEdges, + CORBA::Long theStartNode, + SMESH::array_of_long_array_out theNodeGroups ) + throw (SALOME::SALOME_Exception) +{ + if ( CORBA::is_nil( theEdges )) + THROW_SALOME_CORBA_EXCEPTION("Get1DBranches(): NULL group given", SALOME::BAD_PARAM); + + SMESH::array_of_long_array_var edgeGroupArray = new SMESH::array_of_long_array; + theNodeGroups = new SMESH::array_of_long_array; + + SMESH_TRY; + + prepareIdSource( theEdges ); + + SMESH_MeshAlgos::TElemGroupVector edgeBranches; + SMESH_MeshAlgos::TNodeGroupVector nodeBranches; + SMESH_MeshAlgos::Get1DBranches( SMESH_Mesh_i::GetElements( theEdges, SMESH::EDGE ), + edgeBranches, + nodeBranches, + getMeshDS()->FindNode( theStartNode )); + + edgeGroupArray->length( edgeBranches.size() ); + for ( size_t iG = 0; iG < edgeBranches.size(); ++iG ) + { + edgeGroupArray[ iG ].length( edgeBranches[ iG ].size() ); + for ( size_t i = 0; i < edgeBranches[ iG ].size(); ++i ) + edgeGroupArray[ iG ][ i ] = edgeBranches[ iG ][ i ]->GetID(); + } + + theNodeGroups->length( nodeBranches.size() ); + for ( size_t iG = 0; iG < nodeBranches.size(); ++iG ) + { + theNodeGroups[ iG ].length( nodeBranches[ iG ].size() ); + for ( size_t i = 0; i < nodeBranches[ iG ].size(); ++i ) + theNodeGroups[ iG ][ i ] = nodeBranches[ iG ][ i ]->GetID(); + } + + SMESH_CATCH( SMESH::throwCorbaException ); + + return edgeGroupArray._retn(); +} + +//======================================================================= +//function : FindSharpEdges +//purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges. +//======================================================================= + +SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle, + CORBA::Boolean theAddExisting) + throw (SALOME::SALOME_Exception) +{ + SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges; + SMESH_TRY; + + initData(); + + std::vector< SMESH_MeshAlgos::Edge > edges = + SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting ); + + if ( myIsPreviewMode ) // fill a preview mesh with edges + { + TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge ); + SMDS_Mesh* meshDS = mesh->GetMeshDS(); + for ( size_t i = 0; i < edges.size(); ++i ) + { + SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2); + SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() ); + SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() ); + if ( edges[i]._medium ) + { + xyz1.Set( edges[i]._medium ); + SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() ); + mesh->GetMeshDS()->AddEdge( n1, n2, nm ); + } + else + { + mesh->GetMeshDS()->AddEdge( n1, n2 ); + } + } + } + else + { + resultEdges->length( edges.size() ); + for ( size_t i = 0; i < edges.size(); ++i ) + { + resultEdges[ i ].node1 = edges[i]._node1->GetID(); + resultEdges[ i ].node2 = edges[i]._node2->GetID(); + resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0; + } + } + SMESH_CATCH( SMESH::throwCorbaException ); + return resultEdges._retn(); +} + +//======================================================================= +//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. +//======================================================================= + +SMESH::SMESH_Group_ptr +SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole, + const char* theGroupName) + 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; + + // prepare a preview mesh + 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(); + } + + // fill the hole + std::vector newFaces; + SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces ); + + if ( myIsPreviewMode ) + { + // show new faces + previewMesh->Clear(); + for ( size_t i = 0; i < newFaces.size(); ++i ) + previewMesh->Copy( newFaces[i] ); + } + else + { + // return new faces via a group + SMESH::SMESH_Group_var group; + if ( theGroupName && theGroupName[0] && !newFaces.empty() ) + { + SMESH::ListOfGroups_var groups = myMesh_i->GetGroups(); + for ( CORBA::ULong i = 0; i < groups->length(); ++i ) + { + SMESH::SMESH_GroupBase_var g = groups[ i ]; + if ( g->GetType() != SMESH::FACE ) continue; + SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g ); + if ( standalone->_is_nil() ) continue; + CORBA::String_var name = g->GetName(); + if ( strcmp( theGroupName, name.in() ) == 0 ) + { + group = standalone; + break; + } + } + if ( group->_is_nil() ) + group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName ); + + if ( !group->_is_nil() ) + { + SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group ); + SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() ); + for ( size_t i = 0; i < newFaces.size(); ++i ) + grpDS->Add( newFaces[ i ]); + } + } + + // fill LastCreated + getEditor().ClearLastCreated(); + SMESH_SequenceOfElemPtr& aSeq = + const_cast( getEditor().GetLastCreatedElems() ); + aSeq.swap( newFaces ); + + TPythonDump pyDump; + if ( group->_is_nil() ) pyDump << "_group = "; + else pyDump << group << " = "; + pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))"; + + return group._retn(); + } + + SMESH_CATCH( SMESH::throwCorbaException ); + + return SMESH::SMESH_Group::_nil(); +} + //======================================================================= //function : convError //purpose : @@ -5099,23 +5619,20 @@ CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide, initData(); const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide); - if(!elem) return false; + if ( !elem ) return false; int nbn = newIDs.length(); - int i=0; vector aNodes(nbn); - int nbn1=-1; - for(; iFindNode(newIDs[i]); - if(aNode) { - nbn1++; - aNodes[nbn1] = aNode; - } + for ( int i = 0; i < nbn; i++ ) { + const SMDS_MeshNode* aNode = getMeshDS()->FindNode( newIDs[ i ]); + if ( !aNode ) + return false; + aNodes[ i ] = aNode; } TPythonDump() << "isDone = " << this << ".ChangeElemNodes( " << ide << ", " << newIDs << " )"; - bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 ); + bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], aNodes.size() ); declareMeshModified( /*isReComputeSafe=*/ !res ); @@ -5143,8 +5660,8 @@ void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d bool elemsOK; if ( !( elemsOK = CORBA::is_nil( theObject ))) { - elemsOK = idSourceToSet( theObject, getMeshDS(), elems, - SMDSAbs_All, /*emptyIfIsMesh=*/true ); + elemsOK = idSourceToSet( theObject, getMeshDS(), elems, + SMDSAbs_All, /*emptyIfIsMesh=*/true ); } if ( elemsOK ) { @@ -5266,8 +5783,7 @@ SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName) { SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen(); SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh(); - SALOMEDS::Study_var study = gen->GetCurrentStudy(); - SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh ); + SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh ); gen->SetName( meshSO, theMeshName, "Mesh" ); gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED"); @@ -5295,7 +5811,7 @@ void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPytho */ //================================================================================ -std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix) +std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix) { SMESH::ListOfGroups_var groups = myMesh_i->GetGroups(); set groupNames; @@ -5357,10 +5873,21 @@ bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource, } if ( emptyIfIsMesh && SMESH::DownCast( theIDSource )) { - if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 ) + if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 ) *error = IDSource_EMPTY; return true; } + if ( getMeshDS() == theMeshDS ) // check if theIDSource belongs to myMesh + { + SMESH::SMESH_Mesh_var mesh = theIDSource->GetMesh(); + SMESH_Mesh_i* mesh_i = SMESH::DownCast( mesh ); + if ( mesh_i && mesh_i != myMesh_i ) + { + if ( error ) + *error = IDSource_INVALID; + return false; + } + } prepareIdSource( theIDSource ); SMESH::long_array_var anIDs = theIDSource->GetIDs(); if ( anIDs->length() == 0 ) @@ -5400,7 +5927,7 @@ bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource, * \param theElements - container of elements to duplicate. * \param theGroupName - a name of group to contain the generated elements. * If a group with such a name already exists, the new elements - * are added to the existng group, else a new group is created. + * are added to the existing group, else a new group is created. * If \a theGroupName is empty, new elements are not added * in any group. * \return a group where the new elements are added. NULL if theGroupName == "". @@ -5425,11 +5952,11 @@ SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements, { getEditor().DoubleElements( elems ); - if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() ) + if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() ) { // group type SMESH::ElementType type = - SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() ); + SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() ); // find existing group SMESH::ListOfGroups_var groups = myMesh_i->GetGroups(); for ( size_t i = 0; i < groups->length(); ++i ) @@ -5449,8 +5976,8 @@ SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements, { SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() ); const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems(); - for ( int i = 1; i <= aSeq.Length(); i++ ) - groupDS->SMDSGroup().Add( aSeq(i) ); + for ( size_t i = 0; i < aSeq.size(); i++ ) + groupDS->SMDSGroup().Add( aSeq[i] ); } } } @@ -5562,10 +6089,7 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr th if ( !CORBA::is_nil( theModifiedElems ) ) aModifiedElems = theModifiedElems->GetListOfID(); else - { aModifiedElems = new SMESH::long_array; - aModifiedElems->length( 0 ); - } TPythonDump pyDump; // suppress dump by the next line @@ -5620,7 +6144,7 @@ SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes, SMESH::long_array_var anIds = GetLastCreatedNodes(); if (anIds->length() > 0) { std::string anUnindexedName (theNodes->GetName()); - std::string aNewName = generateGroupName(anUnindexedName + "_double"); + std::string aNewName = GenerateGroupName(anUnindexedName + "_double"); aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str()); aNewGroup->Add(anIds); pyDump << aNewGroup << " = "; @@ -5719,7 +6243,7 @@ SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes, SMESH::long_array_var anIds = GetLastCreatedNodes(); if (anIds->length() > 0) { std::string anUnindexedName (theNodes[0]->GetName()); - std::string aNewName = generateGroupName(anUnindexedName + "_double"); + std::string aNewName = GenerateGroupName(anUnindexedName + "_double"); aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str()); aNewGroup->Add(anIds); pyDump << aNewGroup << " = "; @@ -5943,15 +6467,15 @@ SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems, { // Create group with newly created elements CORBA::String_var elemGroupName = theElems->GetName(); - std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double"); - if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded ) + std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double"); + if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded ) { SMESH::long_array_var anIds = GetLastCreatedElems(); SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true); aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str()); aNewElemGroup->Add(anIds); } - if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded ) + if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded ) { SMESH::long_array_var anIds = GetLastCreatedNodes(); aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str()); @@ -6175,15 +6699,15 @@ SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems { // Create group with newly created elements CORBA::String_var elemGroupName = theElems[0]->GetName(); - std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double"); - if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded ) + std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double"); + if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded ) { SMESH::long_array_var anIds = GetLastCreatedElems(); SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true); aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str()); aNewElemGroup->Add(anIds); } - if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded ) + if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded ) { SMESH::long_array_var anIds = GetLastCreatedNodes(); aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str()); @@ -6278,12 +6802,9 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl { SMESH_TRY; SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups(); - bool isEdgeGroup = false; - bool isFaceGroup = false; - bool isVolumeGroup = false; - SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges"); - SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces"); - SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes"); + SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil(); + SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil(); + SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil(); initData(); @@ -6291,75 +6812,75 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl SMESHDS_Mesh* aMeshDS = getMeshDS(); TIDSortedElemSet anElems, aNodes; - listOfGroupToSet(theElems, aMeshDS, anElems, false); + bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false; + listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp); listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true); TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape); TIDSortedElemSet anAffected; bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected); - declareMeshModified( /*isReComputeSafe=*/ !aResult ); TPythonDump pyDump; - if (aResult) + if ( aResult && anAffected.size() > 0 ) { - int lg = anAffected.size(); SMESH::long_array_var volumeIds = new SMESH::long_array; - volumeIds->length(lg); - SMESH::long_array_var faceIds = new SMESH::long_array; - faceIds->length(lg); - SMESH::long_array_var edgeIds = new SMESH::long_array; - edgeIds->length(lg); + SMESH::long_array_var faceIds = new SMESH::long_array; + SMESH::long_array_var edgeIds = new SMESH::long_array; + volumeIds->length( anAffected.size() ); + faceIds ->length( anAffected.size() ); + edgeIds ->length( anAffected.size() ); + int ivol = 0; int iface = 0; int iedge = 0; - TIDSortedElemSet::const_iterator eIt = anAffected.begin(); for (; eIt != anAffected.end(); ++eIt) { const SMDS_MeshElement* anElem = *eIt; - if (!anElem) - continue; int elemId = anElem->GetID(); - if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume) - volumeIds[ivol++] = elemId; - else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face) - faceIds[iface++] = elemId; - else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge) - edgeIds[iedge++] = elemId; + switch ( anElem->GetType() ) { + case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break; + case SMDSAbs_Face: faceIds[iface++] = elemId; break; + case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break; + default:; + } } volumeIds->length(ivol); faceIds->length(iface); edgeIds->length(iedge); - aNewVolumeGroup->Add(volumeIds); - aNewFaceGroup->Add(faceIds); - aNewEdgeGroup->Add(edgeIds); - isVolumeGroup = (aNewVolumeGroup->Size() > 0); - isFaceGroup = (aNewFaceGroup->Size() > 0); - isEdgeGroup = (aNewEdgeGroup->Size() > 0); + int nbGroups = 0; + if ( ivol > 0 ) + { + aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, + GenerateGroupName("affectedVolumes").c_str()); + aNewVolumeGroup->Add(volumeIds); + aListOfGroups->length( nbGroups+1 ); + aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn(); + } + if ( iface > 0 ) + { + aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, + GenerateGroupName("affectedFaces").c_str()); + aNewFaceGroup->Add(faceIds); + aListOfGroups->length( nbGroups+1 ); + aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn(); + } + if ( iedge > 0 ) + { + aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, + GenerateGroupName("affectedEdges").c_str()); + aNewEdgeGroup->Add(edgeIds); + aListOfGroups->length( nbGroups+1 ); + aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn(); + } } - int nbGroups = 0; - if (isEdgeGroup) nbGroups++; - if (isFaceGroup) nbGroups++; - if (isVolumeGroup) nbGroups++; - aListOfGroups->length(nbGroups); - - int i = 0; - if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn(); - if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn(); - if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn(); - // Update Python script - pyDump << "[ "; - if (isEdgeGroup) pyDump << aNewEdgeGroup << ", "; - if (isFaceGroup) pyDump << aNewFaceGroup << ", "; - if (isVolumeGroup) pyDump << aNewVolumeGroup << ", "; - pyDump << "] = "; - pyDump << this << ".AffectedElemGroupsInRegion( " + pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( " << &theElems << ", " << &theNodesNot << ", " << theShape << " )"; return aListOfGroups._retn(); @@ -6371,7 +6892,7 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl //================================================================================ /*! \brief Generated skin mesh (containing 2D cells) from 3D mesh - The created 2D mesh elements based on nodes of free faces of boundary volumes + The created 2D mesh elements based on nodes of free faces of boundary volumes \return TRUE if operation has been completed successfully, FALSE otherwise */ //================================================================================ @@ -6712,7 +7233,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim, for ( CORBA::ULong i = 0; i < groups.length(); ++i ) { SMESH::SMESH_Mesh_var m = groups[i]->GetMesh(); - if ( myMesh_i != SMESH::DownCast( m )) + if ( !m->_is_nil() && myMesh_i != SMESH::DownCast( m )) groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i]; else groupsOfThisMesh[ nbGroups++ ] = groups[i]; @@ -6760,7 +7281,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim, // group of boundary elements SMESH_Group* smesh_group = 0; SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face; - if ( strlen(groupName) ) + if ( strlen( groupName )) { SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 ); group_var = mesh_i->CreateGroup( groupType, groupName ); @@ -6828,3 +7349,194 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim, SMESH_CATCH( SMESH::throwCorbaException ); return 0; } + +//================================================================================ +/*! + * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of + * the initial mesh. Positions of new nodes are found by cutting the mesh by the + * plane passing through pairs of points specified by each PolySegment structure. + * If there are several paths connecting a pair of points, the shortest path is + * selected by the module. Position of the cutting plane is defined by the two + * points and an optional vector lying on the plane specified by a PolySegment. + * By default the vector is defined by Mesh module as following. A middle point + * of the two given points is computed. The middle point is projected to the mesh. + * The vector goes from the middle point to the projection point. In case of planar + * mesh, the vector is normal to the mesh. + * \param [inout] segments - PolySegment's defining positions of cutting planes. + * Return the used vector and position of the middle point. + * \param [in] groupName - optional name of a group where created mesh segments will + * be added. + */ +//================================================================================ + +void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments, + const char* theGroupName) + throw (SALOME::SALOME_Exception) +{ + if ( theSegments.length() == 0 ) + THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM ); + if ( myMesh->NbFaces() == 0 ) + THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM ); + + SMESH_TRY; + initData(/*deleteSearchers=*/false); + + SMESHDS_Group* groupDS = 0; + SMESHDS_Mesh* meshDS = getMeshDS(); + if ( myIsPreviewMode ) // copy faces to the tmp mesh + { + TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge ); + SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face ); + while ( faceIt->more() ) + tmpMesh->Copy( faceIt->next() ); + meshDS = tmpMesh->GetMeshDS(); + } + else if ( theGroupName[0] ) // find/create a group of segments + { + // SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups(); + // while ( !groupDS && grpIt->more() ) + // { + // SMESH_Group* group = grpIt->next(); + // if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge && + // strcmp( group->GetName(), theGroupName ) == 0 ) + // { + // groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() ); + // } + // } + if ( !groupDS ) + { + SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName ); + + if ( SMESH_Group_i* groupImpl = SMESH::DownCast( groupVar )) + groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() ); + } + } + + // convert input polySegments + SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() ); + for ( CORBA::ULong i = 0; i < theSegments.length(); ++i ) + { + SMESH::PolySegment& segIn = theSegments[ i ]; + SMESH_MeshAlgos::PolySegment& segOut = segments[ i ]; + segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 ); + segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 ); + segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 ); + segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 ); + segOut.myXYZ[0].SetCoord( segIn.xyz1.x, + segIn.xyz1.y, + segIn.xyz1.z); + segOut.myXYZ[1].SetCoord( segIn.xyz2.x, + segIn.xyz2.y, + segIn.xyz2.z); + segOut.myVector.SetCoord( segIn.vector.PS.x, + segIn.vector.PS.y, + segIn.vector.PS.z ); + } + + // get a static ElementSearcher + SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() ); + theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE )); + if ( !theElementSearcher ) + theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() ); + + // compute + std::vector newEdges; + std::vector newNodes; + SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes, + groupDS ? &groupDS->SMDSGroup() : 0, + theElementSearcher ); + + const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ). + swap( newEdges ); + const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ). + assign( newNodes.begin(), newNodes.end() ); + + // return vectors + if ( myIsPreviewMode ) + { + for ( CORBA::ULong i = 0; i < theSegments.length(); ++i ) + { + SMESH::PolySegment& segOut = theSegments[ i ]; + SMESH_MeshAlgos::PolySegment& segIn = segments[ i ]; + segOut.vector.PS.x = segIn.myVector.X(); + segOut.vector.PS.y = segIn.myVector.Y(); + segOut.vector.PS.z = segIn.myVector.Z(); + } + } + else + { + TPythonDump() << "_segments = []"; + for ( CORBA::ULong i = 0; i < theSegments.length(); ++i ) + { + SMESH::PolySegment& segIn = theSegments[ i ]; + TPythonDump() << "_segments.append( SMESH.PolySegment( " + << segIn.node1ID1 << ", " + << segIn.node1ID2 << ", " + << segIn.node2ID1 << ", " + << segIn.node2ID2 << ", " + << "smeshBuilder.MakeDirStruct( " + << segIn.vector.PS.x << ", " + << segIn.vector.PS.y << ", " + << segIn.vector.PS.z << ")))"; + } + TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')"; + } + meshDS->Modified(); + SMESH_CATCH( SMESH::throwCorbaException ); + return; +} + +//================================================================================ +/*! + * \brief Create a slot of given width around given 1D elements lying on a triangle mesh. + * The slot is constructed by cutting faces by cylindrical surfaces made + * around each segment. Segments are expected to be created by MakePolyLine(). + * \return Edges located at the slot boundary + */ +//================================================================================ + +SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments, + CORBA::Double theWidth) + throw (SALOME::SALOME_Exception) +{ + if ( CORBA::is_nil( theSegments ) || + theSegments->GetType() != SMESH::EDGE ) + THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM ); + if ( myMesh->NbFaces() == 0 ) + THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM ); + + SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges; + + SMESH_TRY; + initData(/*deleteSearchers=*/false); + + SMESHDS_Mesh* meshDS = getMeshDS(); + + // get standalone face groups to be updated + std::vector< SMDS_MeshGroup* > faceGroups; + const std::set& allGroups = meshDS->GetGroups(); + std::set::const_iterator grIt = allGroups.begin(); + for ( ; grIt != allGroups.end(); ++grIt ) + if ( const SMESHDS_Group* gr = dynamic_cast< const SMESHDS_Group* >( *grIt )) + if ( gr->GetType() == SMDSAbs_Face ) + faceGroups.push_back( & const_cast< SMESHDS_Group* >( gr )->SMDSGroup() ); + + std::vector< SMESH_MeshAlgos::Edge > edges = + SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ), + theWidth, meshDS, faceGroups ); + + resultEdges->length( edges.size() ); + for ( size_t i = 0; i < edges.size(); ++i ) + { + resultEdges[ i ].node1 = edges[i]._node1->GetID(); + resultEdges[ i ].node2 = edges[i]._node2->GetID(); + resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0; + } + + meshDS->Modified(); + SMESH_CATCH( SMESH::throwCorbaException ); + + TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed + + return resultEdges._retn(); +}