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=d7afbed39f5ec69c7c73eefbbf905161daf70672;hp=d233bb63fa7c62b3ae7ce33c9692b70955526da9;hb=47e876676d669fed6615392e614a3ff4441a57ef;hpb=d06e689ac77d94233be447aed68bdaa54992baf0 diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index d233bb63f..d7afbed39 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2016 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 @@ -64,7 +64,6 @@ #include #include #include -#include #include #include @@ -76,15 +75,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 @@ -114,8 +106,6 @@ namespace MeshEditor_I { _myMeshDS = new SMESHDS_Mesh( _id, true ); myPreviewType = previewElements; } - //!< Destructor - virtual ~TPreviewMesh() { delete _myMeshDS; _myMeshDS = 0; } //!< Copy a set of elements void Copy(const TIDSortedElemSet & theElements, TIDSortedElemSet& theCopyElements, @@ -156,20 +146,11 @@ namespace MeshEditor_I { } // creates a corresponding element on copied nodes - SMDS_MeshElement* anElemCopy = 0; - if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume ) - { - const SMDS_VtkVolume* ph = - dynamic_cast (anElem); - if ( ph ) - anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID - (anElemNodesID, ph->GetQuantities(),anElem->GetID()); - } - else { - anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID, - anElem->GetType(), - anElem->IsPoly() ); - } + ::SMESH_MeshEditor::ElemFeatures elemType; + elemType.Init( anElem, /*basicOnly=*/false ); + elemType.SetID( anElem->GetID() ); + SMDS_MeshElement* anElemCopy = + ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType ); return anElemCopy; } //!< Copy a node @@ -182,6 +163,15 @@ namespace MeshEditor_I { { GetMeshDS()->ClearMesh(); } + void Remove( SMDSAbs_ElementType type ) + { + Remove( GetMeshDS()->elementsIterator( type )); + } + void Remove( SMDS_ElemIteratorPtr eIt ) + { + while ( eIt->more() ) + GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false ); + } };// struct TPreviewMesh static SMESH_NodeSearcher * theNodeSearcher = 0; @@ -189,7 +179,7 @@ namespace MeshEditor_I { //============================================================================= /*! - * \brief Deleter of theNodeSearcher at any compute event occured + * \brief Deleter of theNodeSearcher at any compute event occurred */ //============================================================================= @@ -290,13 +280,13 @@ namespace MeshEditor_I { SMDS_MeshElement::Filter & filter = *aFilter; if ( aType == SMDSAbs_Node ) - for (int i=0; iFindNode( IDs[i] ); if ( filter( elem )) aMap.insert( aMap.end(), elem ); } else - for (int i=0; iFindElement( IDs[i] ); if ( filter( elem )) aMap.insert( aMap.end(), elem ); @@ -320,7 +310,7 @@ namespace MeshEditor_I { SMESH::long_array_var aElementsId = theObject->GetIDs(); if ( types->length() == 1 && types[0] == SMESH::NODE) { - for(int i = 0; i < aElementsId->length(); i++) + for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ ) if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] )) theNodeSet.insert( theNodeSet.end(), n); } @@ -328,13 +318,13 @@ namespace MeshEditor_I { { SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator(); while ( nIt->more( )) - if( const SMDS_MeshElement * elem = nIt->next() ) + if ( const SMDS_MeshElement * elem = nIt->next() ) theNodeSet.insert( elem->begin_nodes(), elem->end_nodes()); } else { - for(int i = 0; i < aElementsId->length(); i++) - if( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] )) + 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()); } } @@ -354,7 +344,7 @@ namespace MeshEditor_I { SMDSAbs_ElementType elemType = (*theElements.begin())->GetType(); bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() ); if ( sameElemType && - theMeshDS->GetMeshInfo().NbElements( elemType ) == theElements.size() ) + theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() ) return; // all the elements are in theElements if ( !sameElemType ) @@ -472,9 +462,9 @@ void SMESH_MeshEditor_i::initData(bool deleteSearchers) //================================================================================ /*! * \brief Increment mesh modif time and optionally record that the performed - * modification may influence futher mesh re-compute. - * \param [in] isReComputeSafe - true if the modification does not infulence - * futher mesh re-compute + * modification may influence further mesh re-compute. + * \param [in] isReComputeSafe - true if the modification does not influence + * further mesh re-compute */ //================================================================================ @@ -506,7 +496,7 @@ void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe ) * \brief Initialize and return myPreviewMesh * \param previewElements - type of elements to show in preview * - * WARNING: call it once par a method! + * WARNING: call it once per method! */ //================================================================================ @@ -531,18 +521,18 @@ TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewEle SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData() throw (SALOME::SALOME_Exception) -{ +{ 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 )); aMeshDS = aMeshPartDS.get(); @@ -553,7 +543,7 @@ SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData() myPreviewData = new SMESH::MeshPreviewStruct(); myPreviewData->nodesXYZ.length(aMeshDS->NbNodes()); - + SMDSAbs_ElementType previewType = SMDSAbs_All; if ( !hasBadElems ) if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) { @@ -573,7 +563,10 @@ SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData() while ( itMeshElems->more() ) { const SMDS_MeshElement* aMeshElem = itMeshElems->next(); - SMDS_NodeIteratorPtr itElemNodes = aMeshElem->nodeIterator(); + SMDS_NodeIteratorPtr itElemNodes = + (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ? + aMeshElem->interlacedNodesIterator() : + aMeshElem->nodeIterator() ); while ( itElemNodes->more() ) { const SMDS_MeshNode* aMeshNode = itElemNodes->next(); int aNodeID = aMeshNode->GetID(); @@ -625,9 +618,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 ); @@ -648,9 +641,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 ); @@ -671,7 +664,7 @@ void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception) //======================================================================= /* - * Returns description of an error/warning occured during the last operation + * Returns description of an error/warning occurred during the last operation * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API */ //======================================================================= @@ -796,7 +789,7 @@ SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements) list< int > IdList; - for (int i = 0; i < IDsOfElements.length(); i++) + for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ ) IdList.push_back( IDsOfElements[i] ); // Update Python script @@ -825,7 +818,7 @@ CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNo initData(); list< int > IdList; - for (int i = 0; i < IDsOfNodes.length(); i++) + for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++) IdList.push_back( IDsOfNodes[i] ); // Update Python script @@ -861,9 +854,7 @@ CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes() SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq ); // remove orphan nodes (if there are any) - list< int > IdList; - for ( int i = 0; i < seq.size(); i++ ) - IdList.push_back( seq[i] ); + list< int > IdList( seq.begin(), seq.end() ); int nbNodesBefore = myMesh->NbNodes(); getEditor().Remove( IdList, true ); @@ -907,14 +898,19 @@ CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA:: */ //============================================================================= -CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode) +CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode, + CORBA::Boolean DuplicateElements) throw (SALOME::SALOME_Exception) { SMESH_TRY; initData(); const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode); - SMDS_MeshElement* elem = getMeshDS()->Add0DElement(aNode); + SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement ); + + SMDS_MeshElement* elem = 0; + if ( DuplicateElements || !it0D->more() ) + elem = getMeshDS()->Add0DElement(aNode); // Update Python script TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )"; @@ -1055,6 +1051,7 @@ CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes) * AddPolygonalFace */ //============================================================================= + CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes) throw (SALOME::SALOME_Exception) { @@ -1064,7 +1061,8 @@ CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsO int NbNodes = IDsOfNodes.length(); std::vector nodes (NbNodes); for (int i = 0; i < NbNodes; i++) - nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]); + if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] ))) + return 0; const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes); @@ -1078,6 +1076,35 @@ CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsO return 0; } +//============================================================================= +/*! + * AddQuadPolygonalFace + */ +//============================================================================= + +CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes) + throw (SALOME::SALOME_Exception) +{ + SMESH_TRY; + initData(); + + int NbNodes = IDsOfNodes.length(); + std::vector nodes (NbNodes); + for (int i = 0; i < NbNodes; i++) + nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]); + + const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes); + + // Update Python script + TPythonDump() <<"faceID = "<GetID() : 0; + + SMESH_CATCH( SMESH::throwCorbaException ); + return 0; +} + //============================================================================= /*! * Create volume, either linear and quadratic (this is determed @@ -1119,6 +1146,10 @@ CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes) n[8],n[9],n[10],n[11],n[12],n[13],n[14], n[15],n[16],n[17],n[18],n[19]); break; + case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7], + n[8],n[9],n[10],n[11],n[12],n[13],n[14], + n[15],n[16],n[17]); + break; case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7], n[8],n[9],n[10],n[11],n[12],n[13],n[14], n[15],n[16],n[17],n[18],n[19], @@ -1216,11 +1247,11 @@ CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_ar //============================================================================= // -// \brief Create 0D elements on all nodes of the given object except those -// nodes on which a 0D element already exists. +// \brief Create 0D elements on all nodes of the given object. // \param theObject object on whose nodes 0D elements will be created. // \param theGroupName optional name of a group to add 0D elements created // and/or found on nodes of \a theObject. +// \param DuplicateElements to add one more 0D element to a node or not. // \return an object (a new group or a temporary SMESH_IDSource) holding // ids of new and/or found 0D elements. // @@ -1228,7 +1259,8 @@ CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_ar SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject, - const char* theGroupName) + const char* theGroupName, + CORBA::Boolean theDuplicateElements) throw (SALOME::SALOME_Exception) { SMESH_TRY; @@ -1239,7 +1271,7 @@ SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObje TIDSortedElemSet elements, elems0D; if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1)) - getEditor().Create0DElementsOnAllNodes( elements, elems0D ); + getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements ); SMESH::long_array_var newElems = new SMESH::long_array; newElems->length( elems0D.size() ); @@ -1555,7 +1587,7 @@ CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfEleme SMESH_TRY; initData(); - for (int i = 0; i < IDsOfElements.length(); i++) + for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ ) { CORBA::Long index = IDsOfElements[i]; const SMDS_MeshElement * elem = getMeshDS()->FindElement(index); @@ -1984,7 +2016,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. @@ -2058,7 +2090,7 @@ void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems, */ //================================================================================ -void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr elems, +void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems, const SMESH::PointStruct & startHexPoint, const SMESH::DirStruct& facetToSplitNormal, CORBA::Short methodFlags, @@ -2110,6 +2142,44 @@ void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr el SMESH_CATCH( SMESH::throwCorbaException ); } +//================================================================================ +/*! + * \brief Split bi-quadratic elements into linear ones without creation of additional nodes: + * - bi-quadratic triangle will be split into 3 linear quadrangles; + * - bi-quadratic quadrangle will be split into 4 linear quadrangles; + * - tri-quadratic hexahedron will be split into 8 linear hexahedra. + * Quadratic elements of lower dimension adjacent to the split bi-quadratic element + * will be split in order to keep the mesh conformal. + * \param elems - elements to split + */ +//================================================================================ + +void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems) + throw (SALOME::SALOME_Exception) +{ + SMESH_TRY; + initData(); + + TIDSortedElemSet elemSet; + for ( size_t i = 0; i < theElems.length(); ++i ) + { + SMESH::SMESH_IDSource_ptr elems = theElems[i].in(); + SMESH::SMESH_Mesh_var mesh = elems->GetMesh(); + if ( mesh->GetId() != myMesh_i->GetId() ) + THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM); + + idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All ); + } + getEditor().SplitBiQuadraticIntoLinear( elemSet ); + + declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute() + + TPythonDump() << this << ".SplitBiQuadraticIntoLinear( " + << theElems << " )"; + + SMESH_CATCH( SMESH::throwCorbaException ); +} + //======================================================================= //function : Smooth //purpose : @@ -2206,7 +2276,7 @@ SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements, arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face); set fixedNodes; - for (int i = 0; i < IDsOfFixedNodes.length(); i++) { + for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) { CORBA::Long index = IDsOfFixedNodes[i]; const SMDS_MeshNode * node = aMesh->FindNode(index); if ( node ) @@ -2398,6 +2468,10 @@ SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes << TVar( theTolerance ) << ", " << theMakeGroups << " )"; } + else + { + getPreviewMesh()->Remove( SMDSAbs_Volume ); + } return aGroups ? aGroups : new SMESH::ListOfGroups; @@ -2415,6 +2489,7 @@ namespace MeshEditor_I bool myIsExtrusionByNormal; static int makeFlags( CORBA::Boolean MakeGroups, + CORBA::Boolean LinearVariation = false, CORBA::Boolean ByAverageNormal = false, CORBA::Boolean UseInputElemsOnly = false, CORBA::Long Flags = 0, @@ -2423,18 +2498,24 @@ 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 ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY; return Flags; } // standard params - ExtrusionParams(const SMESH::DirStruct & theDir, - CORBA::Long theNbOfSteps, - CORBA::Boolean theMakeGroups): + ExtrusionParams(const SMESH::DirStruct & theDir, + CORBA::Long theNbOfSteps, + const SMESH::double_array & theScaleFactors, + CORBA::Boolean theLinearVariation, + const SMESH::double_array & theBasePoint, + CORBA::Boolean theMakeGroups): ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x, theDir.PS.y, theDir.PS.z ), theNbOfSteps, - makeFlags( theMakeGroups )), + toList( theScaleFactors ), + TBasePoint( theBasePoint ), + makeFlags( theMakeGroups, theLinearVariation )), myIsExtrusionByNormal( false ) { } @@ -2448,7 +2529,9 @@ namespace MeshEditor_I theDir.PS.y, theDir.PS.z ), theNbOfSteps, - makeFlags( theMakeGroups, false, false, + std::list(), + 0, + makeFlags( theMakeGroups, false, false, false, theExtrFlags, false ), theSewTolerance ), myIsExtrusionByNormal( false ) @@ -2463,7 +2546,7 @@ namespace MeshEditor_I CORBA::Boolean theMakeGroups ): ::SMESH_MeshEditor::ExtrusParam ( theStepSize, theNbOfSteps, - makeFlags( theMakeGroups, + makeFlags( theMakeGroups, false, theByAverageNormal, theUseInputElemsOnly ), theDim), myIsExtrusionByNormal( true ) @@ -2474,6 +2557,32 @@ namespace MeshEditor_I { Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS); } + + private: + + static std::list toList( const SMESH::double_array & theScaleFactors ) + { + std::list scales; + for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i ) + scales.push_back( theScaleFactors[i] ); + return scales; + } + + // structure used to convert SMESH::double_array to gp_XYZ* + struct TBasePoint + { + gp_XYZ *pp, p; + TBasePoint( const SMESH::double_array & theBasePoint ) + { + pp = 0; + if ( theBasePoint.length() == 3 ) + { + p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] ); + pp = &p; + } + } + operator const gp_XYZ*() const { return pp; } + }; }; } @@ -2497,13 +2606,17 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode const SMESH::ListOfIDSources & theFaces, const SMESH::DirStruct & theStepVector, CORBA::Long theNbOfSteps, + const SMESH::double_array & theScaleFactors, + CORBA::Boolean theLinearVariation, + const SMESH::double_array & theBasePoint, CORBA::Boolean theToMakeGroups) throw (SALOME::SALOME_Exception) { SMESH_TRY; initData(); - ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups ); + ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, + theLinearVariation, theBasePoint, theToMakeGroups ); TIDSortedElemSet elemsNodes[2]; for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) { @@ -2516,14 +2629,14 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face ); TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2]; + SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face; if ( myIsPreviewMode ) { - SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face; // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node ) // previewType = SMDSAbs_Edge; SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume; - TPreviewMesh * tmpMesh = getPreviewMesh(); + TPreviewMesh * tmpMesh = getPreviewMesh( previewType ); tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid ); tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid ); workElements = & copyElements[0]; @@ -2551,6 +2664,10 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode << TVar( theNbOfSteps ) << ", " << theToMakeGroups << " )"; } + else + { + getPreviewMesh( previewType )->Remove( SMDSAbs_Volume ); + } return aGroups ? aGroups : new SMESH::ListOfGroups; @@ -2595,9 +2712,9 @@ SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects, idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType ); TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2]; + SMDSAbs_ElementType previewType = SMDSAbs_Face; if ( myIsPreviewMode ) { - SMDSAbs_ElementType previewType = SMDSAbs_Face; SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume; TPreviewMesh * tmpMesh = getPreviewMesh( previewType ); tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid ); @@ -2623,6 +2740,10 @@ SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects, << ", " << dim << " )"; } + else + { + getPreviewMesh( previewType )->Remove( SMDSAbs_Volume ); + } declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute() @@ -2675,6 +2796,10 @@ SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements << theSewTolerance << ", " << theMakeGroups << " )"; } + else + { + getPreviewMesh()->Remove( SMDSAbs_Volume ); + } return aGroups ? aGroups : new SMESH::ListOfGroups; @@ -2761,7 +2886,7 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the if ( !aMeshImp ) return aGroups._retn(); TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape ); aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape ); - if ( !aSubMesh || !aSubMesh->GetSubMeshDS() ) + if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ ) return aGroups._retn(); } @@ -2783,7 +2908,7 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face ); list angles; - for (int i = 0; i < theAngles.length(); i++) { + for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) { angles.push_back( theAngles[i] ); } @@ -2826,8 +2951,9 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the } if ( !myIsPreviewMode ) { - aPythonDump << "(" << aGroups << ", error) = " - << this << ".ExtrusionAlongPathObjects( " + if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = "; + else aPythonDump << "(_noGroups, error) = "; + aPythonDump << this << ".ExtrusionAlongPathObjects( " << theNodes << ", " << theEdges << ", " << theFaces << ", " @@ -2835,15 +2961,19 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the << thePathShape << ", " << theNodeStart << ", " << theHasAngles << ", " - << theAngles << ", " + << TVar( theAngles ) << ", " << theLinearVariation << ", " << theHasRefPoint << ", " << "SMESH.PointStruct( " - << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", " - << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", " - << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), " + << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", " + << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", " + << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), " << theMakeGroups << " )"; } + else + { + getPreviewMesh()->Remove( SMDSAbs_Volume ); + } return aGroups._retn(); @@ -2977,17 +3107,14 @@ SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements, ::SMESH_MeshEditor::PGroupIDs groupIds = getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh); - if ( theCopy && !myIsPreviewMode) + if ( !myIsPreviewMode ) { if ( theTargetMesh ) - { theTargetMesh->GetMeshDS()->Modified(); - } else - { declareMeshModified( /*isReComputeSafe=*/false ); - } } + return theMakeGroups ? getGroups(groupIds.get()) : 0; SMESH_CATCH( SMESH::throwCorbaException ); @@ -3244,16 +3371,12 @@ SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements, ::SMESH_MeshEditor::PGroupIDs groupIds = getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh); - if ( theCopy && !myIsPreviewMode ) + if ( !myIsPreviewMode ) { if ( theTargetMesh ) - { theTargetMesh->GetMeshDS()->Modified(); - } else - { declareMeshModified( /*isReComputeSafe=*/false ); - } } return theMakeGroups ? getGroups(groupIds.get()) : 0; @@ -3501,7 +3624,7 @@ SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements, ::SMESH_MeshEditor::PGroupIDs groupIds = getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh); - if ( theCopy && !myIsPreviewMode) + if ( !myIsPreviewMode) { if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified(); else declareMeshModified( /*isReComputeSafe=*/false ); @@ -3760,26 +3883,20 @@ SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject, (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1], (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2], }; - double tol = std::numeric_limits::max(); gp_Trsf aTrsf; -#if OCC_VERSION_LARGE > 0x06070100 - // fight against ortagonalization + // fight against orthogonalization // 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]) ); - aTrsf.SetTranslation( gp_Vec( thePoint.x * (1-S[0]), - thePoint.y * (1-S[1]), - thePoint.z * (1-S[2]))); - gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart(); + aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names + gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart(); + gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart(); + loc.SetCoord( thePoint.x * (1-S[0]), + thePoint.y * (1-S[1]), + thePoint.z * (1-S[2])); M.SetDiagonal( S[0], S[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; if ( myIsPreviewMode ) @@ -3799,7 +3916,7 @@ SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject, ::SMESH_MeshEditor::PGroupIDs groupIds = getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh); - if ( theCopy && !myIsPreviewMode ) + if ( !myIsPreviewMode ) { if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified(); else declareMeshModified( /*isReComputeSafe=*/false ); @@ -3876,7 +3993,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 ) @@ -3900,27 +4017,104 @@ 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 + */ +//================================================================================ -//======================================================================= -//function : FindCoincidentNodes -//purpose : -//======================================================================= - -void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tolerance, - SMESH::array_of_long_array_out GroupsOfNodes) +SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject, + CORBA::Double theValue, + CORBA::Boolean theCopyGroups, + 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 ); + theCopyGroups = 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, !myIsPreviewMode ); + + tgtMesh->GetMeshDS()->Modified(); + } + + if ( myIsPreviewMode ) + { + getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements )); + } + else + { + 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( " + << theValue << ", " + << theCopyGroups << ", " + << "'" << theMeshName<< "')"; + } + + return mesh_var._retn(); + + SMESH_CATCH( SMESH::throwCorbaException ); + return SMESH::SMESH_Mesh::_nil(); +} + +//======================================================================= +//function : findCoincidentNodes +//purpose : +//======================================================================= + +void SMESH_MeshEditor_i:: +findCoincidentNodes (TIDSortedNodeSet & Nodes, + CORBA::Double Tolerance, + SMESH::array_of_long_array_out GroupsOfNodes, + CORBA::Boolean SeparateCornersAndMedium) +{ ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes; - TIDSortedNodeSet nodes; // no input nodes - getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes ); + getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium ); GroupsOfNodes = new SMESH::array_of_long_array; GroupsOfNodes->length( aListOfListOfNodes.size() ); ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin(); - for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) { + for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) + { list< const SMDS_MeshNode* >& aListOfNodes = *llIt; list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();; SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ]; @@ -3928,8 +4122,28 @@ void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tol for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ ) aGroup[ j ] = (*lIt)->GetID(); } +} + +//======================================================================= +//function : FindCoincidentNodes +//purpose : +//======================================================================= + +void SMESH_MeshEditor_i:: +FindCoincidentNodes (CORBA::Double Tolerance, + SMESH::array_of_long_array_out GroupsOfNodes, + CORBA::Boolean SeparateCornersAndMedium) + throw (SALOME::SALOME_Exception) +{ + SMESH_TRY; + initData(); + + TIDSortedNodeSet nodes; // no input nodes + findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium ); + TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( " - << Tolerance << " )"; + << Tolerance << ", " + << SeparateCornersAndMedium << " )"; SMESH_CATCH( SMESH::throwCorbaException ); } @@ -3939,9 +4153,11 @@ void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tol //purpose : //======================================================================= -void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject, - CORBA::Double Tolerance, - SMESH::array_of_long_array_out GroupsOfNodes) +void SMESH_MeshEditor_i:: +FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject, + CORBA::Double Tolerance, + SMESH::array_of_long_array_out GroupsOfNodes, + CORBA::Boolean SeparateCornersAndMedium) throw (SALOME::SALOME_Exception) { SMESH_TRY; @@ -3950,25 +4166,12 @@ void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr TIDSortedNodeSet nodes; idSourceToNodeSet( theObject, getMeshDS(), nodes ); - ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes; - if(!nodes.empty()) - getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes ); + findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium ); - GroupsOfNodes = new SMESH::array_of_long_array; - GroupsOfNodes->length( aListOfListOfNodes.size() ); - ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin(); - for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) - { - list< const SMDS_MeshNode* >& aListOfNodes = *llIt; - list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();; - SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ]; - aGroup.length( aListOfNodes.size() ); - for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ ) - aGroup[ j ] = (*lIt)->GetID(); - } TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( " - <GetElements( theExceptSubMeshOrGroups[i], + SMESH::NODE ); + while ( nodeIt->more() ) + nodes.erase( cast2Node( nodeIt->next() )); } - ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes; - if(!nodes.empty()) - getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes ); + findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium ); - theGroupsOfNodes = new SMESH::array_of_long_array; - theGroupsOfNodes->length( aListOfListOfNodes.size() ); - ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin(); - for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) - { - list< const SMDS_MeshNode* >& aListOfNodes = *llIt; - list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();; - SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ]; - aGroup.length( aListOfNodes.size() ); - for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ ) - aGroup[ j ] = (*lIt)->GetID(); - } TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( " << theObject<<", " << theTolerance << ", " - << theExceptSubMeshOrGroups << " )"; + << theExceptSubMeshOrGroups << ", " + << theSeparateCornersAndMedium << " )"; SMESH_CATCH( SMESH::throwCorbaException ); } @@ -4030,7 +4220,9 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject, //purpose : //======================================================================= -void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes) +void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes, + const SMESH::ListOfIDSources& NodesToKeep, + CORBA::Boolean AvoidMakingHoles) throw (SALOME::SALOME_Exception) { SMESH_TRY; @@ -4040,18 +4232,32 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN TPythonDump aTPythonDump; aTPythonDump << this << ".MergeNodes(["; + + TIDSortedNodeSet setOfNodesToKeep; + 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() )); + } + ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes; - for (int i = 0; i < GroupsOfNodes.length(); i++) + for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ ) { const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ]; aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() ); list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back(); - for ( int j = 0; j < aNodeGroup.length(); j++ ) + for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ ) { CORBA::Long index = aNodeGroup[ j ]; - const SMDS_MeshNode * node = aMesh->FindNode(index); - if ( node ) - aListOfNodes.push_back( node ); + if ( const SMDS_MeshNode * node = aMesh->FindNode( index )) + { + if ( setOfNodesToKeep.count( node )) + aListOfNodes.push_front( node ); + else + aListOfNodes.push_back( node ); + } } if ( aListOfNodes.size() < 2 ) aListOfListOfNodes.pop_back(); @@ -4059,9 +4265,10 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN if ( i > 0 ) aTPythonDump << ", "; aTPythonDump << aNodeGroup; } - getEditor().MergeNodes( aListOfListOfNodes ); - aTPythonDump << "])"; + getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles ); + + aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")"; declareMeshModified( /*isReComputeSafe=*/false ); @@ -4127,11 +4334,11 @@ void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsO ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID; - for (int i = 0; i < GroupsOfElementsID.length(); i++) { + for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) { const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ]; aListOfListOfElementsID.push_back( list< int >() ); list< int >& aListOfElemsID = aListOfListOfElementsID.back(); - for ( int j = 0; j < anElemsIDGroup.length(); j++ ) { + for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) { CORBA::Long id = anElemsIDGroup[ j ]; aListOfElemsID.push_back( id ); } @@ -4356,7 +4563,7 @@ SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x, SMDSAbs_ElementType( type ), foundElems); res->length( foundElems.size() ); - for ( int i = 0; i < foundElems.size(); ++i ) + for ( size_t i = 0; i < foundElems.size(); ++i ) res[i] = foundElems[i]->GetID(); return res._retn(); @@ -4382,13 +4589,15 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID { SMESH_TRY; SMESH::long_array_var res = new SMESH::long_array; - - SMESH::array_of_ElementType_var types = elementIDs->GetTypes(); - if ( types->length() == 1 && // a part contains only nodes or 0D elements - ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) && - type != types[0] ) // but search of elements of dim > 0 - return res._retn(); + if ( type != SMESH::NODE ) + { + SMESH::array_of_ElementType_var types = elementIDs->GetTypes(); + if ( types->length() == 1 && // a part contains only nodes or 0D elements + ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) && + type != types[0] ) // but search of elements of dim > 0 + return res._retn(); + } if ( SMESH::DownCast( elementIDs )) // elementIDs is the whole mesh return FindElementsByPoint( x,y,z, type ); @@ -4402,7 +4611,8 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID SMESHDS_Mesh* meshDS = SMESH::DownCast( mesh )->GetImpl().GetMeshDS(); if ( !idSourceToSet( elementIDs, meshDS, elements, - SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true)) + ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ), + /*emptyIfIsMesh=*/true)) return res._retn(); typedef SMDS_SetIterator TIter; @@ -4417,7 +4627,7 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID SMDSAbs_ElementType( type ), foundElems); res->length( foundElems.size() ); - for ( int i = 0; i < foundElems.size(); ++i ) + for ( size_t i = 0; i < foundElems.size(); ++i ) res[i] = foundElems[i]->GetID(); return res._retn(); @@ -4448,6 +4658,150 @@ 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 : 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. +//======================================================================= + +void SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole) + 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; + + 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(); + } + + std::vector newFaces; + SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces ); + + if ( myIsPreviewMode ) + { + previewMesh->Clear(); + for ( size_t i = 0; i < newFaces.size(); ++i ) + previewMesh->Copy( newFaces[i] ); + } + else + { + getEditor().ClearLastCreated(); + SMESH_SequenceOfElemPtr& aSeq = + const_cast( getEditor().GetLastCreatedElems() ); + aSeq.swap( newFaces ); + + TPythonDump() << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))"; + } + + SMESH_CATCH( SMESH::throwCorbaException ); +} + //======================================================================= //function : convError //purpose : @@ -4468,10 +4822,230 @@ static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Se RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS ); RETCASE( SEW_BAD_SIDE1_NODES ); RETCASE( SEW_BAD_SIDE2_NODES ); + RETCASE( SEW_INTERNAL_ERROR ); } return SMESH::SMESH_MeshEditor::SEW_OK; } +//======================================================================= +/*! + * Returns groups of FreeBorder's coincident within the given tolerance. + * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent + * to free borders being compared is used. + */ +//======================================================================= + +SMESH::CoincidentFreeBorders* +SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance) +{ + SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders; + + SMESH_TRY; + + SMESH_MeshAlgos::CoincidentFreeBorders cfb; + SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb ); + + // copy free borders + aCFB->borders.length( cfb._borders.size() ); + for ( size_t i = 0; i < cfb._borders.size(); ++i ) + { + SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i]; + SMESH::FreeBorder& aBRD = aCFB->borders[i]; + aBRD.nodeIDs.length( nodes.size() ); + for ( size_t iN = 0; iN < nodes.size(); ++iN ) + aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID(); + } + + // copy coincident parts + aCFB->coincidentGroups.length( cfb._coincidentGroups.size() ); + for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i ) + { + SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i]; + SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i]; + aGRP.length( grp.size() ); + for ( size_t iP = 0; iP < grp.size(); ++iP ) + { + SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ]; + SMESH::FreeBorderPart& aPART = aGRP[ iP ]; + aPART.border = part._border; + aPART.node1 = part._node1; + aPART.node2 = part._node2; + aPART.nodeLast = part._nodeLast; + } + } + SMESH_CATCH( SMESH::doNothing ); + + TPythonDump() << "CoincidentFreeBorders = " + << this << ".FindCoincidentFreeBorders( " << tolerance << " )"; + + return aCFB._retn(); +} + +//======================================================================= +/*! + * Sew FreeBorder's of each group + */ +//======================================================================= + +CORBA::Short SMESH_MeshEditor_i:: +SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders, + CORBA::Boolean createPolygons, + CORBA::Boolean createPolyhedra) + throw (SALOME::SALOME_Exception) +{ + CORBA::Short nbSewed = 0; + + SMESH_MeshAlgos::TFreeBorderVec groups; + SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart + + // check the input and collect nodes + for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i ) + { + borderNodes.clear(); + const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ]; + for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP ) + { + const SMESH::FreeBorderPart& aPART = aGRP[ iP ]; + if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() ) + THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM); + + const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ]; + + if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() ) + THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM); + if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() ) + THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM); + if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() ) + THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM); + + // do not keep these nodes for further sewing as nodes can be removed by the sewing + const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]); + const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]); + const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]); + if ( !n1) + THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM); + if ( !n2 ) + THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM); + if ( !n3 ) + THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM); + + borderNodes.push_back( n1 ); + borderNodes.push_back( n2 ); + borderNodes.push_back( n3 ); + } + groups.push_back( borderNodes ); + } + + // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead; + // to get nodes that replace other nodes during merge we create 0D elements + // on each node and MergeNodes() will replace underlying nodes of 0D elements by + // new ones. + + vector< const SMDS_MeshElement* > tmp0Delems; + for ( size_t i = 0; i < groups.size(); ++i ) + { + SMESH_MeshAlgos::TFreeBorder& nodes = groups[i]; + for ( size_t iN = 0; iN < nodes.size(); ++iN ) + { + SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement); + if ( it0D->more() ) + tmp0Delems.push_back( it0D->next() ); + else + tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] )); + } + } + + // cout << endl << "INIT" << endl; + // for ( size_t i = 0; i < tmp0Delems.size(); ++i ) + // { + // cout << i << " "; + // if ( i % 3 == 0 ) cout << "^ "; + // tmp0Delems[i]->GetNode(0)->Print( cout ); + // } + + SMESH_TRY; + + ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK; + int i0D = 0; + for ( size_t i = 0; i < groups.size(); ++i ) + { + bool isBordToBord = true; + bool groupSewed = false; + SMESH_MeshAlgos::TFreeBorder& nodes = groups[i]; + for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 ) + { + const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 ); + const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 ); + const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 ); + + const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 ); + const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 ); + const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 ); + + if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 ) + continue; + + // TIDSortedElemSet emptySet, avoidSet; + // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet)) + // { + // cout << "WRONG 2nd 1" << endl; + // n0->Print( cout ); + // n1->Print( cout ); + // } + // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet)) + // { + // cout << "WRONG 2nd 2" << endl; + // n3->Print( cout ); + // n4->Print( cout ); + // } + + if ( !isBordToBord ) + { + n1 = n2; // at border-to-side sewing only last side node (n1) is needed + n2 = 0; // and n2 is not used + } + // 1st border moves to 2nd + res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st + n0 ,n1 ,n2 ,// 2nd + /*2ndIsFreeBorder=*/ isBordToBord, + createPolygons, createPolyhedra); + groupSewed = ( res == ok ); + + isBordToBord = false; + // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl; + // for ( size_t t = 0; t < tmp0Delems.size(); ++t ) + // { + // cout << t << " "; + // if ( t % 3 == 0 ) cout << "^ "; + // tmp0Delems[t]->GetNode(0)->Print( cout ); + // } + } + i0D += nodes.size(); + nbSewed += groupSewed; + } + + TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( " + << freeBorders << ", " + << createPolygons << ", " + << createPolyhedra << " )"; + + SMESH_CATCH( SMESH::doNothing ); + + declareMeshModified( /*isReComputeSafe=*/false ); + + // remove tmp 0D elements + SMESH_TRY; + set< const SMDS_MeshElement* > removed0D; + for ( size_t i = 0; i < tmp0Delems.size(); ++i ) + { + if ( removed0D.insert( tmp0Delems[i] ).second ) + getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false ); + } + SMESH_CATCH( SMESH::throwCorbaException ); + + return nbSewed; +} + //======================================================================= //function : SewFreeBorders //purpose : @@ -4521,14 +5095,14 @@ SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1, SMESH::SMESH_MeshEditor::Sew_Error error = convError( getEditor().SewFreeBorder (aBorderFirstNode, - aBorderSecondNode, - aBorderLastNode, - aSide2FirstNode, - aSide2SecondNode, - aSide2ThirdNode, - true, - CreatePolygons, - CreatePolyedrs) ); + aBorderSecondNode, + aBorderLastNode, + aSide2FirstNode, + aSide2SecondNode, + aSide2ThirdNode, + true, + CreatePolygons, + CreatePolyedrs) ); declareMeshModified( /*isReComputeSafe=*/false ); @@ -4581,13 +5155,13 @@ SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1, SMESH::SMESH_MeshEditor::Sew_Error error = convError( getEditor().SewFreeBorder (aBorderFirstNode, - aBorderSecondNode, - aBorderLastNode, - aSide2FirstNode, - aSide2SecondNode, - aSide2ThirdNode, - true, - false, false) ); + aBorderSecondNode, + aBorderLastNode, + aSide2FirstNode, + aSide2SecondNode, + aSide2ThirdNode, + true, + false, false) ); declareMeshModified( /*isReComputeSafe=*/false ); return error; @@ -4643,14 +5217,14 @@ SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder, SMESH::SMESH_MeshEditor::Sew_Error error = convError( getEditor().SewFreeBorder (aBorderFirstNode, - aBorderSecondNode, - aBorderLastNode, - aSide2FirstNode, - aSide2SecondNode, - aSide2ThirdNode, - false, - CreatePolygons, - CreatePolyedrs) ); + aBorderSecondNode, + aBorderLastNode, + aSide2FirstNode, + aSide2SecondNode, + aSide2ThirdNode, + false, + CreatePolygons, + CreatePolyedrs) ); declareMeshModified( /*isReComputeSafe=*/false ); return error; @@ -4750,7 +5324,6 @@ CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide, TPythonDump() << "isDone = " << this << ".ChangeElemNodes( " << ide << ", " << newIDs << " )"; - MESSAGE("ChangeElementNodes"); bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 ); declareMeshModified( /*isReComputeSafe=*/ !res ); @@ -4773,6 +5346,8 @@ void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d throw (SALOME::SALOME_Exception) { SMESH_TRY; + initData(); + TIDSortedElemSet elems; bool elemsOK; if ( !( elemsOK = CORBA::is_nil( theObject ))) @@ -4802,10 +5377,16 @@ void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic() throw (SALOME::SALOME_Exception) { + SMESH_TRY; + initData(); + CORBA::Boolean isDone = getEditor().ConvertFromQuadratic(); TPythonDump() << this << ".ConvertFromQuadratic()"; declareMeshModified( /*isReComputeSafe=*/!isDone ); return isDone; + + SMESH_CATCH( SMESH::throwCorbaException ); + return false; } //======================================================================= @@ -4858,6 +5439,7 @@ void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr th throw (SALOME::SALOME_Exception) { SMESH_TRY; + initData(); TPythonDump pyDump; @@ -4922,10 +5504,10 @@ void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPytho */ //================================================================================ -string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix) +std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix) { SMESH::ListOfGroups_var groups = myMesh_i->GetGroups(); - set groupNames; + set groupNames; // Get existing group names for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) { @@ -4938,7 +5520,7 @@ string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix) } // Find new name - string name = thePrefix; + std::string name = thePrefix; int index = 0; while (!groupNames.insert(name).second) @@ -4977,7 +5559,7 @@ bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource, { if ( error ) *error = IDSource_OK; - if ( CORBA::is_nil( theIDSource ) ) + if ( CORBA::is_nil( theIDSource )) { if ( error ) *error = IDSource_INVALID; return false; @@ -5027,7 +5609,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 == "". @@ -5052,11 +5634,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 ) @@ -5076,8 +5658,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] ); } } } @@ -5189,10 +5771,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 @@ -5246,8 +5825,8 @@ SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes, // Create group with newly created nodes SMESH::long_array_var anIds = GetLastCreatedNodes(); if (anIds->length() > 0) { - string anUnindexedName (theNodes->GetName()); - string aNewName = generateGroupName(anUnindexedName + "_double"); + std::string anUnindexedName (theNodes->GetName()); + std::string aNewName = generateGroupName(anUnindexedName + "_double"); aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str()); aNewGroup->Add(anIds); pyDump << aNewGroup << " = "; @@ -5345,8 +5924,8 @@ SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes, // Create group with newly created nodes SMESH::long_array_var anIds = GetLastCreatedNodes(); if (anIds->length() > 0) { - string anUnindexedName (theNodes[0]->GetName()); - string aNewName = generateGroupName(anUnindexedName + "_double"); + std::string anUnindexedName (theNodes[0]->GetName()); + std::string aNewName = generateGroupName(anUnindexedName + "_double"); aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str()); aNewGroup->Add(anIds); pyDump << aNewGroup << " = "; @@ -5570,15 +6149,15 @@ SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems, { // Create group with newly created elements CORBA::String_var elemGroupName = theElems->GetName(); - string aNewName = generateGroupName( 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()); @@ -5802,15 +6381,15 @@ SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems { // Create group with newly created elements CORBA::String_var elemGroupName = theElems[0]->GetName(); - string aNewName = generateGroupName( 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()); @@ -5904,14 +6483,10 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl throw (SALOME::SALOME_Exception) { SMESH_TRY; - MESSAGE("AffectedElemGroupsInRegion"); 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(); @@ -5919,76 +6494,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(); - MESSAGE("lg="<< lg); 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(); @@ -6000,7 +6574,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 */ //================================================================================ @@ -6172,7 +6746,7 @@ void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius, theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() ); vector nodesCoords; - for (int i = 0; i < theNodesCoords.length(); i++) + for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++) { nodesCoords.push_back( theNodesCoords[i] ); } @@ -6282,7 +6856,7 @@ SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource, else pyDump << mesh_var << ", "; if ( group_var->_is_nil() ) - pyDump << "_NoneGroup = "; // assignment to None is forbiden + pyDump << "_NoneGroup = "; // assignment to None is forbidden else pyDump << group_var << " = "; pyDump << this << ".MakeBoundaryMesh( " @@ -6333,12 +6907,12 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim, THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM); // separate groups belonging to this and other mesh - SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources; + SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources; SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources; - groupsOfThisMesh->length( groups.length() ); + groupsOfThisMesh ->length( groups.length() ); groupsOfOtherMesh->length( groups.length() ); int nbGroups = 0, nbGroupsOfOtherMesh = 0; - for ( int i = 0; i < groups.length(); ++i ) + for ( CORBA::ULong i = 0; i < groups.length(); ++i ) { SMESH::SMESH_Mesh_var m = groups[i]->GetMesh(); if ( myMesh_i != SMESH::DownCast( m )) @@ -6346,7 +6920,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim, else groupsOfThisMesh[ nbGroups++ ] = groups[i]; if ( SMESH::DownCast( groups[i] )) - THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM); + THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM); } groupsOfThisMesh->length( nbGroups ); groupsOfOtherMesh->length( nbGroupsOfOtherMesh ); @@ -6440,7 +7014,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim, else pyDump << mesh_var << ", "; if ( group_var->_is_nil() ) - pyDump << "_NoneGroup = "; // assignment to None is forbiden + pyDump << "_NoneGroup = "; // assignment to None is forbidden else pyDump << group_var << " = "; pyDump << this << ".MakeBoundaryElements( " @@ -6457,3 +7031,130 @@ 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_MeshEditor::TListOfPolySegments segments( theSegments.length() ); + for ( CORBA::ULong i = 0; i < theSegments.length(); ++i ) + { + SMESH::PolySegment& segIn = theSegments[ i ]; + ::SMESH_MeshEditor::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.myVector.SetCoord( segIn.vector.PS.x, + segIn.vector.PS.y, + segIn.vector.PS.z ); + if ( !segOut.myNode1[0] ) + THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node1ID1, + SALOME::BAD_PARAM ); + if ( !segOut.myNode1[1] ) + THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node2ID1, + SALOME::BAD_PARAM ); + } + + // 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 + getEditor().MakePolyLine( segments, groupDS, theElementSearcher ); + + // return vectors + if ( myIsPreviewMode ) + { + for ( CORBA::ULong i = 0; i < theSegments.length(); ++i ) + { + SMESH::PolySegment& segOut = theSegments[ i ]; + ::SMESH_MeshEditor::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; +}