1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
46 #include "SMDS_SetIterator.hxx"
47 #include "SMDS_VolumeTool.hxx"
48 #include "SMESHDS_Group.hxx"
49 #include "SMESHDS_GroupOnGeom.hxx"
50 #include "SMESH_ControlsDef.hxx"
51 #include "SMESH_Filter_i.hxx"
52 #include "SMESH_Gen_i.hxx"
53 #include "SMESH_Group.hxx"
54 #include "SMESH_Group_i.hxx"
55 #include "SMESH_MeshAlgos.hxx"
56 #include "SMESH_MeshPartDS.hxx"
57 #include "SMESH_MesherHelper.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMeshEventListener.hxx"
60 #include "SMESH_subMesh_i.hxx"
62 #include <utilities.h>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <Utils_CorbaException.hxx>
65 #include <SALOMEDS_wrap.hxx>
66 #include <SALOME_GenericObj_i.hh>
67 #include <Basics_OCCTVersion.hxx>
69 #include <BRepAdaptor_Surface.hxx>
70 #include <BRep_Tool.hxx>
71 #include <TopExp_Explorer.hxx>
73 #include <TopoDS_Edge.hxx>
74 #include <TopoDS_Face.hxx>
79 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
83 #include <Standard_Failure.hxx>
86 #include <Standard_ErrorHandler.hxx>
92 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
94 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
97 using SMESH::TPythonDump;
100 namespace MeshEditor_I {
102 //=============================================================================
104 * \brief Mesh to apply modifications for preview purposes
106 //=============================================================================
108 struct TPreviewMesh: public SMESH_Mesh
110 SMDSAbs_ElementType myPreviewType; // type to show
112 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
113 _isShapeToMesh = (_id =_studyId = 0);
114 _myMeshDS = new SMESHDS_Mesh( _id, true );
115 myPreviewType = previewElements;
117 //!< Copy a set of elements
118 void Copy(const TIDSortedElemSet & theElements,
119 TIDSortedElemSet& theCopyElements,
120 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
121 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
123 // loop on theIDsOfElements
124 TIDSortedElemSet::const_iterator eIt = theElements.begin();
125 for ( ; eIt != theElements.end(); ++eIt )
127 const SMDS_MeshElement* anElem = *eIt;
128 if ( !anElem ) continue;
129 SMDSAbs_ElementType type = anElem->GetType();
130 if ( type == theAvoidType ||
131 ( theSelectType != SMDSAbs_All && type != theSelectType ))
133 const SMDS_MeshElement* anElemCopy;
134 if ( type == SMDSAbs_Node)
135 anElemCopy = Copy( cast2Node(anElem) );
137 anElemCopy = Copy( anElem );
139 theCopyElements.insert( theCopyElements.end(), anElemCopy );
143 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
145 // copy element nodes
146 int anElemNbNodes = anElem->NbNodes();
147 vector< int > anElemNodesID( anElemNbNodes ) ;
148 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
149 for ( int i = 0; itElemNodes->more(); i++)
151 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
153 anElemNodesID[i] = anElemNode->GetID();
156 // creates a corresponding element on copied nodes
157 SMDS_MeshElement* anElemCopy = 0;
158 if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume )
160 const SMDS_VtkVolume* ph =
161 dynamic_cast<const SMDS_VtkVolume*> (anElem);
163 anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID
164 (anElemNodesID, ph->GetQuantities(),anElem->GetID());
167 anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID,
174 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
176 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
177 anElemNode->GetID());
181 GetMeshDS()->ClearMesh();
183 void Remove( SMDSAbs_ElementType type )
185 SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator( type );
186 while ( eIt->more() )
187 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
189 };// struct TPreviewMesh
191 static SMESH_NodeSearcher * theNodeSearcher = 0;
192 static SMESH_ElementSearcher * theElementSearcher = 0;
194 //=============================================================================
196 * \brief Deleter of theNodeSearcher at any compute event occured
198 //=============================================================================
200 struct TSearchersDeleter : public SMESH_subMeshEventListener
203 string myMeshPartIOR;
205 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
206 "SMESH_MeshEditor_i::TSearchersDeleter"),
208 //!< Delete theNodeSearcher
211 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
212 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
214 typedef map < int, SMESH_subMesh * > TDependsOnMap;
215 //!< The meshod called by submesh: do my main job
216 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
217 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
219 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
221 Unset( sm->GetFather() );
224 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
225 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
227 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
234 myMeshPartIOR = meshPartIOR;
235 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
236 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
237 while ( smIt->more() )
240 sm->SetEventListener( this, 0, sm );
244 //!< delete self from all submeshes
245 void Unset(SMESH_Mesh* mesh)
247 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
248 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
249 while ( smIt->more() )
250 smIt->next()->DeleteEventListener( this );
255 } theSearchersDeleter;
257 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
259 TCollection_AsciiString typeStr;
260 switch ( theMirrorType ) {
261 case SMESH::SMESH_MeshEditor::POINT:
262 typeStr = "SMESH.SMESH_MeshEditor.POINT";
264 case SMESH::SMESH_MeshEditor::AXIS:
265 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
268 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
272 //================================================================================
274 * \brief function for conversion of long_array to TIDSortedElemSet
275 * \param IDs - array of IDs
276 * \param aMesh - mesh
277 * \param aMap - collection to fill
278 * \param aType - element type
280 //================================================================================
282 void arrayToSet(const SMESH::long_array & IDs,
283 const SMESHDS_Mesh* aMesh,
284 TIDSortedElemSet& aMap,
285 const SMDSAbs_ElementType aType = SMDSAbs_All,
286 SMDS_MeshElement::Filter* aFilter = NULL)
288 SMDS_MeshElement::NonNullFilter filter1;
289 SMDS_MeshElement::TypeFilter filter2( aType );
291 if ( aFilter == NULL )
292 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
294 SMDS_MeshElement::Filter & filter = *aFilter;
296 if ( aType == SMDSAbs_Node )
297 for (int i=0; i<IDs.length(); i++) {
298 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
300 aMap.insert( aMap.end(), elem );
303 for (int i=0; i<IDs.length(); i++) {
304 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
306 aMap.insert( aMap.end(), elem );
310 //================================================================================
312 * \brief Retrieve nodes from SMESH_IDSource
314 //================================================================================
316 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
317 const SMESHDS_Mesh* theMeshDS,
318 TIDSortedNodeSet& theNodeSet)
321 if ( CORBA::is_nil( theObject ) )
323 SMESH::array_of_ElementType_var types = theObject->GetTypes();
324 SMESH::long_array_var aElementsId = theObject->GetIDs();
325 if ( types->length() == 1 && types[0] == SMESH::NODE)
327 for(int i = 0; i < aElementsId->length(); i++)
328 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
329 theNodeSet.insert( theNodeSet.end(), n);
331 else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
333 SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
334 while ( nIt->more( ))
335 if( const SMDS_MeshElement * elem = nIt->next() )
336 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
340 for(int i = 0; i < aElementsId->length(); i++)
341 if( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
342 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
346 //================================================================================
348 * \brief Returns elements connected to the given elements
350 //================================================================================
352 void getElementsAround(const TIDSortedElemSet& theElements,
353 const SMESHDS_Mesh* theMeshDS,
354 TIDSortedElemSet& theElementsAround)
356 if ( theElements.empty() ) return;
358 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
359 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
361 theMeshDS->GetMeshInfo().NbElements( elemType ) == theElements.size() )
362 return; // all the elements are in theElements
365 elemType = SMDSAbs_All;
367 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
369 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
370 for ( ; elemIt != theElements.end(); ++elemIt )
372 const SMDS_MeshElement* e = *elemIt;
373 int i = e->NbCornerNodes();
376 const SMDS_MeshNode* n = e->GetNode( i );
377 if ( !isNodeChecked[ n->GetID() ])
379 isNodeChecked[ n->GetID() ] = true;
380 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
381 while ( invIt->more() )
383 const SMDS_MeshElement* elemAround = invIt->next();
384 if ( !theElements.count( elemAround ))
385 theElementsAround.insert( elemAround );
392 //================================================================================
394 * \brief Return a string used to detect change of mesh part on which theElementSearcher
395 * is going to be used
397 //================================================================================
399 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
401 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
402 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
403 // take into account passible group modification
404 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
405 partIOR += SMESH_Comment( type );
409 } // namespace MeshEditor_I
411 using namespace MeshEditor_I;
413 //=============================================================================
417 //=============================================================================
419 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
421 myMesh( &theMesh->GetImpl() ),
423 myIsPreviewMode ( isPreview ),
429 //================================================================================
433 //================================================================================
435 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
437 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
438 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
439 poa->deactivate_object(anObjectId.in());
441 //deleteAuxIDSources();
442 delete myPreviewMesh; myPreviewMesh = 0;
443 delete myPreviewEditor; myPreviewEditor = 0;
446 //================================================================================
448 * \brief Returns the mesh
450 //================================================================================
452 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
454 return myMesh_i->_this();
457 //================================================================================
459 * \brief Clear members
461 //================================================================================
463 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
465 if ( myIsPreviewMode ) {
466 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
469 if ( deleteSearchers )
470 TSearchersDeleter::Delete();
472 getEditor().GetError().reset();
473 getEditor().ClearLastCreated();
476 //================================================================================
478 * \brief Increment mesh modif time and optionally record that the performed
479 * modification may influence futher mesh re-compute.
480 * \param [in] isReComputeSafe - true if the modification does not influence
481 * futher mesh re-compute
483 //================================================================================
485 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
487 myMesh->GetMeshDS()->Modified();
488 if ( !isReComputeSafe )
489 myMesh->SetIsModified( true );
492 //================================================================================
494 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
495 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
497 //================================================================================
499 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
501 if ( myIsPreviewMode && !myPreviewEditor ) {
502 if ( !myPreviewMesh ) getPreviewMesh();
503 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
505 return myIsPreviewMode ? *myPreviewEditor : myEditor;
508 //================================================================================
510 * \brief Initialize and return myPreviewMesh
511 * \param previewElements - type of elements to show in preview
513 * WARNING: call it once par a method!
515 //================================================================================
517 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
519 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
521 delete myPreviewEditor;
523 delete myPreviewMesh;
524 myPreviewMesh = new TPreviewMesh( previewElements );
526 myPreviewMesh->Clear();
527 return myPreviewMesh;
530 //================================================================================
532 * Return data of mesh edition preview
534 //================================================================================
536 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
537 throw (SALOME::SALOME_Exception)
540 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
542 if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
544 list<int> aNodesConnectivity;
545 typedef map<int, int> TNodesMap;
548 SMESHDS_Mesh* aMeshDS;
549 std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
551 aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
552 aMeshDS = aMeshPartDS.get();
555 aMeshDS = getEditor().GetMeshDS();
557 myPreviewData = new SMESH::MeshPreviewStruct();
558 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
561 SMDSAbs_ElementType previewType = SMDSAbs_All;
563 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
564 previewType = aPreviewMesh->myPreviewType;
565 switch ( previewType ) {
566 case SMDSAbs_Edge : break;
567 case SMDSAbs_Face : break;
568 case SMDSAbs_Volume: break;
570 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
574 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
576 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
578 while ( itMeshElems->more() ) {
579 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
580 SMDS_NodeIteratorPtr itElemNodes = aMeshElem->nodeIterator();
581 while ( itElemNodes->more() ) {
582 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
583 int aNodeID = aMeshNode->GetID();
584 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
585 if ( anIter == nodesMap.end() ) {
586 // filling the nodes coordinates
587 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
588 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
589 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
590 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
593 aNodesConnectivity.push_back(anIter->second);
596 // filling the elements types
597 SMDSAbs_ElementType aType = aMeshElem->GetType();
598 bool isPoly = aMeshElem->IsPoly();
599 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
600 myPreviewData->elementTypes[i].isPoly = isPoly;
601 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
604 myPreviewData->nodesXYZ.length( j );
606 // filling the elements connectivities
607 list<int>::iterator aConnIter = aNodesConnectivity.begin();
608 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
609 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
610 myPreviewData->elementConnectivities[i] = *aConnIter;
612 return myPreviewData._retn();
614 SMESH_CATCH( SMESH::throwCorbaException );
618 //================================================================================
620 * \brief Returns list of it's IDs of created nodes
621 * \retval SMESH::long_array* - list of node ID
623 //================================================================================
625 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
626 throw (SALOME::SALOME_Exception)
629 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
631 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
632 myLastCreatedNodes->length( aSeq.Length() );
633 for (int i = 1; i <= aSeq.Length(); i++)
634 myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID();
636 return myLastCreatedNodes._retn();
637 SMESH_CATCH( SMESH::throwCorbaException );
641 //================================================================================
643 * \brief Returns list of it's IDs of created elements
644 * \retval SMESH::long_array* - list of elements' ID
646 //================================================================================
648 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
649 throw (SALOME::SALOME_Exception)
652 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
654 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
655 myLastCreatedElems->length( aSeq.Length() );
656 for ( int i = 1; i <= aSeq.Length(); i++ )
657 myLastCreatedElems[i-1] = aSeq.Value(i)->GetID();
659 return myLastCreatedElems._retn();
660 SMESH_CATCH( SMESH::throwCorbaException );
664 //=======================================================================
665 //function : ClearLastCreated
666 //purpose : Clears sequences of last created elements and nodes
667 //=======================================================================
669 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
672 getEditor().ClearLastCreated();
673 SMESH_CATCH( SMESH::throwCorbaException );
676 //=======================================================================
678 * Returns description of an error/warning occured during the last operation
679 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
681 //=======================================================================
683 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
684 throw (SALOME::SALOME_Exception)
687 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
688 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
689 if ( errIn && !errIn->IsOK() )
691 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
692 errOut->comment = errIn->myComment.c_str();
693 errOut->subShapeID = -1;
694 errOut->hasBadMesh = !errIn->myBadElements.empty();
699 errOut->subShapeID = -1;
700 errOut->hasBadMesh = false;
703 return errOut._retn();
704 SMESH_CATCH( SMESH::throwCorbaException );
708 //=======================================================================
709 //function : MakeIDSource
710 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
711 // Call UnRegister() as you fininsh using it!!
712 //=======================================================================
714 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
715 public virtual SALOME::GenericObj_i
717 SMESH::long_array _ids;
718 SMESH::ElementType _type;
719 SMESH::SMESH_Mesh_ptr _mesh;
720 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
721 SMESH::long_array* GetMeshInfo() { return 0; }
722 SMESH::long_array* GetNbElementsByType()
724 SMESH::long_array_var aRes = new SMESH::long_array();
725 aRes->length(SMESH::NB_ELEMENT_TYPES);
726 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
727 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
730 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
731 bool IsMeshInfoCorrect() { return true; }
732 SMESH::array_of_ElementType* GetTypes()
734 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
735 if ( _ids.length() > 0 ) {
739 return types._retn();
741 SALOMEDS::TMPFile* GetVtkUgStream()
743 SALOMEDS::TMPFile_var SeqFile;
744 return SeqFile._retn();
748 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
749 SMESH::ElementType type)
751 _IDSource* idSrc = new _IDSource;
752 idSrc->_mesh = myMesh_i->_this();
755 if ( type == SMESH::ALL && ids.length() > 0 )
756 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
758 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
760 return anIDSourceVar._retn();
763 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
765 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
768 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
771 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
773 nbIds = (int) tmpIdSource->_ids.length();
774 return & tmpIdSource->_ids[0];
780 // void SMESH_MeshEditor_i::deleteAuxIDSources()
782 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
783 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
785 // myAuxIDSources.clear();
788 //=============================================================================
792 //=============================================================================
795 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
796 throw (SALOME::SALOME_Exception)
803 for (int i = 0; i < IDsOfElements.length(); i++)
804 IdList.push_back( IDsOfElements[i] );
806 // Update Python script
807 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
810 bool ret = getEditor().Remove( IdList, false );
812 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
815 SMESH_CATCH( SMESH::throwCorbaException );
819 //=============================================================================
823 //=============================================================================
825 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
826 throw (SALOME::SALOME_Exception)
832 for (int i = 0; i < IDsOfNodes.length(); i++)
833 IdList.push_back( IDsOfNodes[i] );
835 // Update Python script
836 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
838 bool ret = getEditor().Remove( IdList, true );
840 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
843 SMESH_CATCH( SMESH::throwCorbaException );
847 //=============================================================================
851 //=============================================================================
853 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
854 throw (SALOME::SALOME_Exception)
859 // Update Python script
860 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
862 // Create filter to find all orphan nodes
863 SMESH::Controls::Filter::TIdSequence seq;
864 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
865 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
867 // remove orphan nodes (if there are any)
869 for ( int i = 0; i < seq.size(); i++ )
870 IdList.push_back( seq[i] );
872 int nbNodesBefore = myMesh->NbNodes();
873 getEditor().Remove( IdList, true );
874 int nbNodesAfter = myMesh->NbNodes();
876 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
877 return nbNodesBefore - nbNodesAfter;
879 SMESH_CATCH( SMESH::throwCorbaException );
883 //=============================================================================
887 //=============================================================================
889 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
890 throw (SALOME::SALOME_Exception)
895 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
897 // Update Python script
898 TPythonDump() << "nodeID = " << this << ".AddNode( "
899 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
901 declareMeshModified( /*isReComputeSafe=*/false );
904 SMESH_CATCH( SMESH::throwCorbaException );
908 //=============================================================================
910 * Create 0D element on the given node.
912 //=============================================================================
914 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
915 throw (SALOME::SALOME_Exception)
920 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
921 SMDS_MeshElement* elem = getMeshDS()->Add0DElement(aNode);
923 // Update Python script
924 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
926 declareMeshModified( /*isReComputeSafe=*/false );
928 return elem ? elem->GetID() : 0;
930 SMESH_CATCH( SMESH::throwCorbaException );
934 //=============================================================================
936 * Create a ball element on the given node.
938 //=============================================================================
940 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
941 throw (SALOME::SALOME_Exception)
946 if ( diameter < std::numeric_limits<double>::min() )
947 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
949 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
950 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
952 // Update Python script
953 TPythonDump() << "ballElem = "
954 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
956 declareMeshModified( /*isReComputeSafe=*/false );
957 return elem ? elem->GetID() : 0;
959 SMESH_CATCH( SMESH::throwCorbaException );
963 //=============================================================================
965 * Create an edge, either linear and quadratic (this is determed
966 * by number of given nodes, two or three)
968 //=============================================================================
970 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
971 throw (SALOME::SALOME_Exception)
976 int NbNodes = IDsOfNodes.length();
977 SMDS_MeshElement* elem = 0;
980 CORBA::Long index1 = IDsOfNodes[0];
981 CORBA::Long index2 = IDsOfNodes[1];
982 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
983 getMeshDS()->FindNode(index2));
985 // Update Python script
986 TPythonDump() << "edge = " << this << ".AddEdge([ "
987 << index1 << ", " << index2 <<" ])";
990 CORBA::Long n1 = IDsOfNodes[0];
991 CORBA::Long n2 = IDsOfNodes[1];
992 CORBA::Long n12 = IDsOfNodes[2];
993 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
994 getMeshDS()->FindNode(n2),
995 getMeshDS()->FindNode(n12));
996 // Update Python script
997 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
998 <<n1<<", "<<n2<<", "<<n12<<" ])";
1001 declareMeshModified( /*isReComputeSafe=*/false );
1002 return elem ? elem->GetID() : 0;
1004 SMESH_CATCH( SMESH::throwCorbaException );
1008 //=============================================================================
1012 //=============================================================================
1014 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1015 throw (SALOME::SALOME_Exception)
1020 int NbNodes = IDsOfNodes.length();
1026 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1027 for (int i = 0; i < NbNodes; i++)
1028 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1030 SMDS_MeshElement* elem = 0;
1032 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1033 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1034 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1035 nodes[4], nodes[5]); break;
1036 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1037 nodes[4], nodes[5], nodes[6]); break;
1038 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1039 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1040 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1041 nodes[4], nodes[5], nodes[6], nodes[7],
1043 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1046 // Update Python script
1047 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1049 declareMeshModified( /*isReComputeSafe=*/false );
1051 return elem ? elem->GetID() : 0;
1053 SMESH_CATCH( SMESH::throwCorbaException );
1057 //=============================================================================
1061 //=============================================================================
1062 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1063 throw (SALOME::SALOME_Exception)
1068 int NbNodes = IDsOfNodes.length();
1069 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1070 for (int i = 0; i < NbNodes; i++)
1071 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1073 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1075 // Update Python script
1076 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1078 declareMeshModified( /*isReComputeSafe=*/false );
1079 return elem ? elem->GetID() : 0;
1081 SMESH_CATCH( SMESH::throwCorbaException );
1085 //=============================================================================
1087 * Create volume, either linear and quadratic (this is determed
1088 * by number of given nodes)
1090 //=============================================================================
1092 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1093 throw (SALOME::SALOME_Exception)
1098 int NbNodes = IDsOfNodes.length();
1099 vector< const SMDS_MeshNode*> n(NbNodes);
1100 for(int i=0;i<NbNodes;i++)
1101 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1103 SMDS_MeshElement* elem = 0;
1106 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1107 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1108 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1109 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1110 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1111 n[6],n[7],n[8],n[9]);
1113 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1114 n[6],n[7],n[8],n[9],n[10],n[11]);
1116 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1117 n[7],n[8],n[9],n[10],n[11],n[12]);
1119 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1120 n[9],n[10],n[11],n[12],n[13],n[14]);
1122 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1123 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1124 n[15],n[16],n[17],n[18],n[19]);
1126 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1127 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1128 n[15],n[16],n[17],n[18],n[19],
1129 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1133 // Update Python script
1134 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1136 declareMeshModified( /*isReComputeSafe=*/false );
1137 return elem ? elem->GetID() : 0;
1139 SMESH_CATCH( SMESH::throwCorbaException );
1143 //=============================================================================
1145 * AddPolyhedralVolume
1147 //=============================================================================
1148 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1149 const SMESH::long_array & Quantities)
1150 throw (SALOME::SALOME_Exception)
1155 int NbNodes = IDsOfNodes.length();
1156 std::vector<const SMDS_MeshNode*> n (NbNodes);
1157 for (int i = 0; i < NbNodes; i++)
1159 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1160 if (!aNode) return 0;
1164 int NbFaces = Quantities.length();
1165 std::vector<int> q (NbFaces);
1166 for (int j = 0; j < NbFaces; j++)
1167 q[j] = Quantities[j];
1169 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1171 // Update Python script
1172 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1173 << IDsOfNodes << ", " << Quantities << " )";
1175 declareMeshModified( /*isReComputeSafe=*/false );
1176 return elem ? elem->GetID() : 0;
1178 SMESH_CATCH( SMESH::throwCorbaException );
1182 //=============================================================================
1184 * AddPolyhedralVolumeByFaces
1186 //=============================================================================
1188 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1189 throw (SALOME::SALOME_Exception)
1194 int NbFaces = IdsOfFaces.length();
1195 std::vector<const SMDS_MeshNode*> poly_nodes;
1196 std::vector<int> quantities (NbFaces);
1198 for (int i = 0; i < NbFaces; i++) {
1199 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1200 quantities[i] = aFace->NbNodes();
1202 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1203 while (It->more()) {
1204 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1208 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1210 // Update Python script
1211 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1212 << IdsOfFaces << " )";
1214 declareMeshModified( /*isReComputeSafe=*/false );
1215 return elem ? elem->GetID() : 0;
1217 SMESH_CATCH( SMESH::throwCorbaException );
1221 //=============================================================================
1223 // \brief Create 0D elements on all nodes of the given object except those
1224 // nodes on which a 0D element already exists.
1225 // \param theObject object on whose nodes 0D elements will be created.
1226 // \param theGroupName optional name of a group to add 0D elements created
1227 // and/or found on nodes of \a theObject.
1228 // \return an object (a new group or a temporary SMESH_IDSource) holding
1229 // ids of new and/or found 0D elements.
1231 //=============================================================================
1233 SMESH::SMESH_IDSource_ptr
1234 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1235 const char* theGroupName)
1236 throw (SALOME::SALOME_Exception)
1241 SMESH::SMESH_IDSource_var result;
1244 TIDSortedElemSet elements, elems0D;
1245 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1246 getEditor().Create0DElementsOnAllNodes( elements, elems0D );
1248 SMESH::long_array_var newElems = new SMESH::long_array;
1249 newElems->length( elems0D.size() );
1250 TIDSortedElemSet::iterator eIt = elems0D.begin();
1251 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1252 newElems[ i ] = (*eIt)->GetID();
1254 SMESH::SMESH_GroupBase_var groupToFill;
1255 if ( theGroupName && strlen( theGroupName ))
1257 // Get existing group named theGroupName
1258 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1259 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1260 SMESH::SMESH_GroupBase_var group = groups[i];
1261 if ( !group->_is_nil() ) {
1262 CORBA::String_var name = group->GetName();
1263 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1264 groupToFill = group;
1269 if ( groupToFill->_is_nil() )
1270 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1271 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1272 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1275 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1277 group_i->Add( newElems );
1278 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1279 pyDump << groupToFill;
1283 result = MakeIDSource( newElems, SMESH::ELEM0D );
1284 pyDump << "elem0DIDs";
1287 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1288 << theObject << ", '" << theGroupName << "' )";
1290 return result._retn();
1292 SMESH_CATCH( SMESH::throwCorbaException );
1296 //=============================================================================
1298 * \brief Bind a node to a vertex
1299 * \param NodeID - node ID
1300 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1301 * \retval boolean - false if NodeID or VertexID is invalid
1303 //=============================================================================
1305 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1306 throw (SALOME::SALOME_Exception)
1310 SMESHDS_Mesh * mesh = getMeshDS();
1311 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1313 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1315 if ( mesh->MaxShapeIndex() < VertexID )
1316 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1318 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1319 if ( shape.ShapeType() != TopAbs_VERTEX )
1320 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1322 mesh->SetNodeOnVertex( node, VertexID );
1324 myMesh->SetIsModified( true );
1326 SMESH_CATCH( SMESH::throwCorbaException );
1329 //=============================================================================
1331 * \brief Store node position on an edge
1332 * \param NodeID - node ID
1333 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1334 * \param paramOnEdge - parameter on edge where the node is located
1335 * \retval boolean - false if any parameter is invalid
1337 //=============================================================================
1339 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1340 CORBA::Double paramOnEdge)
1341 throw (SALOME::SALOME_Exception)
1345 SMESHDS_Mesh * mesh = getMeshDS();
1346 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1348 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1350 if ( mesh->MaxShapeIndex() < EdgeID )
1351 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1353 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1354 if ( shape.ShapeType() != TopAbs_EDGE )
1355 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1358 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1359 if ( paramOnEdge < f || paramOnEdge > l )
1360 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1362 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1364 myMesh->SetIsModified( true );
1366 SMESH_CATCH( SMESH::throwCorbaException );
1369 //=============================================================================
1371 * \brief Store node position on a face
1372 * \param NodeID - node ID
1373 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1374 * \param u - U parameter on face where the node is located
1375 * \param v - V parameter on face where the node is located
1376 * \retval boolean - false if any parameter is invalid
1378 //=============================================================================
1380 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1381 CORBA::Double u, CORBA::Double v)
1382 throw (SALOME::SALOME_Exception)
1385 SMESHDS_Mesh * mesh = getMeshDS();
1386 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1388 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1390 if ( mesh->MaxShapeIndex() < FaceID )
1391 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1393 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1394 if ( shape.ShapeType() != TopAbs_FACE )
1395 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1397 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1398 bool isOut = ( u < surf.FirstUParameter() ||
1399 u > surf.LastUParameter() ||
1400 v < surf.FirstVParameter() ||
1401 v > surf.LastVParameter() );
1405 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1406 << " u( " << surf.FirstUParameter()
1407 << "," << surf.LastUParameter()
1408 << ") v( " << surf.FirstVParameter()
1409 << "," << surf.LastVParameter() << ")" );
1411 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1414 mesh->SetNodeOnFace( node, FaceID, u, v );
1415 myMesh->SetIsModified( true );
1417 SMESH_CATCH( SMESH::throwCorbaException );
1420 //=============================================================================
1422 * \brief Bind a node to a solid
1423 * \param NodeID - node ID
1424 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1425 * \retval boolean - false if NodeID or SolidID is invalid
1427 //=============================================================================
1429 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1430 throw (SALOME::SALOME_Exception)
1433 SMESHDS_Mesh * mesh = getMeshDS();
1434 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1436 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1438 if ( mesh->MaxShapeIndex() < SolidID )
1439 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1441 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1442 if ( shape.ShapeType() != TopAbs_SOLID &&
1443 shape.ShapeType() != TopAbs_SHELL)
1444 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1446 mesh->SetNodeInVolume( node, SolidID );
1448 SMESH_CATCH( SMESH::throwCorbaException );
1451 //=============================================================================
1453 * \brief Bind an element to a shape
1454 * \param ElementID - element ID
1455 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1457 //=============================================================================
1459 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1460 CORBA::Long ShapeID)
1461 throw (SALOME::SALOME_Exception)
1464 SMESHDS_Mesh * mesh = getMeshDS();
1465 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1467 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1469 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1470 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1472 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1473 if ( shape.ShapeType() != TopAbs_EDGE &&
1474 shape.ShapeType() != TopAbs_FACE &&
1475 shape.ShapeType() != TopAbs_SOLID &&
1476 shape.ShapeType() != TopAbs_SHELL )
1477 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1479 mesh->SetMeshElementOnShape( elem, ShapeID );
1481 myMesh->SetIsModified( true );
1483 SMESH_CATCH( SMESH::throwCorbaException );
1486 //=============================================================================
1490 //=============================================================================
1492 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1493 CORBA::Long NodeID2)
1494 throw (SALOME::SALOME_Exception)
1499 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1500 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1504 // Update Python script
1505 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1506 << NodeID1 << ", " << NodeID2 << " )";
1508 int ret = getEditor().InverseDiag ( n1, n2 );
1510 declareMeshModified( /*isReComputeSafe=*/false );
1513 SMESH_CATCH( SMESH::throwCorbaException );
1517 //=============================================================================
1521 //=============================================================================
1523 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1524 CORBA::Long NodeID2)
1525 throw (SALOME::SALOME_Exception)
1530 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1531 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1535 // Update Python script
1536 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1537 << NodeID1 << ", " << NodeID2 << " )";
1540 bool stat = getEditor().DeleteDiag ( n1, n2 );
1542 declareMeshModified( /*isReComputeSafe=*/!stat );
1546 SMESH_CATCH( SMESH::throwCorbaException );
1550 //=============================================================================
1554 //=============================================================================
1556 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1557 throw (SALOME::SALOME_Exception)
1562 for (int i = 0; i < IDsOfElements.length(); i++)
1564 CORBA::Long index = IDsOfElements[i];
1565 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1567 getEditor().Reorient( elem );
1569 // Update Python script
1570 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1572 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1575 SMESH_CATCH( SMESH::throwCorbaException );
1579 //=============================================================================
1583 //=============================================================================
1585 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1586 throw (SALOME::SALOME_Exception)
1591 TPythonDump aTPythonDump; // suppress dump in Reorient()
1593 prepareIdSource( theObject );
1595 SMESH::long_array_var anElementsId = theObject->GetIDs();
1596 CORBA::Boolean isDone = Reorient(anElementsId);
1598 // Update Python script
1599 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1601 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1604 SMESH_CATCH( SMESH::throwCorbaException );
1608 //=======================================================================
1609 //function : Reorient2D
1610 //purpose : Reorient faces contained in \a the2Dgroup.
1611 // the2Dgroup - the mesh or its part to reorient
1612 // theDirection - desired direction of normal of \a theFace
1613 // theFace - ID of face whose orientation is checked.
1614 // It can be < 1 then \a thePoint is used to find a face.
1615 // thePoint - is used to find a face if \a theFace < 1.
1616 // return number of reoriented elements.
1617 //=======================================================================
1619 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1620 const SMESH::DirStruct& theDirection,
1621 CORBA::Long theFace,
1622 const SMESH::PointStruct& thePoint)
1623 throw (SALOME::SALOME_Exception)
1626 initData(/*deleteSearchers=*/false);
1628 TIDSortedElemSet elements;
1629 IDSource_Error error;
1630 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1631 if ( error == IDSource_EMPTY )
1633 if ( error == IDSource_INVALID )
1634 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1637 const SMDS_MeshElement* face = 0;
1640 face = getMeshDS()->FindElement( theFace );
1642 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1643 if ( face->GetType() != SMDSAbs_Face )
1644 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1648 // create theElementSearcher if needed
1649 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1650 if ( !theElementSearcher )
1652 if ( elements.empty() ) // search in the whole mesh
1654 if ( myMesh->NbFaces() == 0 )
1655 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1657 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1661 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1662 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1664 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1668 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1669 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1672 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1673 if ( !elements.empty() && !elements.count( face ))
1674 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1677 const SMESH::PointStruct * P = &theDirection.PS;
1678 gp_Vec dirVec( P->x, P->y, P->z );
1679 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1680 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1682 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1685 declareMeshModified( /*isReComputeSafe=*/false );
1687 TPythonDump() << this << ".Reorient2D( "
1688 << the2Dgroup << ", "
1689 << theDirection << ", "
1691 << thePoint << " )";
1695 SMESH_CATCH( SMESH::throwCorbaException );
1699 //=======================================================================
1700 //function : Reorient2DBy3D
1701 //purpose : Reorient faces basing on orientation of adjacent volumes.
1702 //=======================================================================
1704 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1705 SMESH::SMESH_IDSource_ptr volumeGroup,
1706 CORBA::Boolean outsideNormal)
1707 throw (SALOME::SALOME_Exception)
1712 TIDSortedElemSet volumes;
1713 IDSource_Error volsError;
1714 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1717 for ( size_t i = 0; i < faceGroups.length(); ++i )
1719 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1721 TIDSortedElemSet faces;
1722 IDSource_Error error;
1723 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1724 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1725 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1726 if ( error == IDSource_OK && volsError != IDSource_OK )
1727 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1729 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1731 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1736 declareMeshModified( /*isReComputeSafe=*/false );
1738 TPythonDump() << this << ".Reorient2DBy3D( "
1739 << faceGroups << ", "
1740 << volumeGroup << ", "
1741 << outsideNormal << " )";
1745 SMESH_CATCH( SMESH::throwCorbaException );
1749 //=============================================================================
1751 * \brief Fuse neighbour triangles into quadrangles.
1753 //=============================================================================
1755 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1756 SMESH::NumericalFunctor_ptr Criterion,
1757 CORBA::Double MaxAngle)
1758 throw (SALOME::SALOME_Exception)
1763 SMESHDS_Mesh* aMesh = getMeshDS();
1764 TIDSortedElemSet faces,copyFaces;
1765 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1766 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1767 TIDSortedElemSet* workElements = & faces;
1769 if ( myIsPreviewMode ) {
1770 SMDSAbs_ElementType select = SMDSAbs_Face;
1771 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1772 workElements = & copyFaces;
1775 SMESH::NumericalFunctor_i* aNumericalFunctor =
1776 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1777 SMESH::Controls::NumericalFunctorPtr aCrit;
1778 if ( !aNumericalFunctor )
1779 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1781 aCrit = aNumericalFunctor->GetNumericalFunctor();
1783 if ( !myIsPreviewMode ) {
1784 // Update Python script
1785 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1786 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1789 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1791 declareMeshModified( /*isReComputeSafe=*/!stat );
1794 SMESH_CATCH( SMESH::throwCorbaException );
1798 //=============================================================================
1800 * \brief Fuse neighbour triangles into quadrangles.
1802 //=============================================================================
1804 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1805 SMESH::NumericalFunctor_ptr Criterion,
1806 CORBA::Double MaxAngle)
1807 throw (SALOME::SALOME_Exception)
1812 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1814 prepareIdSource( theObject );
1815 SMESH::long_array_var anElementsId = theObject->GetIDs();
1816 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1818 if ( !myIsPreviewMode ) {
1819 SMESH::NumericalFunctor_i* aNumericalFunctor =
1820 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1822 // Update Python script
1823 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1824 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1829 SMESH_CATCH( SMESH::throwCorbaException );
1833 //=============================================================================
1835 * \brief Split quadrangles into triangles.
1837 //=============================================================================
1839 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1840 SMESH::NumericalFunctor_ptr Criterion)
1841 throw (SALOME::SALOME_Exception)
1846 SMESHDS_Mesh* aMesh = getMeshDS();
1847 TIDSortedElemSet faces;
1848 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1850 SMESH::NumericalFunctor_i* aNumericalFunctor =
1851 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1852 SMESH::Controls::NumericalFunctorPtr aCrit;
1853 if ( !aNumericalFunctor )
1854 aCrit.reset( new SMESH::Controls::AspectRatio() );
1856 aCrit = aNumericalFunctor->GetNumericalFunctor();
1859 // Update Python script
1860 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1862 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1864 declareMeshModified( /*isReComputeSafe=*/false );
1867 SMESH_CATCH( SMESH::throwCorbaException );
1871 //=============================================================================
1873 * \brief Split quadrangles into triangles.
1875 //=============================================================================
1877 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1878 SMESH::NumericalFunctor_ptr Criterion)
1879 throw (SALOME::SALOME_Exception)
1884 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1886 prepareIdSource( theObject );
1887 SMESH::long_array_var anElementsId = theObject->GetIDs();
1888 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1890 SMESH::NumericalFunctor_i* aNumericalFunctor =
1891 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1893 // Update Python script
1894 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1896 declareMeshModified( /*isReComputeSafe=*/false );
1899 SMESH_CATCH( SMESH::throwCorbaException );
1903 //================================================================================
1905 * \brief Split each of quadrangles into 4 triangles.
1906 * \param [in] theObject - theQuads Container of quadrangles to split.
1908 //================================================================================
1910 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1911 throw (SALOME::SALOME_Exception)
1916 TIDSortedElemSet faces;
1917 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1919 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1921 getEditor().QuadTo4Tri( faces );
1922 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1924 SMESH_CATCH( SMESH::throwCorbaException );
1927 //=============================================================================
1929 * \brief Split quadrangles into triangles.
1931 //=============================================================================
1933 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1934 CORBA::Boolean Diag13)
1935 throw (SALOME::SALOME_Exception)
1940 SMESHDS_Mesh* aMesh = getMeshDS();
1941 TIDSortedElemSet faces;
1942 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1944 // Update Python script
1945 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1946 << IDsOfElements << ", " << Diag13 << " )";
1948 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1950 declareMeshModified( /*isReComputeSafe=*/ !stat );
1953 SMESH_CATCH( SMESH::throwCorbaException );
1957 //=============================================================================
1959 * \brief Split quadrangles into triangles.
1961 //=============================================================================
1963 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1964 CORBA::Boolean Diag13)
1965 throw (SALOME::SALOME_Exception)
1970 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
1972 prepareIdSource( theObject );
1973 SMESH::long_array_var anElementsId = theObject->GetIDs();
1974 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1976 // Update Python script
1977 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
1978 << theObject << ", " << Diag13 << " )";
1980 declareMeshModified( /*isReComputeSafe=*/!isDone );
1983 SMESH_CATCH( SMESH::throwCorbaException );
1988 //=============================================================================
1990 * Find better splitting of the given quadrangle.
1991 * \param IDOfQuad ID of the quadrangle to be splitted.
1992 * \param Criterion A criterion to choose a diagonal for splitting.
1993 * \return 1 if 1-3 diagonal is better, 2 if 2-4
1994 * diagonal is better, 0 if error occurs.
1996 //=============================================================================
1998 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
1999 SMESH::NumericalFunctor_ptr Criterion)
2000 throw (SALOME::SALOME_Exception)
2005 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2006 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2008 SMESH::NumericalFunctor_i* aNumericalFunctor =
2009 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2010 SMESH::Controls::NumericalFunctorPtr aCrit;
2011 if (aNumericalFunctor)
2012 aCrit = aNumericalFunctor->GetNumericalFunctor();
2014 aCrit.reset(new SMESH::Controls::AspectRatio());
2016 int id = getEditor().BestSplit(quad, aCrit);
2017 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2021 SMESH_CATCH( SMESH::throwCorbaException );
2025 //================================================================================
2027 * \brief Split volumic elements into tetrahedrons
2029 //================================================================================
2031 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2032 CORBA::Short methodFlags)
2033 throw (SALOME::SALOME_Exception)
2038 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2039 const int noneFacet = -1;
2040 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2041 while( volIt->more() )
2042 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2044 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2045 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2047 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2048 << elems << ", " << methodFlags << " )";
2050 SMESH_CATCH( SMESH::throwCorbaException );
2053 //================================================================================
2055 * \brief Split hexahedra into triangular prisms
2056 * \param elems - elements to split
2057 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2058 * to split into triangles
2059 * \param methodFlags - flags passing splitting method:
2060 * 1 - split the hexahedron into 2 prisms
2061 * 2 - split the hexahedron into 4 prisms
2063 //================================================================================
2065 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr elems,
2066 const SMESH::PointStruct & startHexPoint,
2067 const SMESH::DirStruct& facetToSplitNormal,
2068 CORBA::Short methodFlags,
2069 CORBA::Boolean allDomains)
2070 throw (SALOME::SALOME_Exception)
2074 prepareIdSource( elems );
2076 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2079 gp_Dir( facetToSplitNormal.PS.x,
2080 facetToSplitNormal.PS.y,
2081 facetToSplitNormal.PS.z ));
2082 TIDSortedElemSet elemSet;
2083 SMESH::long_array_var anElementsId = elems->GetIDs();
2084 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2085 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2087 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2088 while ( !elemSet.empty() )
2090 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2094 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2095 for ( ; ef != elemFacets.end(); ++ef )
2096 elemSet.erase( ef->first );
2099 if ( methodFlags == 2 )
2100 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2102 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2104 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2105 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2107 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2109 << startHexPoint << ", "
2110 << facetToSplitNormal<< ", "
2111 << methodFlags<< ", "
2112 << allDomains << " )";
2114 SMESH_CATCH( SMESH::throwCorbaException );
2117 //=======================================================================
2120 //=======================================================================
2123 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2124 const SMESH::long_array & IDsOfFixedNodes,
2125 CORBA::Long MaxNbOfIterations,
2126 CORBA::Double MaxAspectRatio,
2127 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2128 throw (SALOME::SALOME_Exception)
2130 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2131 MaxAspectRatio, Method, false );
2135 //=======================================================================
2136 //function : SmoothParametric
2138 //=======================================================================
2141 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2142 const SMESH::long_array & IDsOfFixedNodes,
2143 CORBA::Long MaxNbOfIterations,
2144 CORBA::Double MaxAspectRatio,
2145 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2146 throw (SALOME::SALOME_Exception)
2148 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2149 MaxAspectRatio, Method, true );
2153 //=======================================================================
2154 //function : SmoothObject
2156 //=======================================================================
2159 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2160 const SMESH::long_array & IDsOfFixedNodes,
2161 CORBA::Long MaxNbOfIterations,
2162 CORBA::Double MaxAspectRatio,
2163 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2164 throw (SALOME::SALOME_Exception)
2166 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2167 MaxAspectRatio, Method, false);
2171 //=======================================================================
2172 //function : SmoothParametricObject
2174 //=======================================================================
2177 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2178 const SMESH::long_array & IDsOfFixedNodes,
2179 CORBA::Long MaxNbOfIterations,
2180 CORBA::Double MaxAspectRatio,
2181 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2182 throw (SALOME::SALOME_Exception)
2184 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2185 MaxAspectRatio, Method, true);
2189 //=============================================================================
2193 //=============================================================================
2196 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2197 const SMESH::long_array & IDsOfFixedNodes,
2198 CORBA::Long MaxNbOfIterations,
2199 CORBA::Double MaxAspectRatio,
2200 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2202 throw (SALOME::SALOME_Exception)
2207 SMESHDS_Mesh* aMesh = getMeshDS();
2209 TIDSortedElemSet elements;
2210 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2212 set<const SMDS_MeshNode*> fixedNodes;
2213 for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
2214 CORBA::Long index = IDsOfFixedNodes[i];
2215 const SMDS_MeshNode * node = aMesh->FindNode(index);
2217 fixedNodes.insert( node );
2219 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2220 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2221 method = ::SMESH_MeshEditor::CENTROIDAL;
2223 getEditor().Smooth(elements, fixedNodes, method,
2224 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2226 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2228 // Update Python script
2229 TPythonDump() << "isDone = " << this << "."
2230 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2231 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2232 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2233 << "SMESH.SMESH_MeshEditor."
2234 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2235 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2239 SMESH_CATCH( SMESH::throwCorbaException );
2243 //=============================================================================
2247 //=============================================================================
2250 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2251 const SMESH::long_array & IDsOfFixedNodes,
2252 CORBA::Long MaxNbOfIterations,
2253 CORBA::Double MaxAspectRatio,
2254 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2256 throw (SALOME::SALOME_Exception)
2261 TPythonDump aTPythonDump; // suppress dump in smooth()
2263 prepareIdSource( theObject );
2264 SMESH::long_array_var anElementsId = theObject->GetIDs();
2265 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2266 MaxAspectRatio, Method, IsParametric);
2268 // Update Python script
2269 aTPythonDump << "isDone = " << this << "."
2270 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2271 << theObject << ", " << IDsOfFixedNodes << ", "
2272 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2273 << "SMESH.SMESH_MeshEditor."
2274 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2275 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2279 SMESH_CATCH( SMESH::throwCorbaException );
2283 //=============================================================================
2287 //=============================================================================
2289 void SMESH_MeshEditor_i::RenumberNodes()
2290 throw (SALOME::SALOME_Exception)
2293 // Update Python script
2294 TPythonDump() << this << ".RenumberNodes()";
2296 getMeshDS()->Renumber( true );
2298 SMESH_CATCH( SMESH::throwCorbaException );
2301 //=============================================================================
2305 //=============================================================================
2307 void SMESH_MeshEditor_i::RenumberElements()
2308 throw (SALOME::SALOME_Exception)
2311 // Update Python script
2312 TPythonDump() << this << ".RenumberElements()";
2314 getMeshDS()->Renumber( false );
2316 SMESH_CATCH( SMESH::throwCorbaException );
2319 //=======================================================================
2321 * \brief Return groups by their IDs
2323 //=======================================================================
2325 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2326 throw (SALOME::SALOME_Exception)
2331 myMesh_i->CreateGroupServants();
2332 return myMesh_i->GetGroups( *groupIDs );
2334 SMESH_CATCH( SMESH::throwCorbaException );
2338 //=======================================================================
2339 //function : RotationSweepObjects
2341 //=======================================================================
2343 SMESH::ListOfGroups*
2344 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2345 const SMESH::ListOfIDSources & theEdges,
2346 const SMESH::ListOfIDSources & theFaces,
2347 const SMESH::AxisStruct & theAxis,
2348 CORBA::Double theAngleInRadians,
2349 CORBA::Long theNbOfSteps,
2350 CORBA::Double theTolerance,
2351 const bool theMakeGroups)
2352 throw (SALOME::SALOME_Exception)
2357 TIDSortedElemSet elemsNodes[2];
2358 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2359 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2360 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2362 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2363 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2364 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2365 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2367 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2368 bool makeWalls=true;
2369 if ( myIsPreviewMode )
2371 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2372 TPreviewMesh * tmpMesh = getPreviewMesh();
2373 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2374 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2375 workElements = & copyElements[0];
2376 //makeWalls = false; -- faces are needed for preview
2379 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2381 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2382 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2384 ::SMESH_MeshEditor::PGroupIDs groupIds =
2385 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2386 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2388 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2390 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2392 if ( !myIsPreviewMode )
2394 dumpGroupsList( aPythonDump, aGroups );
2395 aPythonDump << this<< ".RotationSweepObjects( "
2400 << TVar( theAngleInRadians ) << ", "
2401 << TVar( theNbOfSteps ) << ", "
2402 << TVar( theTolerance ) << ", "
2403 << theMakeGroups << " )";
2407 getPreviewMesh()->Remove( SMDSAbs_Volume );
2410 return aGroups ? aGroups : new SMESH::ListOfGroups;
2412 SMESH_CATCH( SMESH::throwCorbaException );
2416 namespace MeshEditor_I
2419 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2421 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2423 bool myIsExtrusionByNormal;
2425 static int makeFlags( CORBA::Boolean MakeGroups,
2426 CORBA::Boolean ByAverageNormal = false,
2427 CORBA::Boolean UseInputElemsOnly = false,
2428 CORBA::Long Flags = 0,
2429 CORBA::Boolean MakeBoundary = true )
2431 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2432 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2433 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2434 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2438 ExtrusionParams(const SMESH::DirStruct & theDir,
2439 CORBA::Long theNbOfSteps,
2440 CORBA::Boolean theMakeGroups):
2441 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2445 makeFlags( theMakeGroups )),
2446 myIsExtrusionByNormal( false )
2450 ExtrusionParams(const SMESH::DirStruct & theDir,
2451 CORBA::Long theNbOfSteps,
2452 CORBA::Boolean theMakeGroups,
2453 CORBA::Long theExtrFlags,
2454 CORBA::Double theSewTolerance):
2455 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2459 makeFlags( theMakeGroups, false, false,
2460 theExtrFlags, false ),
2462 myIsExtrusionByNormal( false )
2465 // params for extrusion by normal
2466 ExtrusionParams(CORBA::Double theStepSize,
2467 CORBA::Long theNbOfSteps,
2468 CORBA::Short theDim,
2469 CORBA::Boolean theByAverageNormal,
2470 CORBA::Boolean theUseInputElemsOnly,
2471 CORBA::Boolean theMakeGroups ):
2472 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2474 makeFlags( theMakeGroups,
2475 theByAverageNormal, theUseInputElemsOnly ),
2477 myIsExtrusionByNormal( true )
2483 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2488 //=======================================================================
2490 * \brief Generate dim+1 elements by extrusion of elements along vector
2491 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2492 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2493 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2494 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2495 * \param [in] nbOfSteps - number of elements to generate from one element
2496 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2497 * corresponding to groups the input elements included in.
2498 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2500 //=======================================================================
2502 SMESH::ListOfGroups*
2503 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2504 const SMESH::ListOfIDSources & theEdges,
2505 const SMESH::ListOfIDSources & theFaces,
2506 const SMESH::DirStruct & theStepVector,
2507 CORBA::Long theNbOfSteps,
2508 CORBA::Boolean theToMakeGroups)
2509 throw (SALOME::SALOME_Exception)
2514 ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
2516 TIDSortedElemSet elemsNodes[2];
2517 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2518 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2519 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2521 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2522 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2523 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2524 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2526 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2527 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2528 if ( myIsPreviewMode )
2530 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2531 // previewType = SMDSAbs_Edge;
2533 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2534 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2535 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2536 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2537 workElements = & copyElements[0];
2539 params.SetNoGroups();
2541 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2543 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2544 ::SMESH_MeshEditor::PGroupIDs groupIds =
2545 getEditor().ExtrusionSweep( workElements, params, aHistory );
2547 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2549 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2551 if ( !myIsPreviewMode )
2553 dumpGroupsList( aPythonDump, aGroups );
2554 aPythonDump << this<< ".ExtrusionSweepObjects( "
2558 << theStepVector << ", "
2559 << TVar( theNbOfSteps ) << ", "
2560 << theToMakeGroups << " )";
2564 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2567 return aGroups ? aGroups : new SMESH::ListOfGroups;
2569 SMESH_CATCH( SMESH::throwCorbaException );
2573 //=======================================================================
2574 //function : ExtrusionByNormal
2576 //=======================================================================
2578 SMESH::ListOfGroups*
2579 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2580 CORBA::Double stepSize,
2581 CORBA::Long nbOfSteps,
2582 CORBA::Boolean byAverageNormal,
2583 CORBA::Boolean useInputElemsOnly,
2584 CORBA::Boolean makeGroups,
2586 throw (SALOME::SALOME_Exception)
2591 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2593 ExtrusionParams params( stepSize, nbOfSteps, dim,
2594 byAverageNormal, useInputElemsOnly, makeGroups );
2596 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2597 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2599 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2600 if (( elemTypes->length() == 1 ) &&
2601 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2602 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2605 TIDSortedElemSet elemsNodes[2];
2606 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2607 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2609 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2610 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2611 if ( myIsPreviewMode )
2613 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2614 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2615 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2616 workElements = & copyElements[0];
2618 params.SetNoGroups();
2621 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2622 ::SMESH_MeshEditor::PGroupIDs groupIds =
2623 getEditor().ExtrusionSweep( workElements, params, aHistory );
2625 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2627 if (!myIsPreviewMode) {
2628 dumpGroupsList(aPythonDump, aGroups);
2629 aPythonDump << this << ".ExtrusionByNormal( " << objects
2630 << ", " << TVar( stepSize )
2631 << ", " << TVar( nbOfSteps )
2632 << ", " << byAverageNormal
2633 << ", " << useInputElemsOnly
2634 << ", " << makeGroups
2640 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2643 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2645 return aGroups ? aGroups : new SMESH::ListOfGroups;
2647 SMESH_CATCH( SMESH::throwCorbaException );
2651 //=======================================================================
2652 //function : AdvancedExtrusion
2654 //=======================================================================
2656 SMESH::ListOfGroups*
2657 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2658 const SMESH::DirStruct & theStepVector,
2659 CORBA::Long theNbOfSteps,
2660 CORBA::Long theExtrFlags,
2661 CORBA::Double theSewTolerance,
2662 CORBA::Boolean theMakeGroups)
2663 throw (SALOME::SALOME_Exception)
2668 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2670 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2671 theExtrFlags, theSewTolerance );
2673 TIDSortedElemSet elemsNodes[2];
2674 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2676 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2677 ::SMESH_MeshEditor::PGroupIDs groupIds =
2678 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2680 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2682 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2684 if ( !myIsPreviewMode ) {
2685 dumpGroupsList(aPythonDump, aGroups);
2686 aPythonDump << this << ".AdvancedExtrusion( "
2687 << theIDsOfElements << ", "
2688 << theStepVector << ", "
2689 << theNbOfSteps << ", "
2690 << theExtrFlags << ", "
2691 << theSewTolerance << ", "
2692 << theMakeGroups << " )";
2696 getPreviewMesh()->Remove( SMDSAbs_Volume );
2699 return aGroups ? aGroups : new SMESH::ListOfGroups;
2701 SMESH_CATCH( SMESH::throwCorbaException );
2705 //================================================================================
2707 * \brief Convert extrusion error to IDL enum
2709 //================================================================================
2713 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2715 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2719 RETCASE( EXTR_NO_ELEMENTS );
2720 RETCASE( EXTR_PATH_NOT_EDGE );
2721 RETCASE( EXTR_BAD_PATH_SHAPE );
2722 RETCASE( EXTR_BAD_STARTING_NODE );
2723 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2724 RETCASE( EXTR_CANT_GET_TANGENT );
2726 return SMESH::SMESH_MeshEditor::EXTR_OK;
2730 //=======================================================================
2731 //function : extrusionAlongPath
2733 //=======================================================================
2734 SMESH::ListOfGroups*
2735 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2736 const SMESH::ListOfIDSources & theEdges,
2737 const SMESH::ListOfIDSources & theFaces,
2738 SMESH::SMESH_IDSource_ptr thePathMesh,
2739 GEOM::GEOM_Object_ptr thePathShape,
2740 CORBA::Long theNodeStart,
2741 CORBA::Boolean theHasAngles,
2742 const SMESH::double_array & theAngles,
2743 CORBA::Boolean theLinearVariation,
2744 CORBA::Boolean theHasRefPoint,
2745 const SMESH::PointStruct & theRefPoint,
2747 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2748 throw (SALOME::SALOME_Exception)
2753 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2755 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2756 if ( thePathMesh->_is_nil() )
2757 return aGroups._retn();
2760 SMESH_subMesh* aSubMesh = 0;
2761 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2762 if ( thePathShape->_is_nil() )
2764 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2765 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2767 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2768 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2769 if ( !aMeshImp ) return aGroups._retn();
2770 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2771 if ( !aSubMesh ) return aGroups._retn();
2773 else if ( !aMeshImp ||
2774 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2776 return aGroups._retn();
2781 if ( !aMeshImp ) return aGroups._retn();
2782 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2783 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2784 if ( !aSubMesh || !aSubMesh->GetSubMeshDS() )
2785 return aGroups._retn();
2788 SMDS_MeshNode* nodeStart =
2789 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2791 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2792 return aGroups._retn();
2795 TIDSortedElemSet elemsNodes[2];
2796 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2797 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2798 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2800 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2801 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2802 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2803 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2805 list<double> angles;
2806 for (int i = 0; i < theAngles.length(); i++) {
2807 angles.push_back( theAngles[i] );
2810 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2812 int nbOldGroups = myMesh->NbGroup();
2814 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2815 if ( myIsPreviewMode )
2817 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2818 TPreviewMesh * tmpMesh = getPreviewMesh();
2819 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2820 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2821 workElements = & copyElements[0];
2822 theMakeGroups = false;
2825 ::SMESH_MeshEditor::Extrusion_Error error;
2827 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2828 theHasAngles, angles, theLinearVariation,
2829 theHasRefPoint, refPnt, theMakeGroups );
2831 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2832 theHasAngles, angles, theLinearVariation,
2833 theHasRefPoint, refPnt, theMakeGroups );
2835 declareMeshModified( /*isReComputeSafe=*/true );
2836 theError = convExtrError( error );
2838 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2839 if ( theMakeGroups ) {
2840 list<int> groupIDs = myMesh->GetGroupIds();
2841 list<int>::iterator newBegin = groupIDs.begin();
2842 std::advance( newBegin, nbOldGroups ); // skip old groups
2843 groupIDs.erase( groupIDs.begin(), newBegin );
2844 aGroups = getGroups( & groupIDs );
2845 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2848 if ( !myIsPreviewMode ) {
2849 aPythonDump << "(" << aGroups << ", error) = "
2850 << this << ".ExtrusionAlongPathObjects( "
2854 << thePathMesh << ", "
2855 << thePathShape << ", "
2856 << theNodeStart << ", "
2857 << theHasAngles << ", "
2858 << theAngles << ", "
2859 << theLinearVariation << ", "
2860 << theHasRefPoint << ", "
2861 << "SMESH.PointStruct( "
2862 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2863 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2864 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2865 << theMakeGroups << " )";
2869 getPreviewMesh()->Remove( SMDSAbs_Volume );
2872 return aGroups._retn();
2874 SMESH_CATCH( SMESH::throwCorbaException );
2878 //================================================================================
2880 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2881 * of given angles along path steps
2882 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2883 * which proceeds the extrusion
2884 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2885 * is used to define the sub-mesh for the path
2887 //================================================================================
2889 SMESH::double_array*
2890 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2891 GEOM::GEOM_Object_ptr thePathShape,
2892 const SMESH::double_array & theAngles)
2894 SMESH::double_array_var aResult = new SMESH::double_array();
2895 int nbAngles = theAngles.length();
2896 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2898 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2899 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2900 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2901 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2902 return aResult._retn();
2903 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2904 if ( nbSteps == nbAngles )
2906 aResult.inout() = theAngles;
2910 aResult->length( nbSteps );
2911 double rAn2St = double( nbAngles ) / double( nbSteps );
2912 double angPrev = 0, angle;
2913 for ( int iSt = 0; iSt < nbSteps; ++iSt )
2915 double angCur = rAn2St * ( iSt+1 );
2916 double angCurFloor = floor( angCur );
2917 double angPrevFloor = floor( angPrev );
2918 if ( angPrevFloor == angCurFloor )
2919 angle = rAn2St * theAngles[ int( angCurFloor ) ];
2922 int iP = int( angPrevFloor );
2923 double angPrevCeil = ceil(angPrev);
2924 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2926 int iC = int( angCurFloor );
2927 if ( iC < nbAngles )
2928 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2930 iP = int( angPrevCeil );
2932 angle += theAngles[ iC ];
2934 aResult[ iSt ] = angle;
2939 // Update Python script
2940 TPythonDump() << "rotAngles = " << theAngles;
2941 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
2942 << thePathMesh << ", "
2943 << thePathShape << ", "
2946 return aResult._retn();
2949 //=======================================================================
2952 //=======================================================================
2954 SMESH::ListOfGroups*
2955 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
2956 const SMESH::AxisStruct & theAxis,
2957 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2958 CORBA::Boolean theCopy,
2960 ::SMESH_Mesh* theTargetMesh)
2961 throw (SALOME::SALOME_Exception)
2966 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2967 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2969 if ( theTargetMesh )
2973 switch ( theMirrorType ) {
2974 case SMESH::SMESH_MeshEditor::POINT:
2975 aTrsf.SetMirror( P );
2977 case SMESH::SMESH_MeshEditor::AXIS:
2978 aTrsf.SetMirror( gp_Ax1( P, V ));
2981 aTrsf.SetMirror( gp_Ax2( P, V ));
2984 TIDSortedElemSet copyElements;
2985 TIDSortedElemSet* workElements = & theElements;
2987 if ( myIsPreviewMode )
2989 TPreviewMesh * tmpMesh = getPreviewMesh();
2990 tmpMesh->Copy( theElements, copyElements);
2991 if ( !theCopy && !theTargetMesh )
2993 TIDSortedElemSet elemsAround, elemsAroundCopy;
2994 getElementsAround( theElements, getMeshDS(), elemsAround );
2995 tmpMesh->Copy( elemsAround, elemsAroundCopy);
2997 workElements = & copyElements;
2998 theMakeGroups = false;
3001 ::SMESH_MeshEditor::PGroupIDs groupIds =
3002 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3004 if ( theCopy && !myIsPreviewMode)
3006 if ( theTargetMesh )
3008 theTargetMesh->GetMeshDS()->Modified();
3012 declareMeshModified( /*isReComputeSafe=*/false );
3015 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3017 SMESH_CATCH( SMESH::throwCorbaException );
3021 //=======================================================================
3024 //=======================================================================
3026 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3027 const SMESH::AxisStruct & theAxis,
3028 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3029 CORBA::Boolean theCopy)
3030 throw (SALOME::SALOME_Exception)
3032 if ( !myIsPreviewMode ) {
3033 TPythonDump() << this << ".Mirror( "
3034 << theIDsOfElements << ", "
3036 << mirrorTypeName(theMirrorType) << ", "
3039 if ( theIDsOfElements.length() > 0 )
3041 TIDSortedElemSet elements;
3042 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3043 mirror(elements, theAxis, theMirrorType, theCopy, false);
3048 //=======================================================================
3049 //function : MirrorObject
3051 //=======================================================================
3053 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3054 const SMESH::AxisStruct & theAxis,
3055 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3056 CORBA::Boolean theCopy)
3057 throw (SALOME::SALOME_Exception)
3059 if ( !myIsPreviewMode ) {
3060 TPythonDump() << this << ".MirrorObject( "
3061 << theObject << ", "
3063 << mirrorTypeName(theMirrorType) << ", "
3066 TIDSortedElemSet elements;
3068 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3070 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3071 mirror(elements, theAxis, theMirrorType, theCopy, false);
3074 //=======================================================================
3075 //function : MirrorMakeGroups
3077 //=======================================================================
3079 SMESH::ListOfGroups*
3080 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3081 const SMESH::AxisStruct& theMirror,
3082 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3083 throw (SALOME::SALOME_Exception)
3085 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3087 SMESH::ListOfGroups * aGroups = 0;
3088 if ( theIDsOfElements.length() > 0 )
3090 TIDSortedElemSet elements;
3091 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3092 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3094 if (!myIsPreviewMode) {
3095 dumpGroupsList(aPythonDump, aGroups);
3096 aPythonDump << this << ".MirrorMakeGroups( "
3097 << theIDsOfElements << ", "
3098 << theMirror << ", "
3099 << mirrorTypeName(theMirrorType) << " )";
3104 //=======================================================================
3105 //function : MirrorObjectMakeGroups
3107 //=======================================================================
3109 SMESH::ListOfGroups*
3110 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3111 const SMESH::AxisStruct& theMirror,
3112 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3113 throw (SALOME::SALOME_Exception)
3115 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3117 SMESH::ListOfGroups * aGroups = 0;
3118 TIDSortedElemSet elements;
3119 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3120 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3122 if (!myIsPreviewMode)
3124 dumpGroupsList(aPythonDump,aGroups);
3125 aPythonDump << this << ".MirrorObjectMakeGroups( "
3126 << theObject << ", "
3127 << theMirror << ", "
3128 << mirrorTypeName(theMirrorType) << " )";
3133 //=======================================================================
3134 //function : MirrorMakeMesh
3136 //=======================================================================
3138 SMESH::SMESH_Mesh_ptr
3139 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3140 const SMESH::AxisStruct& theMirror,
3141 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3142 CORBA::Boolean theCopyGroups,
3143 const char* theMeshName)
3144 throw (SALOME::SALOME_Exception)
3146 SMESH_Mesh_i* mesh_i;
3147 SMESH::SMESH_Mesh_var mesh;
3148 { // open new scope to dump "MakeMesh" command
3149 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3151 TPythonDump pydump; // to prevent dump at mesh creation
3153 mesh = makeMesh( theMeshName );
3154 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3155 if (mesh_i && theIDsOfElements.length() > 0 )
3157 TIDSortedElemSet elements;
3158 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3159 mirror(elements, theMirror, theMirrorType,
3160 false, theCopyGroups, & mesh_i->GetImpl());
3161 mesh_i->CreateGroupServants();
3164 if (!myIsPreviewMode) {
3165 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3166 << theIDsOfElements << ", "
3167 << theMirror << ", "
3168 << mirrorTypeName(theMirrorType) << ", "
3169 << theCopyGroups << ", '"
3170 << theMeshName << "' )";
3175 if (!myIsPreviewMode && mesh_i)
3176 mesh_i->GetGroups();
3178 return mesh._retn();
3181 //=======================================================================
3182 //function : MirrorObjectMakeMesh
3184 //=======================================================================
3186 SMESH::SMESH_Mesh_ptr
3187 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3188 const SMESH::AxisStruct& theMirror,
3189 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3190 CORBA::Boolean theCopyGroups,
3191 const char* theMeshName)
3192 throw (SALOME::SALOME_Exception)
3194 SMESH_Mesh_i* mesh_i;
3195 SMESH::SMESH_Mesh_var mesh;
3196 { // open new scope to dump "MakeMesh" command
3197 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3199 TPythonDump pydump; // to prevent dump at mesh creation
3201 mesh = makeMesh( theMeshName );
3202 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3203 TIDSortedElemSet elements;
3205 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3207 mirror(elements, theMirror, theMirrorType,
3208 false, theCopyGroups, & mesh_i->GetImpl());
3209 mesh_i->CreateGroupServants();
3211 if (!myIsPreviewMode) {
3212 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3213 << theObject << ", "
3214 << theMirror << ", "
3215 << mirrorTypeName(theMirrorType) << ", "
3216 << theCopyGroups << ", '"
3217 << theMeshName << "' )";
3222 if (!myIsPreviewMode && mesh_i)
3223 mesh_i->GetGroups();
3225 return mesh._retn();
3228 //=======================================================================
3229 //function : translate
3231 //=======================================================================
3233 SMESH::ListOfGroups*
3234 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3235 const SMESH::DirStruct & theVector,
3236 CORBA::Boolean theCopy,
3238 ::SMESH_Mesh* theTargetMesh)
3239 throw (SALOME::SALOME_Exception)
3244 if ( theTargetMesh )
3248 const SMESH::PointStruct * P = &theVector.PS;
3249 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3251 TIDSortedElemSet copyElements;
3252 TIDSortedElemSet* workElements = &theElements;
3254 if ( myIsPreviewMode )
3256 TPreviewMesh * tmpMesh = getPreviewMesh();
3257 tmpMesh->Copy( theElements, copyElements);
3258 if ( !theCopy && !theTargetMesh )
3260 TIDSortedElemSet elemsAround, elemsAroundCopy;
3261 getElementsAround( theElements, getMeshDS(), elemsAround );
3262 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3264 workElements = & copyElements;
3265 theMakeGroups = false;
3268 ::SMESH_MeshEditor::PGroupIDs groupIds =
3269 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3271 if ( theCopy && !myIsPreviewMode )
3273 if ( theTargetMesh )
3275 theTargetMesh->GetMeshDS()->Modified();
3279 declareMeshModified( /*isReComputeSafe=*/false );
3283 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3285 SMESH_CATCH( SMESH::throwCorbaException );
3289 //=======================================================================
3290 //function : Translate
3292 //=======================================================================
3294 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3295 const SMESH::DirStruct & theVector,
3296 CORBA::Boolean theCopy)
3297 throw (SALOME::SALOME_Exception)
3299 if (!myIsPreviewMode) {
3300 TPythonDump() << this << ".Translate( "
3301 << theIDsOfElements << ", "
3302 << theVector << ", "
3305 if (theIDsOfElements.length()) {
3306 TIDSortedElemSet elements;
3307 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3308 translate(elements, theVector, theCopy, false);
3312 //=======================================================================
3313 //function : TranslateObject
3315 //=======================================================================
3317 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3318 const SMESH::DirStruct & theVector,
3319 CORBA::Boolean theCopy)
3320 throw (SALOME::SALOME_Exception)
3322 if (!myIsPreviewMode) {
3323 TPythonDump() << this << ".TranslateObject( "
3324 << theObject << ", "
3325 << theVector << ", "
3328 TIDSortedElemSet elements;
3330 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3332 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3333 translate(elements, theVector, theCopy, false);
3336 //=======================================================================
3337 //function : TranslateMakeGroups
3339 //=======================================================================
3341 SMESH::ListOfGroups*
3342 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3343 const SMESH::DirStruct& theVector)
3344 throw (SALOME::SALOME_Exception)
3346 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3348 SMESH::ListOfGroups * aGroups = 0;
3349 if (theIDsOfElements.length()) {
3350 TIDSortedElemSet elements;
3351 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3352 aGroups = translate(elements,theVector,true,true);
3354 if (!myIsPreviewMode) {
3355 dumpGroupsList(aPythonDump, aGroups);
3356 aPythonDump << this << ".TranslateMakeGroups( "
3357 << theIDsOfElements << ", "
3358 << theVector << " )";
3363 //=======================================================================
3364 //function : TranslateObjectMakeGroups
3366 //=======================================================================
3368 SMESH::ListOfGroups*
3369 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3370 const SMESH::DirStruct& theVector)
3371 throw (SALOME::SALOME_Exception)
3373 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3375 SMESH::ListOfGroups * aGroups = 0;
3376 TIDSortedElemSet elements;
3377 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3378 aGroups = translate(elements, theVector, true, true);
3380 if (!myIsPreviewMode) {
3381 dumpGroupsList(aPythonDump, aGroups);
3382 aPythonDump << this << ".TranslateObjectMakeGroups( "
3383 << theObject << ", "
3384 << theVector << " )";
3389 //=======================================================================
3390 //function : TranslateMakeMesh
3392 //=======================================================================
3394 SMESH::SMESH_Mesh_ptr
3395 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3396 const SMESH::DirStruct& theVector,
3397 CORBA::Boolean theCopyGroups,
3398 const char* theMeshName)
3399 throw (SALOME::SALOME_Exception)
3401 SMESH_Mesh_i* mesh_i;
3402 SMESH::SMESH_Mesh_var mesh;
3404 { // open new scope to dump "MakeMesh" command
3405 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3407 TPythonDump pydump; // to prevent dump at mesh creation
3409 mesh = makeMesh( theMeshName );
3410 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3412 if ( mesh_i && theIDsOfElements.length() )
3414 TIDSortedElemSet elements;
3415 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3416 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3417 mesh_i->CreateGroupServants();
3420 if ( !myIsPreviewMode ) {
3421 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3422 << theIDsOfElements << ", "
3423 << theVector << ", "
3424 << theCopyGroups << ", '"
3425 << theMeshName << "' )";
3430 if (!myIsPreviewMode && mesh_i)
3431 mesh_i->GetGroups();
3433 return mesh._retn();
3436 //=======================================================================
3437 //function : TranslateObjectMakeMesh
3439 //=======================================================================
3441 SMESH::SMESH_Mesh_ptr
3442 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3443 const SMESH::DirStruct& theVector,
3444 CORBA::Boolean theCopyGroups,
3445 const char* theMeshName)
3446 throw (SALOME::SALOME_Exception)
3449 SMESH_Mesh_i* mesh_i;
3450 SMESH::SMESH_Mesh_var mesh;
3451 { // open new scope to dump "MakeMesh" command
3452 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3454 TPythonDump pydump; // to prevent dump at mesh creation
3455 mesh = makeMesh( theMeshName );
3456 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3458 TIDSortedElemSet elements;
3460 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3462 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3463 mesh_i->CreateGroupServants();
3465 if ( !myIsPreviewMode ) {
3466 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3467 << theObject << ", "
3468 << theVector << ", "
3469 << theCopyGroups << ", '"
3470 << theMeshName << "' )";
3475 if (!myIsPreviewMode && mesh_i)
3476 mesh_i->GetGroups();
3478 return mesh._retn();
3480 SMESH_CATCH( SMESH::throwCorbaException );
3484 //=======================================================================
3487 //=======================================================================
3489 SMESH::ListOfGroups*
3490 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3491 const SMESH::AxisStruct & theAxis,
3492 CORBA::Double theAngle,
3493 CORBA::Boolean theCopy,
3495 ::SMESH_Mesh* theTargetMesh)
3496 throw (SALOME::SALOME_Exception)
3501 if ( theTargetMesh )
3504 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3505 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3508 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3510 TIDSortedElemSet copyElements;
3511 TIDSortedElemSet* workElements = &theElements;
3512 if ( myIsPreviewMode ) {
3513 TPreviewMesh * tmpMesh = getPreviewMesh();
3514 tmpMesh->Copy( theElements, copyElements );
3515 if ( !theCopy && !theTargetMesh )
3517 TIDSortedElemSet elemsAround, elemsAroundCopy;
3518 getElementsAround( theElements, getMeshDS(), elemsAround );
3519 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3521 workElements = ©Elements;
3522 theMakeGroups = false;
3525 ::SMESH_MeshEditor::PGroupIDs groupIds =
3526 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3528 if ( theCopy && !myIsPreviewMode)
3530 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3531 else declareMeshModified( /*isReComputeSafe=*/false );
3534 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3536 SMESH_CATCH( SMESH::throwCorbaException );
3540 //=======================================================================
3543 //=======================================================================
3545 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3546 const SMESH::AxisStruct & theAxis,
3547 CORBA::Double theAngle,
3548 CORBA::Boolean theCopy)
3549 throw (SALOME::SALOME_Exception)
3551 if (!myIsPreviewMode) {
3552 TPythonDump() << this << ".Rotate( "
3553 << theIDsOfElements << ", "
3555 << TVar( theAngle ) << ", "
3558 if (theIDsOfElements.length() > 0)
3560 TIDSortedElemSet elements;
3561 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3562 rotate(elements,theAxis,theAngle,theCopy,false);
3566 //=======================================================================
3567 //function : RotateObject
3569 //=======================================================================
3571 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3572 const SMESH::AxisStruct & theAxis,
3573 CORBA::Double theAngle,
3574 CORBA::Boolean theCopy)
3575 throw (SALOME::SALOME_Exception)
3577 if ( !myIsPreviewMode ) {
3578 TPythonDump() << this << ".RotateObject( "
3579 << theObject << ", "
3581 << TVar( theAngle ) << ", "
3584 TIDSortedElemSet elements;
3585 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3586 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3587 rotate(elements,theAxis,theAngle,theCopy,false);
3590 //=======================================================================
3591 //function : RotateMakeGroups
3593 //=======================================================================
3595 SMESH::ListOfGroups*
3596 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3597 const SMESH::AxisStruct& theAxis,
3598 CORBA::Double theAngle)
3599 throw (SALOME::SALOME_Exception)
3601 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3603 SMESH::ListOfGroups * aGroups = 0;
3604 if (theIDsOfElements.length() > 0)
3606 TIDSortedElemSet elements;
3607 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3608 aGroups = rotate(elements,theAxis,theAngle,true,true);
3610 if (!myIsPreviewMode) {
3611 dumpGroupsList(aPythonDump, aGroups);
3612 aPythonDump << this << ".RotateMakeGroups( "
3613 << theIDsOfElements << ", "
3615 << TVar( theAngle ) << " )";
3620 //=======================================================================
3621 //function : RotateObjectMakeGroups
3623 //=======================================================================
3625 SMESH::ListOfGroups*
3626 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3627 const SMESH::AxisStruct& theAxis,
3628 CORBA::Double theAngle)
3629 throw (SALOME::SALOME_Exception)
3631 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3633 SMESH::ListOfGroups * aGroups = 0;
3634 TIDSortedElemSet elements;
3635 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3636 aGroups = rotate(elements, theAxis, theAngle, true, true);
3638 if (!myIsPreviewMode) {
3639 dumpGroupsList(aPythonDump, aGroups);
3640 aPythonDump << this << ".RotateObjectMakeGroups( "
3641 << theObject << ", "
3643 << TVar( theAngle ) << " )";
3648 //=======================================================================
3649 //function : RotateMakeMesh
3651 //=======================================================================
3653 SMESH::SMESH_Mesh_ptr
3654 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3655 const SMESH::AxisStruct& theAxis,
3656 CORBA::Double theAngleInRadians,
3657 CORBA::Boolean theCopyGroups,
3658 const char* theMeshName)
3659 throw (SALOME::SALOME_Exception)
3662 SMESH::SMESH_Mesh_var mesh;
3663 SMESH_Mesh_i* mesh_i;
3665 { // open new scope to dump "MakeMesh" command
3666 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3668 TPythonDump pydump; // to prevent dump at mesh creation
3670 mesh = makeMesh( theMeshName );
3671 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3673 if ( mesh_i && theIDsOfElements.length() > 0 )
3675 TIDSortedElemSet elements;
3676 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3677 rotate(elements, theAxis, theAngleInRadians,
3678 false, theCopyGroups, & mesh_i->GetImpl());
3679 mesh_i->CreateGroupServants();
3681 if ( !myIsPreviewMode ) {
3682 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3683 << theIDsOfElements << ", "
3685 << TVar( theAngleInRadians ) << ", "
3686 << theCopyGroups << ", '"
3687 << theMeshName << "' )";
3692 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3693 mesh_i->GetGroups();
3695 return mesh._retn();
3697 SMESH_CATCH( SMESH::throwCorbaException );
3701 //=======================================================================
3702 //function : RotateObjectMakeMesh
3704 //=======================================================================
3706 SMESH::SMESH_Mesh_ptr
3707 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3708 const SMESH::AxisStruct& theAxis,
3709 CORBA::Double theAngleInRadians,
3710 CORBA::Boolean theCopyGroups,
3711 const char* theMeshName)
3712 throw (SALOME::SALOME_Exception)
3715 SMESH::SMESH_Mesh_var mesh;
3716 SMESH_Mesh_i* mesh_i;
3718 {// open new scope to dump "MakeMesh" command
3719 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3721 TPythonDump pydump; // to prevent dump at mesh creation
3722 mesh = makeMesh( theMeshName );
3723 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3725 TIDSortedElemSet elements;
3727 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3729 rotate(elements, theAxis, theAngleInRadians,
3730 false, theCopyGroups, & mesh_i->GetImpl());
3731 mesh_i->CreateGroupServants();
3733 if ( !myIsPreviewMode ) {
3734 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3735 << theObject << ", "
3737 << TVar( theAngleInRadians ) << ", "
3738 << theCopyGroups << ", '"
3739 << theMeshName << "' )";
3744 if (!myIsPreviewMode && mesh_i)
3745 mesh_i->GetGroups();
3747 return mesh._retn();
3749 SMESH_CATCH( SMESH::throwCorbaException );
3753 //=======================================================================
3756 //=======================================================================
3758 SMESH::ListOfGroups*
3759 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3760 const SMESH::PointStruct& thePoint,
3761 const SMESH::double_array& theScaleFact,
3762 CORBA::Boolean theCopy,
3764 ::SMESH_Mesh* theTargetMesh)
3765 throw (SALOME::SALOME_Exception)
3769 if ( theScaleFact.length() < 1 )
3770 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3771 if ( theScaleFact.length() == 2 )
3772 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3774 if ( theTargetMesh )
3777 TIDSortedElemSet elements;
3778 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3779 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3784 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3785 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3787 double tol = std::numeric_limits<double>::max();
3790 #if OCC_VERSION_LARGE > 0x06070100
3791 // fight against ortagonalization
3792 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3793 // 0, S[1], 0, thePoint.y * (1-S[1]),
3794 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3795 aTrsf.SetTranslation( gp_Vec( thePoint.x * (1-S[0]),
3796 thePoint.y * (1-S[1]),
3797 thePoint.z * (1-S[2])));
3798 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3799 M.SetDiagonal( S[0], S[1], S[2] );
3802 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3803 0, S[1], 0, thePoint.y * (1-S[1]),
3804 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3807 TIDSortedElemSet copyElements;
3808 TIDSortedElemSet* workElements = &elements;
3809 if ( myIsPreviewMode )
3811 TPreviewMesh * tmpMesh = getPreviewMesh();
3812 tmpMesh->Copy( elements, copyElements);
3813 if ( !theCopy && !theTargetMesh )
3815 TIDSortedElemSet elemsAround, elemsAroundCopy;
3816 getElementsAround( elements, getMeshDS(), elemsAround );
3817 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3819 workElements = & copyElements;
3820 theMakeGroups = false;
3823 ::SMESH_MeshEditor::PGroupIDs groupIds =
3824 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3826 if ( theCopy && !myIsPreviewMode )
3828 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3829 else declareMeshModified( /*isReComputeSafe=*/false );
3831 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3833 SMESH_CATCH( SMESH::throwCorbaException );
3837 //=======================================================================
3840 //=======================================================================
3842 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3843 const SMESH::PointStruct& thePoint,
3844 const SMESH::double_array& theScaleFact,
3845 CORBA::Boolean theCopy)
3846 throw (SALOME::SALOME_Exception)
3848 if ( !myIsPreviewMode ) {
3849 TPythonDump() << this << ".Scale( "
3850 << theObject << ", "
3852 << TVar( theScaleFact ) << ", "
3855 scale(theObject, thePoint, theScaleFact, theCopy, false);
3859 //=======================================================================
3860 //function : ScaleMakeGroups
3862 //=======================================================================
3864 SMESH::ListOfGroups*
3865 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3866 const SMESH::PointStruct& thePoint,
3867 const SMESH::double_array& theScaleFact)
3868 throw (SALOME::SALOME_Exception)
3870 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3872 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3873 if (!myIsPreviewMode) {
3874 dumpGroupsList(aPythonDump, aGroups);
3875 aPythonDump << this << ".Scale("
3878 << TVar( theScaleFact ) << ",True,True)";
3884 //=======================================================================
3885 //function : ScaleMakeMesh
3887 //=======================================================================
3889 SMESH::SMESH_Mesh_ptr
3890 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3891 const SMESH::PointStruct& thePoint,
3892 const SMESH::double_array& theScaleFact,
3893 CORBA::Boolean theCopyGroups,
3894 const char* theMeshName)
3895 throw (SALOME::SALOME_Exception)
3897 SMESH_Mesh_i* mesh_i;
3898 SMESH::SMESH_Mesh_var mesh;
3899 { // open new scope to dump "MakeMesh" command
3900 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3902 TPythonDump pydump; // to prevent dump at mesh creation
3903 mesh = makeMesh( theMeshName );
3904 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3908 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3909 mesh_i->CreateGroupServants();
3911 if ( !myIsPreviewMode )
3912 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3913 << theObject << ", "
3915 << TVar( theScaleFact ) << ", "
3916 << theCopyGroups << ", '"
3917 << theMeshName << "' )";
3921 if (!myIsPreviewMode && mesh_i)
3922 mesh_i->GetGroups();
3924 return mesh._retn();
3928 //=======================================================================
3929 //function : FindCoincidentNodes
3931 //=======================================================================
3933 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tolerance,
3934 SMESH::array_of_long_array_out GroupsOfNodes)
3935 throw (SALOME::SALOME_Exception)
3940 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3941 TIDSortedNodeSet nodes; // no input nodes
3942 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3944 GroupsOfNodes = new SMESH::array_of_long_array;
3945 GroupsOfNodes->length( aListOfListOfNodes.size() );
3946 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3947 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3948 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3949 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3950 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3951 aGroup.length( aListOfNodes.size() );
3952 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3953 aGroup[ j ] = (*lIt)->GetID();
3955 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3956 << Tolerance << " )";
3958 SMESH_CATCH( SMESH::throwCorbaException );
3961 //=======================================================================
3962 //function : FindCoincidentNodesOnPart
3964 //=======================================================================
3966 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
3967 CORBA::Double Tolerance,
3968 SMESH::array_of_long_array_out GroupsOfNodes)
3969 throw (SALOME::SALOME_Exception)
3974 TIDSortedNodeSet nodes;
3975 idSourceToNodeSet( theObject, getMeshDS(), nodes );
3977 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3979 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3981 GroupsOfNodes = new SMESH::array_of_long_array;
3982 GroupsOfNodes->length( aListOfListOfNodes.size() );
3983 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3984 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3986 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3987 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3988 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3989 aGroup.length( aListOfNodes.size() );
3990 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3991 aGroup[ j ] = (*lIt)->GetID();
3993 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
3995 << Tolerance << " )";
3997 SMESH_CATCH( SMESH::throwCorbaException );
4000 //================================================================================
4002 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4003 * ExceptSubMeshOrGroups
4005 //================================================================================
4007 void SMESH_MeshEditor_i::
4008 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4009 CORBA::Double theTolerance,
4010 SMESH::array_of_long_array_out theGroupsOfNodes,
4011 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups)
4012 throw (SALOME::SALOME_Exception)
4017 TIDSortedNodeSet nodes;
4018 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4020 for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4022 TIDSortedNodeSet exceptNodes;
4023 idSourceToNodeSet( theExceptSubMeshOrGroups[i], getMeshDS(), exceptNodes );
4024 TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
4025 for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
4026 nodes.erase( *avoidNode );
4028 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4030 getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
4032 theGroupsOfNodes = new SMESH::array_of_long_array;
4033 theGroupsOfNodes->length( aListOfListOfNodes.size() );
4034 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4035 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4037 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4038 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4039 SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
4040 aGroup.length( aListOfNodes.size() );
4041 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4042 aGroup[ j ] = (*lIt)->GetID();
4044 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4046 << theTolerance << ", "
4047 << theExceptSubMeshOrGroups << " )";
4049 SMESH_CATCH( SMESH::throwCorbaException );
4052 //=======================================================================
4053 //function : MergeNodes
4055 //=======================================================================
4057 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
4058 throw (SALOME::SALOME_Exception)
4063 SMESHDS_Mesh* aMesh = getMeshDS();
4065 TPythonDump aTPythonDump;
4066 aTPythonDump << this << ".MergeNodes([";
4067 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4068 for (int i = 0; i < GroupsOfNodes.length(); i++)
4070 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4071 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4072 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4073 for ( int j = 0; j < aNodeGroup.length(); j++ )
4075 CORBA::Long index = aNodeGroup[ j ];
4076 const SMDS_MeshNode * node = aMesh->FindNode(index);
4078 aListOfNodes.push_back( node );
4080 if ( aListOfNodes.size() < 2 )
4081 aListOfListOfNodes.pop_back();
4083 if ( i > 0 ) aTPythonDump << ", ";
4084 aTPythonDump << aNodeGroup;
4086 getEditor().MergeNodes( aListOfListOfNodes );
4088 aTPythonDump << "])";
4090 declareMeshModified( /*isReComputeSafe=*/false );
4092 SMESH_CATCH( SMESH::throwCorbaException );
4095 //=======================================================================
4096 //function : FindEqualElements
4098 //=======================================================================
4100 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4101 SMESH::array_of_long_array_out GroupsOfElementsID)
4102 throw (SALOME::SALOME_Exception)
4107 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4108 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4110 TIDSortedElemSet elems;
4111 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4113 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4114 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4116 GroupsOfElementsID = new SMESH::array_of_long_array;
4117 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4119 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4120 aListOfListOfElementsID.begin();
4121 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4123 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4124 list<int>& listOfIDs = *arraysIt;
4125 aGroup.length( listOfIDs.size() );
4126 list<int>::iterator idIt = listOfIDs.begin();
4127 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4128 aGroup[ k ] = *idIt;
4131 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4135 SMESH_CATCH( SMESH::throwCorbaException );
4138 //=======================================================================
4139 //function : MergeElements
4141 //=======================================================================
4143 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4144 throw (SALOME::SALOME_Exception)
4149 TPythonDump aTPythonDump;
4150 aTPythonDump << this << ".MergeElements( [";
4152 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4154 for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4155 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4156 aListOfListOfElementsID.push_back( list< int >() );
4157 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4158 for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4159 CORBA::Long id = anElemsIDGroup[ j ];
4160 aListOfElemsID.push_back( id );
4162 if ( aListOfElemsID.size() < 2 )
4163 aListOfListOfElementsID.pop_back();
4164 if ( i > 0 ) aTPythonDump << ", ";
4165 aTPythonDump << anElemsIDGroup;
4168 getEditor().MergeElements(aListOfListOfElementsID);
4170 declareMeshModified( /*isReComputeSafe=*/true );
4172 aTPythonDump << "] )";
4174 SMESH_CATCH( SMESH::throwCorbaException );
4177 //=======================================================================
4178 //function : MergeEqualElements
4180 //=======================================================================
4182 void SMESH_MeshEditor_i::MergeEqualElements()
4183 throw (SALOME::SALOME_Exception)
4188 getEditor().MergeEqualElements();
4190 declareMeshModified( /*isReComputeSafe=*/true );
4192 TPythonDump() << this << ".MergeEqualElements()";
4194 SMESH_CATCH( SMESH::throwCorbaException );
4197 //=============================================================================
4199 * Move the node to a given point
4201 //=============================================================================
4203 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4207 throw (SALOME::SALOME_Exception)
4210 initData(/*deleteSearchers=*/false);
4212 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4216 if ( theNodeSearcher )
4217 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4219 if ( myIsPreviewMode ) // make preview data
4221 // in a preview mesh, make edges linked to a node
4222 TPreviewMesh& tmpMesh = *getPreviewMesh();
4223 TIDSortedElemSet linkedNodes;
4224 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4225 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4226 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4227 for ( ; nIt != linkedNodes.end(); ++nIt )
4229 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4230 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4234 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4235 // fill preview data
4237 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4238 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4240 getMeshDS()->MoveNode(node, x, y, z);
4242 if ( !myIsPreviewMode )
4244 // Update Python script
4245 TPythonDump() << "isDone = " << this << ".MoveNode( "
4246 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4247 declareMeshModified( /*isReComputeSafe=*/false );
4250 SMESH_CATCH( SMESH::throwCorbaException );
4255 //================================================================================
4257 * \brief Return ID of node closest to a given point
4259 //================================================================================
4261 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4264 throw (SALOME::SALOME_Exception)
4267 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4269 if ( !theNodeSearcher ) {
4270 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4273 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4274 return node->GetID();
4276 SMESH_CATCH( SMESH::throwCorbaException );
4280 //================================================================================
4282 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4283 * move the node closest to the point to point's location and return ID of the node
4285 //================================================================================
4287 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4290 CORBA::Long theNodeID)
4291 throw (SALOME::SALOME_Exception)
4294 // We keep theNodeSearcher until any mesh modification:
4295 // 1) initData() deletes theNodeSearcher at any edition,
4296 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4298 initData(/*deleteSearchers=*/false);
4300 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4302 int nodeID = theNodeID;
4303 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4304 if ( !node ) // preview moving node
4306 if ( !theNodeSearcher ) {
4307 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4310 node = theNodeSearcher->FindClosestTo( p );
4313 nodeID = node->GetID();
4314 if ( myIsPreviewMode ) // make preview data
4316 // in a preview mesh, make edges linked to a node
4317 TPreviewMesh tmpMesh = *getPreviewMesh();
4318 TIDSortedElemSet linkedNodes;
4319 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4320 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4321 for ( ; nIt != linkedNodes.end(); ++nIt )
4323 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4324 tmpMesh.Copy( &edge );
4327 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4329 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4330 // fill preview data
4332 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4334 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4338 getMeshDS()->MoveNode(node, x, y, z);
4342 if ( !myIsPreviewMode )
4344 TPythonDump() << "nodeID = " << this
4345 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4346 << ", " << nodeID << " )";
4348 declareMeshModified( /*isReComputeSafe=*/false );
4353 SMESH_CATCH( SMESH::throwCorbaException );
4357 //=======================================================================
4359 * Return elements of given type where the given point is IN or ON.
4361 * 'ALL' type means elements of any type excluding nodes
4363 //=======================================================================
4365 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4368 SMESH::ElementType type)
4369 throw (SALOME::SALOME_Exception)
4372 SMESH::long_array_var res = new SMESH::long_array;
4373 vector< const SMDS_MeshElement* > foundElems;
4375 theSearchersDeleter.Set( myMesh );
4376 if ( !theElementSearcher ) {
4377 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4379 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4380 SMDSAbs_ElementType( type ),
4382 res->length( foundElems.size() );
4383 for ( int i = 0; i < foundElems.size(); ++i )
4384 res[i] = foundElems[i]->GetID();
4388 SMESH_CATCH( SMESH::throwCorbaException );
4392 //=======================================================================
4393 //function : FindAmongElementsByPoint
4394 //purpose : Searching among the given elements, return elements of given type
4395 // where the given point is IN or ON.
4396 // 'ALL' type means elements of any type excluding nodes
4397 //=======================================================================
4400 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4404 SMESH::ElementType type)
4405 throw (SALOME::SALOME_Exception)
4408 SMESH::long_array_var res = new SMESH::long_array;
4410 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4411 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4412 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4413 type != types[0] ) // but search of elements of dim > 0
4416 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4417 return FindElementsByPoint( x,y,z, type );
4419 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4421 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4422 if ( !theElementSearcher )
4424 // create a searcher from elementIDs
4425 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4426 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4428 if ( !idSourceToSet( elementIDs, meshDS, elements,
4429 SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4432 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4433 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4435 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4438 vector< const SMDS_MeshElement* > foundElems;
4440 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4441 SMDSAbs_ElementType( type ),
4443 res->length( foundElems.size() );
4444 for ( int i = 0; i < foundElems.size(); ++i )
4445 res[i] = foundElems[i]->GetID();
4449 SMESH_CATCH( SMESH::throwCorbaException );
4453 //=======================================================================
4454 //function : GetPointState
4455 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4456 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4457 //=======================================================================
4459 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4462 throw (SALOME::SALOME_Exception)
4465 theSearchersDeleter.Set( myMesh );
4466 if ( !theElementSearcher ) {
4467 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4469 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4471 SMESH_CATCH( SMESH::throwCorbaException );
4475 //=======================================================================
4476 //function : convError
4478 //=======================================================================
4480 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4482 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4486 RETCASE( SEW_BORDER1_NOT_FOUND );
4487 RETCASE( SEW_BORDER2_NOT_FOUND );
4488 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4489 RETCASE( SEW_BAD_SIDE_NODES );
4490 RETCASE( SEW_VOLUMES_TO_SPLIT );
4491 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4492 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4493 RETCASE( SEW_BAD_SIDE1_NODES );
4494 RETCASE( SEW_BAD_SIDE2_NODES );
4496 return SMESH::SMESH_MeshEditor::SEW_OK;
4499 //=======================================================================
4500 //function : SewFreeBorders
4502 //=======================================================================
4504 SMESH::SMESH_MeshEditor::Sew_Error
4505 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4506 CORBA::Long SecondNodeID1,
4507 CORBA::Long LastNodeID1,
4508 CORBA::Long FirstNodeID2,
4509 CORBA::Long SecondNodeID2,
4510 CORBA::Long LastNodeID2,
4511 CORBA::Boolean CreatePolygons,
4512 CORBA::Boolean CreatePolyedrs)
4513 throw (SALOME::SALOME_Exception)
4518 SMESHDS_Mesh* aMesh = getMeshDS();
4520 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4521 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4522 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4523 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4524 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4525 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4527 if (!aBorderFirstNode ||
4528 !aBorderSecondNode||
4530 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4531 if (!aSide2FirstNode ||
4532 !aSide2SecondNode ||
4534 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4536 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4537 << FirstNodeID1 << ", "
4538 << SecondNodeID1 << ", "
4539 << LastNodeID1 << ", "
4540 << FirstNodeID2 << ", "
4541 << SecondNodeID2 << ", "
4542 << LastNodeID2 << ", "
4543 << CreatePolygons<< ", "
4544 << CreatePolyedrs<< " )";
4546 SMESH::SMESH_MeshEditor::Sew_Error error =
4547 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4558 declareMeshModified( /*isReComputeSafe=*/false );
4561 SMESH_CATCH( SMESH::throwCorbaException );
4562 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4566 //=======================================================================
4567 //function : SewConformFreeBorders
4569 //=======================================================================
4571 SMESH::SMESH_MeshEditor::Sew_Error
4572 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4573 CORBA::Long SecondNodeID1,
4574 CORBA::Long LastNodeID1,
4575 CORBA::Long FirstNodeID2,
4576 CORBA::Long SecondNodeID2)
4577 throw (SALOME::SALOME_Exception)
4582 SMESHDS_Mesh* aMesh = getMeshDS();
4584 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4585 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4586 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4587 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4588 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4589 const SMDS_MeshNode* aSide2ThirdNode = 0;
4591 if (!aBorderFirstNode ||
4592 !aBorderSecondNode||
4594 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4595 if (!aSide2FirstNode ||
4597 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4599 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4600 << FirstNodeID1 << ", "
4601 << SecondNodeID1 << ", "
4602 << LastNodeID1 << ", "
4603 << FirstNodeID2 << ", "
4604 << SecondNodeID2 << " )";
4606 SMESH::SMESH_MeshEditor::Sew_Error error =
4607 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4616 declareMeshModified( /*isReComputeSafe=*/false );
4619 SMESH_CATCH( SMESH::throwCorbaException );
4620 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4624 //=======================================================================
4625 //function : SewBorderToSide
4627 //=======================================================================
4629 SMESH::SMESH_MeshEditor::Sew_Error
4630 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4631 CORBA::Long SecondNodeIDOnFreeBorder,
4632 CORBA::Long LastNodeIDOnFreeBorder,
4633 CORBA::Long FirstNodeIDOnSide,
4634 CORBA::Long LastNodeIDOnSide,
4635 CORBA::Boolean CreatePolygons,
4636 CORBA::Boolean CreatePolyedrs)
4637 throw (SALOME::SALOME_Exception)
4642 SMESHDS_Mesh* aMesh = getMeshDS();
4644 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4645 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4646 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4647 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4648 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4649 const SMDS_MeshNode* aSide2ThirdNode = 0;
4651 if (!aBorderFirstNode ||
4652 !aBorderSecondNode||
4654 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4655 if (!aSide2FirstNode ||
4657 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4659 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4660 << FirstNodeIDOnFreeBorder << ", "
4661 << SecondNodeIDOnFreeBorder << ", "
4662 << LastNodeIDOnFreeBorder << ", "
4663 << FirstNodeIDOnSide << ", "
4664 << LastNodeIDOnSide << ", "
4665 << CreatePolygons << ", "
4666 << CreatePolyedrs << ") ";
4668 SMESH::SMESH_MeshEditor::Sew_Error error =
4669 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4679 declareMeshModified( /*isReComputeSafe=*/false );
4682 SMESH_CATCH( SMESH::throwCorbaException );
4683 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4687 //=======================================================================
4688 //function : SewSideElements
4690 //=======================================================================
4692 SMESH::SMESH_MeshEditor::Sew_Error
4693 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4694 const SMESH::long_array& IDsOfSide2Elements,
4695 CORBA::Long NodeID1OfSide1ToMerge,
4696 CORBA::Long NodeID1OfSide2ToMerge,
4697 CORBA::Long NodeID2OfSide1ToMerge,
4698 CORBA::Long NodeID2OfSide2ToMerge)
4699 throw (SALOME::SALOME_Exception)
4704 SMESHDS_Mesh* aMesh = getMeshDS();
4706 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
4707 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
4708 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4709 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4711 if (!aFirstNode1ToMerge ||
4712 !aFirstNode2ToMerge )
4713 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4714 if (!aSecondNode1ToMerge||
4715 !aSecondNode2ToMerge)
4716 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4718 TIDSortedElemSet aSide1Elems, aSide2Elems;
4719 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4720 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4722 TPythonDump() << "error = " << this << ".SewSideElements( "
4723 << IDsOfSide1Elements << ", "
4724 << IDsOfSide2Elements << ", "
4725 << NodeID1OfSide1ToMerge << ", "
4726 << NodeID1OfSide2ToMerge << ", "
4727 << NodeID2OfSide1ToMerge << ", "
4728 << NodeID2OfSide2ToMerge << ")";
4730 SMESH::SMESH_MeshEditor::Sew_Error error =
4731 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
4734 aSecondNode1ToMerge,
4735 aSecondNode2ToMerge));
4737 declareMeshModified( /*isReComputeSafe=*/false );
4740 SMESH_CATCH( SMESH::throwCorbaException );
4741 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4744 //================================================================================
4746 * \brief Set new nodes for given element
4747 * \param ide - element id
4748 * \param newIDs - new node ids
4749 * \retval CORBA::Boolean - true if result is OK
4751 //================================================================================
4753 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4754 const SMESH::long_array& newIDs)
4755 throw (SALOME::SALOME_Exception)
4760 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
4761 if(!elem) return false;
4763 int nbn = newIDs.length();
4765 vector<const SMDS_MeshNode*> aNodes(nbn);
4768 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
4771 aNodes[nbn1] = aNode;
4774 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4775 << ide << ", " << newIDs << " )";
4777 MESSAGE("ChangeElementNodes");
4778 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4780 declareMeshModified( /*isReComputeSafe=*/ !res );
4784 SMESH_CATCH( SMESH::throwCorbaException );
4788 //=======================================================================
4790 * \brief Makes a part of the mesh quadratic or bi-quadratic
4792 //=======================================================================
4794 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
4795 CORBA::Boolean theToBiQuad,
4796 SMESH::SMESH_IDSource_ptr theObject)
4797 throw (SALOME::SALOME_Exception)
4802 TIDSortedElemSet elems;
4804 if ( !( elemsOK = CORBA::is_nil( theObject )))
4806 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
4807 SMDSAbs_All, /*emptyIfIsMesh=*/true );
4811 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
4812 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4814 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
4815 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
4817 declareMeshModified( /*isReComputeSafe=*/false );
4820 SMESH_CATCH( SMESH::throwCorbaException );
4823 //=======================================================================
4824 //function : ConvertFromQuadratic
4826 //=======================================================================
4828 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4829 throw (SALOME::SALOME_Exception)
4834 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
4835 TPythonDump() << this << ".ConvertFromQuadratic()";
4836 declareMeshModified( /*isReComputeSafe=*/!isDone );
4839 SMESH_CATCH( SMESH::throwCorbaException );
4843 //=======================================================================
4844 //function : ConvertToQuadratic
4846 //=======================================================================
4848 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4849 throw (SALOME::SALOME_Exception)
4851 convertToQuadratic( theForce3d, false );
4852 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
4855 //================================================================================
4857 * \brief Makes a part of the mesh quadratic
4859 //================================================================================
4861 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
4862 SMESH::SMESH_IDSource_ptr theObject)
4863 throw (SALOME::SALOME_Exception)
4865 convertToQuadratic( theForce3d, false, theObject );
4866 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
4869 //================================================================================
4871 * \brief Makes a part of the mesh bi-quadratic
4873 //================================================================================
4875 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
4876 SMESH::SMESH_IDSource_ptr theObject)
4877 throw (SALOME::SALOME_Exception)
4879 convertToQuadratic( theForce3d, true, theObject );
4880 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
4883 //================================================================================
4885 * \brief Makes a part of the mesh linear
4887 //================================================================================
4889 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
4890 throw (SALOME::SALOME_Exception)
4897 TIDSortedElemSet elems;
4898 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
4900 if ( elems.empty() )
4902 ConvertFromQuadratic();
4904 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
4906 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4910 getEditor().ConvertFromQuadratic(elems);
4913 declareMeshModified( /*isReComputeSafe=*/false );
4915 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
4917 SMESH_CATCH( SMESH::throwCorbaException );
4920 //=======================================================================
4921 //function : makeMesh
4922 //purpose : create a named imported mesh
4923 //=======================================================================
4925 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4927 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4928 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4929 SALOMEDS::Study_var study = gen->GetCurrentStudy();
4930 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
4931 gen->SetName( meshSO, theMeshName, "Mesh" );
4932 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4934 return mesh._retn();
4937 //=======================================================================
4938 //function : dumpGroupsList
4940 //=======================================================================
4942 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
4943 const SMESH::ListOfGroups * theGroupList)
4945 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
4946 if ( isDumpGroupList )
4947 theDumpPython << theGroupList << " = ";
4950 //================================================================================
4952 \brief Generates the unique group name.
4953 \param thePrefix name prefix
4956 //================================================================================
4958 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
4960 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4961 set<string> groupNames;
4963 // Get existing group names
4964 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
4965 SMESH::SMESH_GroupBase_var aGroup = groups[i];
4966 if (CORBA::is_nil(aGroup))
4969 CORBA::String_var name = aGroup->GetName();
4970 groupNames.insert( name.in() );
4974 string name = thePrefix;
4977 while (!groupNames.insert(name).second)
4978 name = SMESH_Comment( thePrefix ) << "_" << index++;
4983 //================================================================================
4985 * \brief Prepare SMESH_IDSource for work
4987 //================================================================================
4989 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
4991 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
4993 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
4994 filter->SetMesh( mesh );
4997 //================================================================================
4999 * \brief Retrieve elements of given type from SMESH_IDSource
5001 //================================================================================
5003 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5004 const SMESHDS_Mesh* theMeshDS,
5005 TIDSortedElemSet& theElemSet,
5006 const SMDSAbs_ElementType theType,
5007 const bool emptyIfIsMesh,
5008 IDSource_Error* error)
5011 if ( error ) *error = IDSource_OK;
5013 if ( CORBA::is_nil( theIDSource ) )
5015 if ( error ) *error = IDSource_INVALID;
5018 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5020 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5021 *error = IDSource_EMPTY;
5024 prepareIdSource( theIDSource );
5025 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5026 if ( anIDs->length() == 0 )
5028 if ( error ) *error = IDSource_EMPTY;
5031 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5032 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5034 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5036 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5040 if ( error ) *error = IDSource_INVALID;
5046 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5047 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5049 if ( error ) *error = IDSource_INVALID;
5056 //================================================================================
5058 * \brief Duplicates given elements, i.e. creates new elements based on the
5059 * same nodes as the given ones.
5060 * \param theElements - container of elements to duplicate.
5061 * \param theGroupName - a name of group to contain the generated elements.
5062 * If a group with such a name already exists, the new elements
5063 * are added to the existng group, else a new group is created.
5064 * If \a theGroupName is empty, new elements are not added
5066 * \return a group where the new elements are added. NULL if theGroupName == "".
5069 //================================================================================
5071 SMESH::SMESH_Group_ptr
5072 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5073 const char* theGroupName)
5074 throw (SALOME::SALOME_Exception)
5076 SMESH::SMESH_Group_var newGroup;
5083 TIDSortedElemSet elems;
5084 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5086 getEditor().DoubleElements( elems );
5088 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5091 SMESH::ElementType type =
5092 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5093 // find existing group
5094 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5095 for ( size_t i = 0; i < groups->length(); ++i )
5096 if ( groups[i]->GetType() == type )
5098 CORBA::String_var name = groups[i]->GetName();
5099 if ( strcmp( name, theGroupName ) == 0 ) {
5100 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5104 // create a new group
5105 if ( newGroup->_is_nil() )
5106 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5108 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5110 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5111 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5112 for ( int i = 1; i <= aSeq.Length(); i++ )
5113 groupDS->SMDSGroup().Add( aSeq(i) );
5118 if ( !newGroup->_is_nil() )
5119 pyDump << newGroup << " = ";
5120 pyDump << this << ".DoubleElements( "
5121 << theElements << ", " << "'" << theGroupName <<"')";
5123 SMESH_CATCH( SMESH::throwCorbaException );
5125 return newGroup._retn();
5128 //================================================================================
5130 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5131 \param theNodes - identifiers of nodes to be doubled
5132 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5133 nodes. If list of element identifiers is empty then nodes are doubled but
5134 they not assigned to elements
5135 \return TRUE if operation has been completed successfully, FALSE otherwise
5136 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5138 //================================================================================
5140 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5141 const SMESH::long_array& theModifiedElems )
5142 throw (SALOME::SALOME_Exception)
5147 list< int > aListOfNodes;
5149 for ( i = 0, n = theNodes.length(); i < n; i++ )
5150 aListOfNodes.push_back( theNodes[ i ] );
5152 list< int > aListOfElems;
5153 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5154 aListOfElems.push_back( theModifiedElems[ i ] );
5156 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5158 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5160 // Update Python script
5161 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5165 SMESH_CATCH( SMESH::throwCorbaException );
5169 //================================================================================
5171 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5172 This method provided for convenience works as DoubleNodes() described above.
5173 \param theNodeId - identifier of node to be doubled.
5174 \param theModifiedElems - identifiers of elements to be updated.
5175 \return TRUE if operation has been completed successfully, FALSE otherwise
5176 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5178 //================================================================================
5180 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5181 const SMESH::long_array& theModifiedElems )
5182 throw (SALOME::SALOME_Exception)
5185 SMESH::long_array_var aNodes = new SMESH::long_array;
5186 aNodes->length( 1 );
5187 aNodes[ 0 ] = theNodeId;
5189 TPythonDump pyDump; // suppress dump by the next line
5191 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5193 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5197 SMESH_CATCH( SMESH::throwCorbaException );
5201 //================================================================================
5203 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5204 This method provided for convenience works as DoubleNodes() described above.
5205 \param theNodes - group of nodes to be doubled.
5206 \param theModifiedElems - group of elements to be updated.
5207 \return TRUE if operation has been completed successfully, FALSE otherwise
5208 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5210 //================================================================================
5212 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5213 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5214 throw (SALOME::SALOME_Exception)
5217 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5220 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5221 SMESH::long_array_var aModifiedElems;
5222 if ( !CORBA::is_nil( theModifiedElems ) )
5223 aModifiedElems = theModifiedElems->GetListOfID();
5226 aModifiedElems = new SMESH::long_array;
5227 aModifiedElems->length( 0 );
5230 TPythonDump pyDump; // suppress dump by the next line
5232 bool done = DoubleNodes( aNodes, aModifiedElems );
5234 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5238 SMESH_CATCH( SMESH::throwCorbaException );
5242 //================================================================================
5244 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5245 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5246 * \param theNodes - group of nodes to be doubled.
5247 * \param theModifiedElems - group of elements to be updated.
5248 * \return a new group with newly created nodes
5249 * \sa DoubleNodeGroup()
5251 //================================================================================
5253 SMESH::SMESH_Group_ptr
5254 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5255 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5256 throw (SALOME::SALOME_Exception)
5259 SMESH::SMESH_Group_var aNewGroup;
5261 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5262 return aNewGroup._retn();
5265 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5266 SMESH::long_array_var aModifiedElems;
5267 if ( !CORBA::is_nil( theModifiedElems ) )
5268 aModifiedElems = theModifiedElems->GetListOfID();
5270 aModifiedElems = new SMESH::long_array;
5271 aModifiedElems->length( 0 );
5274 TPythonDump pyDump; // suppress dump by the next line
5276 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5279 // Create group with newly created nodes
5280 SMESH::long_array_var anIds = GetLastCreatedNodes();
5281 if (anIds->length() > 0) {
5282 string anUnindexedName (theNodes->GetName());
5283 string aNewName = generateGroupName(anUnindexedName + "_double");
5284 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5285 aNewGroup->Add(anIds);
5286 pyDump << aNewGroup << " = ";
5290 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5291 << theModifiedElems << " )";
5293 return aNewGroup._retn();
5295 SMESH_CATCH( SMESH::throwCorbaException );
5299 //================================================================================
5301 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5302 This method provided for convenience works as DoubleNodes() described above.
5303 \param theNodes - list of groups of nodes to be doubled
5304 \param theModifiedElems - list of groups of elements to be updated.
5305 \return TRUE if operation has been completed successfully, FALSE otherwise
5306 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5308 //================================================================================
5310 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5311 const SMESH::ListOfGroups& theModifiedElems )
5312 throw (SALOME::SALOME_Exception)
5317 std::list< int > aNodes;
5319 for ( i = 0, n = theNodes.length(); i < n; i++ )
5321 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5322 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5324 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5325 for ( j = 0, m = aCurr->length(); j < m; j++ )
5326 aNodes.push_back( aCurr[ j ] );
5330 std::list< int > anElems;
5331 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5333 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5334 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5336 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5337 for ( j = 0, m = aCurr->length(); j < m; j++ )
5338 anElems.push_back( aCurr[ j ] );
5342 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5344 declareMeshModified( /*isReComputeSafe=*/false );
5346 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5350 SMESH_CATCH( SMESH::throwCorbaException );
5354 //================================================================================
5356 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5357 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5358 * \param theNodes - group of nodes to be doubled.
5359 * \param theModifiedElems - group of elements to be updated.
5360 * \return a new group with newly created nodes
5361 * \sa DoubleNodeGroups()
5363 //================================================================================
5365 SMESH::SMESH_Group_ptr
5366 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5367 const SMESH::ListOfGroups& theModifiedElems )
5368 throw (SALOME::SALOME_Exception)
5370 SMESH::SMESH_Group_var aNewGroup;
5372 TPythonDump pyDump; // suppress dump by the next line
5374 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5378 // Create group with newly created nodes
5379 SMESH::long_array_var anIds = GetLastCreatedNodes();
5380 if (anIds->length() > 0) {
5381 string anUnindexedName (theNodes[0]->GetName());
5382 string aNewName = generateGroupName(anUnindexedName + "_double");
5383 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5384 aNewGroup->Add(anIds);
5385 pyDump << aNewGroup << " = ";
5389 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5390 << theModifiedElems << " )";
5392 return aNewGroup._retn();
5396 //================================================================================
5398 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5399 \param theElems - the list of elements (edges or faces) to be replicated
5400 The nodes for duplication could be found from these elements
5401 \param theNodesNot - list of nodes to NOT replicate
5402 \param theAffectedElems - the list of elements (cells and edges) to which the
5403 replicated nodes should be associated to.
5404 \return TRUE if operation has been completed successfully, FALSE otherwise
5405 \sa DoubleNodeGroup(), DoubleNodeGroups()
5407 //================================================================================
5409 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5410 const SMESH::long_array& theNodesNot,
5411 const SMESH::long_array& theAffectedElems )
5412 throw (SALOME::SALOME_Exception)
5417 SMESHDS_Mesh* aMeshDS = getMeshDS();
5418 TIDSortedElemSet anElems, aNodes, anAffected;
5419 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5420 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5421 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5423 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5425 // Update Python script
5426 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5427 << theNodesNot << ", " << theAffectedElems << " )";
5429 declareMeshModified( /*isReComputeSafe=*/false );
5432 SMESH_CATCH( SMESH::throwCorbaException );
5436 //================================================================================
5438 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5439 \param theElems - the list of elements (edges or faces) to be replicated
5440 The nodes for duplication could be found from these elements
5441 \param theNodesNot - list of nodes to NOT replicate
5442 \param theShape - shape to detect affected elements (element which geometric center
5443 located on or inside shape).
5444 The replicated nodes should be associated to affected elements.
5445 \return TRUE if operation has been completed successfully, FALSE otherwise
5446 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5448 //================================================================================
5450 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5451 const SMESH::long_array& theNodesNot,
5452 GEOM::GEOM_Object_ptr theShape )
5453 throw (SALOME::SALOME_Exception)
5459 SMESHDS_Mesh* aMeshDS = getMeshDS();
5460 TIDSortedElemSet anElems, aNodes;
5461 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5462 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5464 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5465 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5467 // Update Python script
5468 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5469 << theNodesNot << ", " << theShape << " )";
5471 declareMeshModified( /*isReComputeSafe=*/false );
5474 SMESH_CATCH( SMESH::throwCorbaException );
5478 //================================================================================
5480 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5481 \param theElems - group of of elements (edges or faces) to be replicated
5482 \param theNodesNot - group of nodes not to replicated
5483 \param theAffectedElems - group of elements to which the replicated nodes
5484 should be associated to.
5485 \return TRUE if operation has been completed successfully, FALSE otherwise
5486 \sa DoubleNodes(), DoubleNodeGroups()
5488 //================================================================================
5491 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5492 SMESH::SMESH_GroupBase_ptr theNodesNot,
5493 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5494 throw (SALOME::SALOME_Exception)
5497 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5503 SMESHDS_Mesh* aMeshDS = getMeshDS();
5504 TIDSortedElemSet anElems, aNodes, anAffected;
5505 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5506 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5507 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5509 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5511 // Update Python script
5512 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5513 << theNodesNot << ", " << theAffectedElems << " )";
5515 declareMeshModified( /*isReComputeSafe=*/false );
5518 SMESH_CATCH( SMESH::throwCorbaException );
5522 //================================================================================
5524 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5525 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5526 * \param theElems - group of of elements (edges or faces) to be replicated
5527 * \param theNodesNot - group of nodes not to replicated
5528 * \param theAffectedElems - group of elements to which the replicated nodes
5529 * should be associated to.
5530 * \return a new group with newly created elements
5531 * \sa DoubleNodeElemGroup()
5533 //================================================================================
5535 SMESH::SMESH_Group_ptr
5536 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5537 SMESH::SMESH_GroupBase_ptr theNodesNot,
5538 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5539 throw (SALOME::SALOME_Exception)
5542 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5546 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5547 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5549 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5551 << theNodesNot << ", "
5552 << theAffectedElems << " )";
5554 return elemGroup._retn();
5557 //================================================================================
5559 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5560 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5561 * \param theElems - group of of elements (edges or faces) to be replicated
5562 * \param theNodesNot - group of nodes not to replicated
5563 * \param theAffectedElems - group of elements to which the replicated nodes
5564 * should be associated to.
5565 * \return a new group with newly created elements
5566 * \sa DoubleNodeElemGroup()
5568 //================================================================================
5570 SMESH::ListOfGroups*
5571 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5572 SMESH::SMESH_GroupBase_ptr theNodesNot,
5573 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5574 CORBA::Boolean theElemGroupNeeded,
5575 CORBA::Boolean theNodeGroupNeeded)
5576 throw (SALOME::SALOME_Exception)
5579 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5580 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5581 aTwoGroups->length( 2 );
5583 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5584 return aTwoGroups._retn();
5589 SMESHDS_Mesh* aMeshDS = getMeshDS();
5590 TIDSortedElemSet anElems, aNodes, anAffected;
5591 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5592 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5593 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5596 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5598 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5604 // Create group with newly created elements
5605 CORBA::String_var elemGroupName = theElems->GetName();
5606 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5607 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5609 SMESH::long_array_var anIds = GetLastCreatedElems();
5610 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5611 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5612 aNewElemGroup->Add(anIds);
5614 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5616 SMESH::long_array_var anIds = GetLastCreatedNodes();
5617 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5618 aNewNodeGroup->Add(anIds);
5622 // Update Python script
5625 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5626 else pyDump << aNewElemGroup << ", ";
5627 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5628 else pyDump << aNewNodeGroup << " ] = ";
5630 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5631 << theNodesNot << ", "
5632 << theAffectedElems << ", "
5633 << theElemGroupNeeded << ", "
5634 << theNodeGroupNeeded <<" )";
5636 aTwoGroups[0] = aNewElemGroup._retn();
5637 aTwoGroups[1] = aNewNodeGroup._retn();
5638 return aTwoGroups._retn();
5640 SMESH_CATCH( SMESH::throwCorbaException );
5644 //================================================================================
5646 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5647 \param theElems - group of of elements (edges or faces) to be replicated
5648 \param theNodesNot - group of nodes not to replicated
5649 \param theShape - shape to detect affected elements (element which geometric center
5650 located on or inside shape).
5651 The replicated nodes should be associated to affected elements.
5652 \return TRUE if operation has been completed successfully, FALSE otherwise
5653 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5655 //================================================================================
5658 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5659 SMESH::SMESH_GroupBase_ptr theNodesNot,
5660 GEOM::GEOM_Object_ptr theShape )
5661 throw (SALOME::SALOME_Exception)
5664 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5670 SMESHDS_Mesh* aMeshDS = getMeshDS();
5671 TIDSortedElemSet anElems, aNodes, anAffected;
5672 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5673 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5675 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5676 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5679 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5681 // Update Python script
5682 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5683 << theNodesNot << ", " << theShape << " )";
5686 SMESH_CATCH( SMESH::throwCorbaException );
5690 //================================================================================
5692 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5693 * \param [in] theGrpList - groups
5694 * \param [in] theMeshDS - mesh
5695 * \param [out] theElemSet - set of elements
5696 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5698 //================================================================================
5700 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5701 SMESHDS_Mesh* theMeshDS,
5702 TIDSortedElemSet& theElemSet,
5703 const bool theIsNodeGrp)
5705 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5707 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5708 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5709 : aGrp->GetType() != SMESH::NODE ) )
5711 SMESH::long_array_var anIDs = aGrp->GetIDs();
5712 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5717 //================================================================================
5719 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5720 This method provided for convenience works as DoubleNodes() described above.
5721 \param theElems - list of groups of elements (edges or faces) to be replicated
5722 \param theNodesNot - list of groups of nodes not to replicated
5723 \param theAffectedElems - group of elements to which the replicated nodes
5724 should be associated to.
5725 \return TRUE if operation has been completed successfully, FALSE otherwise
5726 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5728 //================================================================================
5731 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5732 const SMESH::ListOfGroups& theNodesNot,
5733 const SMESH::ListOfGroups& theAffectedElems)
5734 throw (SALOME::SALOME_Exception)
5740 SMESHDS_Mesh* aMeshDS = getMeshDS();
5741 TIDSortedElemSet anElems, aNodes, anAffected;
5742 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5743 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5744 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5746 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5748 // Update Python script
5749 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5750 << &theNodesNot << ", " << &theAffectedElems << " )";
5752 declareMeshModified( /*isReComputeSafe=*/false );
5755 SMESH_CATCH( SMESH::throwCorbaException );
5759 //================================================================================
5761 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5762 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5763 \param theElems - list of groups of elements (edges or faces) to be replicated
5764 \param theNodesNot - list of groups of nodes not to replicated
5765 \param theAffectedElems - group of elements to which the replicated nodes
5766 should be associated to.
5767 * \return a new group with newly created elements
5768 * \sa DoubleNodeElemGroups()
5770 //================================================================================
5772 SMESH::SMESH_Group_ptr
5773 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5774 const SMESH::ListOfGroups& theNodesNot,
5775 const SMESH::ListOfGroups& theAffectedElems)
5776 throw (SALOME::SALOME_Exception)
5779 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
5783 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5784 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5786 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
5788 << theNodesNot << ", "
5789 << theAffectedElems << " )";
5791 return elemGroup._retn();
5794 //================================================================================
5796 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5797 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5798 \param theElems - list of groups of elements (edges or faces) to be replicated
5799 \param theNodesNot - list of groups of nodes not to replicated
5800 \param theAffectedElems - group of elements to which the replicated nodes
5801 should be associated to.
5802 * \return a new group with newly created elements
5803 * \sa DoubleNodeElemGroups()
5805 //================================================================================
5807 SMESH::ListOfGroups*
5808 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
5809 const SMESH::ListOfGroups& theNodesNot,
5810 const SMESH::ListOfGroups& theAffectedElems,
5811 CORBA::Boolean theElemGroupNeeded,
5812 CORBA::Boolean theNodeGroupNeeded)
5813 throw (SALOME::SALOME_Exception)
5816 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5817 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5818 aTwoGroups->length( 2 );
5823 SMESHDS_Mesh* aMeshDS = getMeshDS();
5824 TIDSortedElemSet anElems, aNodes, anAffected;
5825 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5826 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5827 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5829 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5831 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5836 // Create group with newly created elements
5837 CORBA::String_var elemGroupName = theElems[0]->GetName();
5838 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5839 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5841 SMESH::long_array_var anIds = GetLastCreatedElems();
5842 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5843 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5844 aNewElemGroup->Add(anIds);
5846 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5848 SMESH::long_array_var anIds = GetLastCreatedNodes();
5849 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5850 aNewNodeGroup->Add(anIds);
5854 // Update Python script
5857 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5858 else pyDump << aNewElemGroup << ", ";
5859 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5860 else pyDump << aNewNodeGroup << " ] = ";
5862 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
5863 << &theNodesNot << ", "
5864 << &theAffectedElems << ", "
5865 << theElemGroupNeeded << ", "
5866 << theNodeGroupNeeded << " )";
5868 aTwoGroups[0] = aNewElemGroup._retn();
5869 aTwoGroups[1] = aNewNodeGroup._retn();
5870 return aTwoGroups._retn();
5872 SMESH_CATCH( SMESH::throwCorbaException );
5876 //================================================================================
5878 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5879 This method provided for convenience works as DoubleNodes() described above.
5880 \param theElems - list of groups of elements (edges or faces) to be replicated
5881 \param theNodesNot - list of groups of nodes not to replicated
5882 \param theShape - shape to detect affected elements (element which geometric center
5883 located on or inside shape).
5884 The replicated nodes should be associated to affected elements.
5885 \return TRUE if operation has been completed successfully, FALSE otherwise
5886 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5888 //================================================================================
5891 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5892 const SMESH::ListOfGroups& theNodesNot,
5893 GEOM::GEOM_Object_ptr theShape )
5894 throw (SALOME::SALOME_Exception)
5900 SMESHDS_Mesh* aMeshDS = getMeshDS();
5901 TIDSortedElemSet anElems, aNodes;
5902 listOfGroupToSet(theElems, aMeshDS, anElems,false );
5903 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5905 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5906 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5908 // Update Python script
5909 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5910 << &theNodesNot << ", " << theShape << " )";
5912 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5915 SMESH_CATCH( SMESH::throwCorbaException );
5919 //================================================================================
5921 \brief Identify the elements that will be affected by node duplication (actual
5922 duplication is not performed.
5923 This method is the first step of DoubleNodeElemGroupsInRegion.
5924 \param theElems - list of groups of elements (edges or faces) to be replicated
5925 \param theNodesNot - list of groups of nodes not to replicated
5926 \param theShape - shape to detect affected elements (element which geometric center
5927 located on or inside shape).
5928 The replicated nodes should be associated to affected elements.
5929 \return groups of affected elements
5930 \sa DoubleNodeElemGroupsInRegion()
5932 //================================================================================
5933 SMESH::ListOfGroups*
5934 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
5935 const SMESH::ListOfGroups& theNodesNot,
5936 GEOM::GEOM_Object_ptr theShape )
5937 throw (SALOME::SALOME_Exception)
5940 MESSAGE("AffectedElemGroupsInRegion");
5941 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
5942 bool isEdgeGroup = false;
5943 bool isFaceGroup = false;
5944 bool isVolumeGroup = false;
5945 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
5946 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
5947 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
5951 ::SMESH_MeshEditor aMeshEditor(myMesh);
5953 SMESHDS_Mesh* aMeshDS = getMeshDS();
5954 TIDSortedElemSet anElems, aNodes;
5955 listOfGroupToSet(theElems, aMeshDS, anElems, false);
5956 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
5958 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
5959 TIDSortedElemSet anAffected;
5960 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
5963 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5968 int lg = anAffected.size();
5969 MESSAGE("lg="<< lg);
5970 SMESH::long_array_var volumeIds = new SMESH::long_array;
5971 volumeIds->length(lg);
5972 SMESH::long_array_var faceIds = new SMESH::long_array;
5973 faceIds->length(lg);
5974 SMESH::long_array_var edgeIds = new SMESH::long_array;
5975 edgeIds->length(lg);
5980 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
5981 for (; eIt != anAffected.end(); ++eIt)
5983 const SMDS_MeshElement* anElem = *eIt;
5986 int elemId = anElem->GetID();
5987 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
5988 volumeIds[ivol++] = elemId;
5989 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
5990 faceIds[iface++] = elemId;
5991 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
5992 edgeIds[iedge++] = elemId;
5994 volumeIds->length(ivol);
5995 faceIds->length(iface);
5996 edgeIds->length(iedge);
5998 aNewVolumeGroup->Add(volumeIds);
5999 aNewFaceGroup->Add(faceIds);
6000 aNewEdgeGroup->Add(edgeIds);
6001 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6002 isFaceGroup = (aNewFaceGroup->Size() > 0);
6003 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6007 if (isEdgeGroup) nbGroups++;
6008 if (isFaceGroup) nbGroups++;
6009 if (isVolumeGroup) nbGroups++;
6010 aListOfGroups->length(nbGroups);
6013 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6014 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6015 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6017 // Update Python script
6020 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6021 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6022 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6024 pyDump << this << ".AffectedElemGroupsInRegion( "
6025 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6027 return aListOfGroups._retn();
6029 SMESH_CATCH( SMESH::throwCorbaException );
6033 //================================================================================
6035 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6036 The created 2D mesh elements based on nodes of free faces of boundary volumes
6037 \return TRUE if operation has been completed successfully, FALSE otherwise
6039 //================================================================================
6041 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6042 throw (SALOME::SALOME_Exception)
6047 bool aResult = getEditor().Make2DMeshFrom3D();
6049 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6051 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6054 SMESH_CATCH( SMESH::throwCorbaException );
6058 //================================================================================
6060 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6061 * The list of groups must contain at least two groups. The groups have to be disjoint:
6062 * no common element into two different groups.
6063 * The nodes of the internal faces at the boundaries of the groups are doubled.
6064 * Optionally, the internal faces are replaced by flat elements.
6065 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6066 * The flat elements are stored in groups of volumes.
6067 * These groups are named according to the position of the group in the list:
6068 * the group j_n_p is the group of the flat elements that are built between the group #n and the group #p in the list.
6069 * 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.
6070 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6071 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6072 * \param theDomains - list of groups of volumes
6073 * \param createJointElems - if TRUE, create the elements
6074 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6075 * the boundary between \a theDomains and the rest mesh
6076 * \return TRUE if operation has been completed successfully, FALSE otherwise
6078 //================================================================================
6081 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6082 CORBA::Boolean createJointElems,
6083 CORBA::Boolean onAllBoundaries )
6084 throw (SALOME::SALOME_Exception)
6091 SMESHDS_Mesh* aMeshDS = getMeshDS();
6093 // MESSAGE("theDomains.length = "<<theDomains.length());
6094 if ( theDomains.length() <= 1 && !onAllBoundaries )
6095 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6097 vector<TIDSortedElemSet> domains;
6098 domains.resize( theDomains.length() );
6100 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6102 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6103 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6105 // if ( aGrp->GetType() != SMESH::VOLUME )
6106 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6107 SMESH::long_array_var anIDs = aGrp->GetIDs();
6108 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6112 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6113 // TODO publish the groups of flat elements in study
6115 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6117 // Update Python script
6118 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6119 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6121 SMESH_CATCH( SMESH::throwCorbaException );
6123 myMesh_i->CreateGroupServants(); // publish created groups if any
6128 //================================================================================
6130 * \brief Double nodes on some external faces and create flat elements.
6131 * Flat elements are mainly used by some types of mechanic calculations.
6133 * Each group of the list must be constituted of faces.
6134 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6135 * @param theGroupsOfFaces - list of groups of faces
6136 * @return TRUE if operation has been completed successfully, FALSE otherwise
6138 //================================================================================
6141 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6142 throw (SALOME::SALOME_Exception)
6147 SMESHDS_Mesh* aMeshDS = getMeshDS();
6149 vector<TIDSortedElemSet> faceGroups;
6152 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6154 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6155 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6157 TIDSortedElemSet faceGroup;
6159 faceGroups.push_back(faceGroup);
6160 SMESH::long_array_var anIDs = aGrp->GetIDs();
6161 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6165 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6166 // TODO publish the groups of flat elements in study
6168 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6170 // Update Python script
6171 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6174 SMESH_CATCH( SMESH::throwCorbaException );
6178 //================================================================================
6180 * \brief Identify all the elements around a geom shape, get the faces delimiting
6183 * Build groups of volume to remove, groups of faces to replace on the skin of the
6184 * object, groups of faces to remove inside the object, (idem edges).
6185 * Build ordered list of nodes at the border of each group of faces to replace
6186 * (to be used to build a geom subshape).
6188 //================================================================================
6190 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6191 GEOM::GEOM_Object_ptr theShape,
6192 const char* groupName,
6193 const SMESH::double_array& theNodesCoords,
6194 SMESH::array_of_long_array_out GroupsOfNodes)
6195 throw (SALOME::SALOME_Exception)
6200 std::vector<std::vector<int> > aListOfListOfNodes;
6201 ::SMESH_MeshEditor aMeshEditor( myMesh );
6203 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6204 if ( !theNodeSearcher )
6205 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6207 vector<double> nodesCoords;
6208 for (int i = 0; i < theNodesCoords.length(); i++)
6210 nodesCoords.push_back( theNodesCoords[i] );
6213 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6214 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6215 nodesCoords, aListOfListOfNodes);
6217 GroupsOfNodes = new SMESH::array_of_long_array;
6218 GroupsOfNodes->length( aListOfListOfNodes.size() );
6219 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6220 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6222 vector<int>& aListOfNodes = *llIt;
6223 vector<int>::iterator lIt = aListOfNodes.begin();;
6224 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6225 aGroup.length( aListOfNodes.size() );
6226 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6227 aGroup[ j ] = (*lIt);
6229 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6232 << ", '" << groupName << "', "
6233 << theNodesCoords << " )";
6235 SMESH_CATCH( SMESH::throwCorbaException );
6238 // issue 20749 ===================================================================
6240 * \brief Creates missing boundary elements
6241 * \param elements - elements whose boundary is to be checked
6242 * \param dimension - defines type of boundary elements to create
6243 * \param groupName - a name of group to store created boundary elements in,
6244 * "" means not to create the group
6245 * \param meshName - a name of new mesh to store created boundary elements in,
6246 * "" means not to create the new mesh
6247 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6248 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6249 * boundary elements will be copied into the new mesh
6250 * \param group - returns the create group, if any
6251 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6253 // ================================================================================
6255 SMESH::SMESH_Mesh_ptr
6256 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6257 SMESH::Bnd_Dimension dim,
6258 const char* groupName,
6259 const char* meshName,
6260 CORBA::Boolean toCopyElements,
6261 CORBA::Boolean toCopyExistingBondary,
6262 SMESH::SMESH_Group_out group)
6263 throw (SALOME::SALOME_Exception)
6268 if ( dim > SMESH::BND_1DFROM2D )
6269 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6271 SMESHDS_Mesh* aMeshDS = getMeshDS();
6273 SMESH::SMESH_Mesh_var mesh_var;
6274 SMESH::SMESH_Group_var group_var;
6278 TIDSortedElemSet elements;
6279 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6280 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6284 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6285 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6287 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6289 // group of new boundary elements
6290 SMESH_Group* smesh_group = 0;
6291 if ( strlen(groupName) )
6293 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6294 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6295 smesh_group = group_i->GetSmeshGroup();
6299 getEditor().MakeBoundaryMesh( elements,
6300 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6304 toCopyExistingBondary);
6307 smesh_mesh->GetMeshDS()->Modified();
6310 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6312 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6313 if ( mesh_var->_is_nil() )
6314 pyDump << myMesh_i->_this() << ", ";
6316 pyDump << mesh_var << ", ";
6317 if ( group_var->_is_nil() )
6318 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6320 pyDump << group_var << " = ";
6321 pyDump << this << ".MakeBoundaryMesh( "
6323 << "SMESH." << dimName[int(dim)] << ", "
6324 << "'" << groupName << "', "
6325 << "'" << meshName<< "', "
6326 << toCopyElements << ", "
6327 << toCopyExistingBondary << ")";
6329 group = group_var._retn();
6330 return mesh_var._retn();
6332 SMESH_CATCH( SMESH::throwCorbaException );
6333 return SMESH::SMESH_Mesh::_nil();
6336 //================================================================================
6338 * \brief Creates missing boundary elements
6339 * \param dimension - defines type of boundary elements to create
6340 * \param groupName - a name of group to store all boundary elements in,
6341 * "" means not to create the group
6342 * \param meshName - a name of a new mesh, which is a copy of the initial
6343 * mesh + created boundary elements; "" means not to create the new mesh
6344 * \param toCopyAll - if true, the whole initial mesh will be copied into
6345 * the new mesh else only boundary elements will be copied into the new mesh
6346 * \param groups - optional groups of elements to make boundary around
6347 * \param mesh - returns the mesh where elements were added to
6348 * \param group - returns the created group, if any
6349 * \retval long - number of added boundary elements
6351 //================================================================================
6353 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6354 const char* groupName,
6355 const char* meshName,
6356 CORBA::Boolean toCopyAll,
6357 const SMESH::ListOfIDSources& groups,
6358 SMESH::SMESH_Mesh_out mesh,
6359 SMESH::SMESH_Group_out group)
6360 throw (SALOME::SALOME_Exception)
6365 if ( dim > SMESH::BND_1DFROM2D )
6366 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6368 // separate groups belonging to this and other mesh
6369 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6370 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6371 groupsOfThisMesh->length( groups.length() );
6372 groupsOfOtherMesh->length( groups.length() );
6373 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6374 for ( int i = 0; i < groups.length(); ++i )
6376 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6377 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6378 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6380 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6381 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6382 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6384 groupsOfThisMesh->length( nbGroups );
6385 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6390 if ( nbGroupsOfOtherMesh > 0 )
6392 // process groups belonging to another mesh
6393 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6394 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6395 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6396 groupsOfOtherMesh, mesh, group );
6399 SMESH::SMESH_Mesh_var mesh_var;
6400 SMESH::SMESH_Group_var group_var;
6403 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6404 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6408 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6410 /*toCopyGroups=*/false,
6411 /*toKeepIDs=*/true);
6413 mesh_var = makeMesh(meshName);
6415 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6416 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6419 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6420 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6422 // group of boundary elements
6423 SMESH_Group* smesh_group = 0;
6424 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6425 if ( strlen(groupName) )
6427 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6428 group_var = mesh_i->CreateGroup( groupType, groupName );
6429 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6430 smesh_group = group_i->GetSmeshGroup();
6433 TIDSortedElemSet elements;
6435 if ( groups.length() > 0 )
6437 for ( int i = 0; i < nbGroups; ++i )
6440 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6442 SMESH::Bnd_Dimension bdim =
6443 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6444 nbAdded += getEditor().MakeBoundaryMesh( elements,
6445 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6448 /*toCopyElements=*/false,
6449 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6450 /*toAddExistingBondary=*/true,
6451 /*aroundElements=*/true);
6457 nbAdded += getEditor().MakeBoundaryMesh( elements,
6458 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6461 /*toCopyElements=*/false,
6462 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6463 /*toAddExistingBondary=*/true);
6465 tgtMesh->GetMeshDS()->Modified();
6467 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6469 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6470 pyDump << "nbAdded, ";
6471 if ( mesh_var->_is_nil() )
6472 pyDump << myMesh_i->_this() << ", ";
6474 pyDump << mesh_var << ", ";
6475 if ( group_var->_is_nil() )
6476 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6478 pyDump << group_var << " = ";
6479 pyDump << this << ".MakeBoundaryElements( "
6480 << "SMESH." << dimName[int(dim)] << ", "
6481 << "'" << groupName << "', "
6482 << "'" << meshName<< "', "
6483 << toCopyAll << ", "
6486 mesh = mesh_var._retn();
6487 group = group_var._retn();
6490 SMESH_CATCH( SMESH::throwCorbaException );