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=763f976e4e758859ae76dff901ed5877fb8bd8c2;hp=4683044f5f9bf7c2abafae3986f1e1d01cac9728;hb=52d825495306f72048c8754aa5c86c6a390f8262;hpb=c23ba6b3e4bc9ad07eac19ea1856b7bb36161a6a diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index 4683044f5..763f976e4 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2014 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 @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,7 +23,7 @@ // Author : Nicolas REJNERI // Module : SMESH -#ifdef WNT +#ifdef WIN32 #define NOMINMAX #endif @@ -63,6 +63,8 @@ #include #include #include +#include +#include #include #include @@ -176,6 +178,10 @@ namespace MeshEditor_I { return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(), anElemNode->GetID()); } + void RemoveAll() + { + GetMeshDS()->ClearMesh(); + } };// struct TPreviewMesh static SMESH_NodeSearcher * theNodeSearcher = 0; @@ -222,22 +228,22 @@ namespace MeshEditor_I { } myMesh = mesh; myMeshPartIOR = meshPartIOR; - if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) { - const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn(); - TDependsOnMap::const_iterator sm; - for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++) - sm->second->SetEventListener( this, 0, sm->second ); + SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() ); + SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true ); + while ( smIt->more() ) + { + sm = smIt->next(); + sm->SetEventListener( this, 0, sm ); } } } //!< delete self from all submeshes void Unset(SMESH_Mesh* mesh) { - if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) { - const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn(); - TDependsOnMap::const_iterator sm; - for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++) - sm->second->DeleteEventListener( this ); + if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) { + SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true ); + while ( smIt->more() ) + smIt->next()->DeleteEventListener( this ); } myMesh = 0; } @@ -272,12 +278,16 @@ namespace MeshEditor_I { void arrayToSet(const SMESH::long_array & IDs, const SMESHDS_Mesh* aMesh, TIDSortedElemSet& aMap, - const SMDSAbs_ElementType aType = SMDSAbs_All ) + const SMDSAbs_ElementType aType = SMDSAbs_All, + SMDS_MeshElement::Filter* aFilter = NULL) { SMDS_MeshElement::NonNullFilter filter1; SMDS_MeshElement::TypeFilter filter2( aType ); - SMDS_MeshElement::Filter & filter = - ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter&) filter1 : filter2; + + if ( aFilter == NULL ) + aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2; + + SMDS_MeshElement::Filter & filter = *aFilter; if ( aType == SMDSAbs_Node ) for (int i=0; i( theIDSource )) + { + if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 ) + *error = IDSource_EMPTY; return true; - + } SMESH::long_array_var anIDs = theIDSource->GetIDs(); if ( anIDs->length() == 0 ) + { + if ( error ) *error = IDSource_EMPTY; return false; + } SMESH::array_of_ElementType_var types = theIDSource->GetTypes(); if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes { if ( theType == SMDSAbs_All || theType == SMDSAbs_Node ) + { arrayToSet( anIDs, theMeshDS, theElemSet, SMDSAbs_Node ); + } else + { + if ( error ) *error = IDSource_INVALID; return false; + } } else { arrayToSet( anIDs, theMeshDS, theElemSet, theType); - return bool(anIDs->length()) == bool(theElemSet.size()); + if ( bool(anIDs->length()) != bool(theElemSet.size())) + { + if ( error ) *error = IDSource_INVALID; + return false; + } } return true; } @@ -453,7 +486,11 @@ SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview): SMESH_MeshEditor_i::~SMESH_MeshEditor_i() { - deleteAuxIDSources(); + PortableServer::POA_var poa = SMESH_Gen_i::GetPOA(); + PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this); + poa->deactivate_object(anObjectId.in()); + + //deleteAuxIDSources(); delete myPreviewMesh; myPreviewMesh = 0; delete myPreviewEditor; myPreviewEditor = 0; } @@ -467,7 +504,7 @@ SMESH_MeshEditor_i::~SMESH_MeshEditor_i() void SMESH_MeshEditor_i::initData(bool deleteSearchers) { if ( myIsPreviewMode ) { - if ( myPreviewMesh ) myPreviewMesh->Clear(); + if ( myPreviewMesh ) myPreviewMesh->RemoveAll(); } else { if ( deleteSearchers ) @@ -711,10 +748,12 @@ SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError() //======================================================================= //function : MakeIDSource -//purpose : Wrap a sequence of ids in a SMESH_IDSource +//purpose : Wrap a sequence of ids in a SMESH_IDSource. +// Call UnRegister() as you fininsh using it!! //======================================================================= -struct SMESH_MeshEditor_i::_IDSource : public POA_SMESH::SMESH_IDSource +struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource, + public virtual SALOME::GenericObj_i { SMESH::long_array _ids; SMESH::ElementType _type; @@ -745,16 +784,16 @@ struct SMESH_MeshEditor_i::_IDSource : public POA_SMESH::SMESH_IDSource SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids, SMESH::ElementType type) { - if ( myAuxIDSources.size() > 10 ) { - delete myAuxIDSources.front(); - myAuxIDSources.pop_front(); - } + // if ( myAuxIDSources.size() > 10 ) { + // delete myAuxIDSources.front(); + // myAuxIDSources.pop_front(); + // } _IDSource* idSrc = new _IDSource; idSrc->_mesh = myMesh_i->_this(); idSrc->_ids = ids; idSrc->_type = type; - myAuxIDSources.push_back( idSrc ); + //myAuxIDSources.push_back( idSrc ); SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this(); @@ -778,13 +817,13 @@ CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idS return 0; } -void SMESH_MeshEditor_i::deleteAuxIDSources() -{ - std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin(); - for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt ) - delete *idSrcIt; - myAuxIDSources.clear(); -} +// void SMESH_MeshEditor_i::deleteAuxIDSources() +// { +// std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin(); +// for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt ) +// delete *idSrcIt; +// myAuxIDSources.clear(); +// } //============================================================================= /*! @@ -1629,7 +1668,11 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup, TIDSortedElemSet elements; prepareIdSource( the2Dgroup ); - if ( !idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1)) + IDSource_Error error; + idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error ); + if ( error == IDSource_EMPTY ) + return 0; + if ( error == IDSource_INVALID ) THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM); @@ -1695,6 +1738,58 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup, return 0; } +//======================================================================= +//function : Reorient2DBy3D +//purpose : Reorient faces basing on orientation of adjacent volumes. +//======================================================================= + +CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups, + SMESH::SMESH_IDSource_ptr volumeGroup, + CORBA::Boolean outsideNormal) + throw (SALOME::SALOME_Exception) +{ + SMESH_TRY; + initData(); + + TIDSortedElemSet volumes; + prepareIdSource( volumeGroup ); + IDSource_Error volsError; + idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError); + + int nbReori = 0; + for ( size_t i = 0; i < faceGroups.length(); ++i ) + { + SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in(); + prepareIdSource( faceGrp ); + + TIDSortedElemSet faces; + IDSource_Error error; + idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error ); + if ( error == IDSource_INVALID && faceGroups.length() == 1 ) + THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM); + if ( error == IDSource_OK && volsError != IDSource_OK ) + THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM); + + nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal ); + + if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated + break; + } + + if ( nbReori ) { + declareMeshModified( /*isReComputeSafe=*/false ); + } + TPythonDump() << this << ".Reorient2DBy3D( " + << faceGroups << ", " + << volumeGroup << ", " + << outsideNormal << " )"; + + return nbReori; + + SMESH_CATCH( SMESH::throwCorbaException ); + return 0; +} + //============================================================================= /*! * \brief Fuse neighbour triangles into quadrangles. @@ -1710,8 +1805,16 @@ CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfE initData(); SMESHDS_Mesh* aMesh = getMeshDS(); - TIDSortedElemSet faces; - arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face); + TIDSortedElemSet faces,copyFaces; + SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE); + arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter); + TIDSortedElemSet* workElements = & faces; + + if ( myIsPreviewMode ) { + SMDSAbs_ElementType select = SMDSAbs_Face; + getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select ); + workElements = & copyFaces; + } SMESH::NumericalFunctor_i* aNumericalFunctor = dynamic_cast( SMESH_Gen_i::GetServant( Criterion ).in() ); @@ -1721,12 +1824,13 @@ CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfE else aCrit = aNumericalFunctor->GetNumericalFunctor(); - // Update Python script - TPythonDump() << "isDone = " << this << ".TriToQuad( " - << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )"; - + if ( !myIsPreviewMode ) { + // Update Python script + TPythonDump() << "isDone = " << this << ".TriToQuad( " + << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )"; + } - bool stat = getEditor().TriToQuad( faces, aCrit, MaxAngle ); + bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle ); declareMeshModified( /*isReComputeSafe=*/!stat ); return stat; @@ -1755,12 +1859,14 @@ CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr SMESH::long_array_var anElementsId = theObject->GetIDs(); CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle); - SMESH::NumericalFunctor_i* aNumericalFunctor = - SMESH::DownCast( Criterion ); + if ( !myIsPreviewMode ) { + SMESH::NumericalFunctor_i* aNumericalFunctor = + SMESH::DownCast( Criterion ); - // Update Python script - aTPythonDump << "isDone = " << this << ".TriToQuadObject(" - << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )"; + // Update Python script + aTPythonDump << "isDone = " << this << ".TriToQuadObject(" + << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )"; + } return isDone; @@ -1954,6 +2060,7 @@ CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad, int id = getEditor().BestSplit(quad, aCrit); declareMeshModified( /*isReComputeSafe=*/ id < 1 ); + return id; } SMESH_CATCH( SMESH::throwCorbaException ); @@ -1972,13 +2079,15 @@ void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems, { SMESH_TRY; initData(); - prepareIdSource( elems ); - SMESH::long_array_var anElementsId = elems->GetIDs(); - TIDSortedElemSet elemSet; - arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume ); - getEditor().SplitVolumesIntoTetra( elemSet, int( methodFlags )); + ::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 )); + + getEditor().SplitVolumes( elemSet, int( methodFlags )); declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute() TPythonDump() << this << ".SplitVolumesIntoTetra( " @@ -1987,6 +2096,70 @@ void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems, SMESH_CATCH( SMESH::throwCorbaException ); } +//================================================================================ +/*! + * \brief Split hexahedra into triangular prisms + * \param elems - elements to split + * \param facetToSplitNormal - normal used to find a facet of hexahedron + * to split into triangles + * \param methodFlags - flags passing splitting method: + * 1 - split the hexahedron into 2 prisms + * 2 - split the hexahedron into 4 prisms + */ +//================================================================================ + +void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr elems, + const SMESH::PointStruct & startHexPoint, + const SMESH::DirStruct& facetToSplitNormal, + CORBA::Short methodFlags, + CORBA::Boolean allDomains) + throw (SALOME::SALOME_Exception) +{ + SMESH_TRY; + initData(); + prepareIdSource( elems ); + + gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x, + startHexPoint.y, + startHexPoint.z ), + gp_Dir( facetToSplitNormal.PS.x, + facetToSplitNormal.PS.y, + facetToSplitNormal.PS.z )); + TIDSortedElemSet elemSet; + SMESH::long_array_var anElementsId = elems->GetIDs(); + SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA ); + arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter ); + + ::SMESH_MeshEditor::TFacetOfElem elemFacets; + while ( !elemSet.empty() ) + { + getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets ); + if ( !allDomains ) + break; + + ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin(); + for ( ; ef != elemFacets.end(); ++ef ) + elemSet.erase( ef->first ); + } + + if ( methodFlags == 2 ) + methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS ); + else + methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS ); + + getEditor().SplitVolumes( elemFacets, int( methodFlags )); + declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute() + + TPythonDump() << this << ".SplitHexahedraIntoPrisms( " + << elems << ", " + << startHexPoint << ", " + << facetToSplitNormal<< ", " + << methodFlags<< ", " + << allDomains << " )"; + + SMESH_CATCH( SMESH::throwCorbaException ); +} + //======================================================================= //function : Smooth //purpose : @@ -2551,7 +2724,7 @@ SMESH_MeshEditor_i::extrusionSweep(const SMESH::long_array & theIDsOfElements, theMakeGroups = false; } - TElemOfElemListMap aHystory; + ::SMESH_MeshEditor::TTElemOfElemListMap aHystory; ::SMESH_MeshEditor::PGroupIDs groupIds = getEditor().ExtrusionSweep (*workElements, stepVec, theNbOfSteps, aHystory, theMakeGroups); @@ -2843,7 +3016,7 @@ SMESH_MeshEditor_i::advancedExtrusion(const SMESH::long_array & theIDsOfElements const SMESH::PointStruct * P = &theStepVector.PS; gp_Vec stepVec( P->x, P->y, P->z ); - TElemOfElemListMap aHystory; + ::SMESH_MeshEditor::TTElemOfElemListMap aHystory; ::SMESH_MeshEditor::PGroupIDs groupIds = getEditor().ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory, theMakeGroups, theExtrFlags, theSewTolerance); @@ -4574,9 +4747,16 @@ SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject, }; double tol = std::numeric_limits::max(); gp_Trsf aTrsf; + +#if OCC_VERSION_LARGE > 0x06070100 + 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]) ); +#else 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; @@ -5160,13 +5340,6 @@ SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x, for ( int i = 0; i < foundElems.size(); ++i ) res[i] = foundElems[i]->GetID(); - if ( !myIsPreviewMode ) // call from tui - TPythonDump() << "res = " << this << ".FindElementsByPoint( " - << x << ", " - << y << ", " - << z << ", " - << type << " )"; - return res._retn(); SMESH_CATCH( SMESH::throwCorbaException ); @@ -5228,14 +5401,6 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID for ( int i = 0; i < foundElems.size(); ++i ) res[i] = foundElems[i]->GetID(); - if ( !myIsPreviewMode ) // call from tui - TPythonDump() << "res = " << this << ".FindAmongElementsByPoint( " - << elementIDs << ", " - << x << ", " - << y << ", " - << z << ", " - << type << " )"; - return res._retn(); SMESH_CATCH( SMESH::throwCorbaException ); @@ -6797,18 +6962,21 @@ CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D() * If there is no shared faces between the group #n and the group #p in the list, the group j_n_p is not created. * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation). * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples". - * @param theDomains - list of groups of volumes - * @param createJointElems - if TRUE, create the elements - * @return TRUE if operation has been completed successfully, FALSE otherwise + * \param theDomains - list of groups of volumes + * \param createJointElems - if TRUE, create the elements + * \param onAllBoundaries - if TRUE, the nodes and elements are also created on + * the boundary between \a theDomains and the rest mesh + * \return TRUE if operation has been completed successfully, FALSE otherwise */ //================================================================================ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains, - CORBA::Boolean createJointElems ) + CORBA::Boolean createJointElems, + CORBA::Boolean onAllBoundaries ) throw (SALOME::SALOME_Exception) { - bool aResult = false; + bool isOK = false; SMESH_TRY; initData(); @@ -6816,10 +6984,11 @@ SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& the SMESHDS_Mesh* aMeshDS = getMeshDS(); // MESSAGE("theDomains.length = "< domains; - domains.clear(); + domains.resize( theDomains.length() ); for ( int i = 0, n = theDomains.length(); i < n; i++ ) { @@ -6828,26 +6997,25 @@ SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& the { // if ( aGrp->GetType() != SMESH::VOLUME ) // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM); - TIDSortedElemSet domain; - domain.clear(); - domains.push_back(domain); SMESH::long_array_var anIDs = aGrp->GetIDs(); arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All ); } } - aResult = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems ); + isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries ); // TODO publish the groups of flat elements in study - declareMeshModified( /*isReComputeSafe=*/ !aResult ); + declareMeshModified( /*isReComputeSafe=*/ !isOK ); // Update Python script TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains - << ", " << createJointElems << " )"; + << ", " << createJointElems << ", " << onAllBoundaries << " )"; SMESH_CATCH( SMESH::throwCorbaException ); - return aResult; + myMesh_i->CreateGroupServants(); // publish created groups if any + + return isOK; } //================================================================================