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;
118 virtual ~TPreviewMesh() { delete _myMeshDS; _myMeshDS = 0; }
119 //!< Copy a set of elements
120 void Copy(const TIDSortedElemSet & theElements,
121 TIDSortedElemSet& theCopyElements,
122 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
123 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
125 // loop on theIDsOfElements
126 TIDSortedElemSet::const_iterator eIt = theElements.begin();
127 for ( ; eIt != theElements.end(); ++eIt )
129 const SMDS_MeshElement* anElem = *eIt;
130 if ( !anElem ) continue;
131 SMDSAbs_ElementType type = anElem->GetType();
132 if ( type == theAvoidType ||
133 ( theSelectType != SMDSAbs_All && type != theSelectType ))
135 const SMDS_MeshElement* anElemCopy;
136 if ( type == SMDSAbs_Node)
137 anElemCopy = Copy( cast2Node(anElem) );
139 anElemCopy = Copy( anElem );
141 theCopyElements.insert( theCopyElements.end(), anElemCopy );
145 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
147 // copy element nodes
148 int anElemNbNodes = anElem->NbNodes();
149 vector< int > anElemNodesID( anElemNbNodes ) ;
150 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
151 for ( int i = 0; itElemNodes->more(); i++)
153 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
155 anElemNodesID[i] = anElemNode->GetID();
158 // creates a corresponding element on copied nodes
159 SMDS_MeshElement* anElemCopy = 0;
160 if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume )
162 const SMDS_VtkVolume* ph =
163 dynamic_cast<const SMDS_VtkVolume*> (anElem);
165 anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID
166 (anElemNodesID, ph->GetQuantities(),anElem->GetID());
169 anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID,
176 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
178 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
179 anElemNode->GetID());
183 GetMeshDS()->ClearMesh();
185 void Remove( SMDSAbs_ElementType type )
187 SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator( type );
188 while ( eIt->more() )
189 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
191 };// struct TPreviewMesh
193 static SMESH_NodeSearcher * theNodeSearcher = 0;
194 static SMESH_ElementSearcher * theElementSearcher = 0;
196 //=============================================================================
198 * \brief Deleter of theNodeSearcher at any compute event occured
200 //=============================================================================
202 struct TSearchersDeleter : public SMESH_subMeshEventListener
205 string myMeshPartIOR;
207 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
208 "SMESH_MeshEditor_i::TSearchersDeleter"),
210 //!< Delete theNodeSearcher
213 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
214 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
216 typedef map < int, SMESH_subMesh * > TDependsOnMap;
217 //!< The meshod called by submesh: do my main job
218 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
219 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
221 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
223 Unset( sm->GetFather() );
226 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
227 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
229 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
236 myMeshPartIOR = meshPartIOR;
237 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
238 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
239 while ( smIt->more() )
242 sm->SetEventListener( this, 0, sm );
246 //!< delete self from all submeshes
247 void Unset(SMESH_Mesh* mesh)
249 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
250 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
251 while ( smIt->more() )
252 smIt->next()->DeleteEventListener( this );
257 } theSearchersDeleter;
259 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
261 TCollection_AsciiString typeStr;
262 switch ( theMirrorType ) {
263 case SMESH::SMESH_MeshEditor::POINT:
264 typeStr = "SMESH.SMESH_MeshEditor.POINT";
266 case SMESH::SMESH_MeshEditor::AXIS:
267 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
270 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
274 //================================================================================
276 * \brief function for conversion of long_array to TIDSortedElemSet
277 * \param IDs - array of IDs
278 * \param aMesh - mesh
279 * \param aMap - collection to fill
280 * \param aType - element type
282 //================================================================================
284 void arrayToSet(const SMESH::long_array & IDs,
285 const SMESHDS_Mesh* aMesh,
286 TIDSortedElemSet& aMap,
287 const SMDSAbs_ElementType aType = SMDSAbs_All,
288 SMDS_MeshElement::Filter* aFilter = NULL)
290 SMDS_MeshElement::NonNullFilter filter1;
291 SMDS_MeshElement::TypeFilter filter2( aType );
293 if ( aFilter == NULL )
294 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
296 SMDS_MeshElement::Filter & filter = *aFilter;
298 if ( aType == SMDSAbs_Node )
299 for (int i=0; i<IDs.length(); i++) {
300 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
302 aMap.insert( aMap.end(), elem );
305 for (int i=0; i<IDs.length(); i++) {
306 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
308 aMap.insert( aMap.end(), elem );
312 //================================================================================
314 * \brief Retrieve nodes from SMESH_IDSource
316 //================================================================================
318 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
319 const SMESHDS_Mesh* theMeshDS,
320 TIDSortedNodeSet& theNodeSet)
323 if ( CORBA::is_nil( theObject ) )
325 SMESH::array_of_ElementType_var types = theObject->GetTypes();
326 SMESH::long_array_var aElementsId = theObject->GetIDs();
327 if ( types->length() == 1 && types[0] == SMESH::NODE)
329 for(int i = 0; i < aElementsId->length(); i++)
330 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
331 theNodeSet.insert( theNodeSet.end(), n);
333 else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
335 SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
336 while ( nIt->more( ))
337 if( const SMDS_MeshElement * elem = nIt->next() )
338 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
342 for(int i = 0; i < aElementsId->length(); i++)
343 if( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
344 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
348 //================================================================================
350 * \brief Returns elements connected to the given elements
352 //================================================================================
354 void getElementsAround(const TIDSortedElemSet& theElements,
355 const SMESHDS_Mesh* theMeshDS,
356 TIDSortedElemSet& theElementsAround)
358 if ( theElements.empty() ) return;
360 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
361 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
363 theMeshDS->GetMeshInfo().NbElements( elemType ) == theElements.size() )
364 return; // all the elements are in theElements
367 elemType = SMDSAbs_All;
369 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
371 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
372 for ( ; elemIt != theElements.end(); ++elemIt )
374 const SMDS_MeshElement* e = *elemIt;
375 int i = e->NbCornerNodes();
378 const SMDS_MeshNode* n = e->GetNode( i );
379 if ( !isNodeChecked[ n->GetID() ])
381 isNodeChecked[ n->GetID() ] = true;
382 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
383 while ( invIt->more() )
385 const SMDS_MeshElement* elemAround = invIt->next();
386 if ( !theElements.count( elemAround ))
387 theElementsAround.insert( elemAround );
394 //================================================================================
396 * \brief Return a string used to detect change of mesh part on which theElementSearcher
397 * is going to be used
399 //================================================================================
401 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
403 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
404 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
405 // take into account passible group modification
406 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
407 partIOR += SMESH_Comment( type );
411 } // namespace MeshEditor_I
413 using namespace MeshEditor_I;
415 //=============================================================================
419 //=============================================================================
421 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
423 myMesh( &theMesh->GetImpl() ),
425 myIsPreviewMode ( isPreview ),
431 //================================================================================
435 //================================================================================
437 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
439 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
440 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
441 poa->deactivate_object(anObjectId.in());
443 //deleteAuxIDSources();
444 delete myPreviewMesh; myPreviewMesh = 0;
445 delete myPreviewEditor; myPreviewEditor = 0;
448 //================================================================================
450 * \brief Returns the mesh
452 //================================================================================
454 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
456 return myMesh_i->_this();
459 //================================================================================
461 * \brief Clear members
463 //================================================================================
465 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
467 if ( myIsPreviewMode ) {
468 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
471 if ( deleteSearchers )
472 TSearchersDeleter::Delete();
474 getEditor().GetError().reset();
475 getEditor().ClearLastCreated();
478 //================================================================================
480 * \brief Increment mesh modif time and optionally record that the performed
481 * modification may influence futher mesh re-compute.
482 * \param [in] isReComputeSafe - true if the modification does not infulence
483 * futher mesh re-compute
485 //================================================================================
487 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
489 myMesh->GetMeshDS()->Modified();
490 if ( !isReComputeSafe )
491 myMesh->SetIsModified( true );
494 //================================================================================
496 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
497 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
499 //================================================================================
501 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
503 if ( myIsPreviewMode && !myPreviewEditor ) {
504 if ( !myPreviewMesh ) getPreviewMesh();
505 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
507 return myIsPreviewMode ? *myPreviewEditor : myEditor;
510 //================================================================================
512 * \brief Initialize and return myPreviewMesh
513 * \param previewElements - type of elements to show in preview
515 * WARNING: call it once par a method!
517 //================================================================================
519 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
521 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
523 delete myPreviewEditor;
525 delete myPreviewMesh;
526 myPreviewMesh = new TPreviewMesh( previewElements );
528 myPreviewMesh->Clear();
529 return myPreviewMesh;
532 //================================================================================
534 * Return data of mesh edition preview
536 //================================================================================
538 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
539 throw (SALOME::SALOME_Exception)
542 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
544 if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
546 list<int> aNodesConnectivity;
547 typedef map<int, int> TNodesMap;
550 SMESHDS_Mesh* aMeshDS;
551 std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
553 aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
554 aMeshDS = aMeshPartDS.get();
557 aMeshDS = getEditor().GetMeshDS();
559 myPreviewData = new SMESH::MeshPreviewStruct();
560 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
563 SMDSAbs_ElementType previewType = SMDSAbs_All;
565 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
566 previewType = aPreviewMesh->myPreviewType;
567 switch ( previewType ) {
568 case SMDSAbs_Edge : break;
569 case SMDSAbs_Face : break;
570 case SMDSAbs_Volume: break;
572 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
576 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
578 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
580 while ( itMeshElems->more() ) {
581 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
582 SMDS_NodeIteratorPtr itElemNodes = aMeshElem->nodeIterator();
583 while ( itElemNodes->more() ) {
584 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
585 int aNodeID = aMeshNode->GetID();
586 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
587 if ( anIter == nodesMap.end() ) {
588 // filling the nodes coordinates
589 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
590 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
591 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
592 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
595 aNodesConnectivity.push_back(anIter->second);
598 // filling the elements types
599 SMDSAbs_ElementType aType = aMeshElem->GetType();
600 bool isPoly = aMeshElem->IsPoly();
601 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
602 myPreviewData->elementTypes[i].isPoly = isPoly;
603 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
606 myPreviewData->nodesXYZ.length( j );
608 // filling the elements connectivities
609 list<int>::iterator aConnIter = aNodesConnectivity.begin();
610 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
611 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
612 myPreviewData->elementConnectivities[i] = *aConnIter;
614 return myPreviewData._retn();
616 SMESH_CATCH( SMESH::throwCorbaException );
620 //================================================================================
622 * \brief Returns list of it's IDs of created nodes
623 * \retval SMESH::long_array* - list of node ID
625 //================================================================================
627 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
628 throw (SALOME::SALOME_Exception)
631 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
633 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
634 myLastCreatedNodes->length( aSeq.Length() );
635 for (int i = 1; i <= aSeq.Length(); i++)
636 myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID();
638 return myLastCreatedNodes._retn();
639 SMESH_CATCH( SMESH::throwCorbaException );
643 //================================================================================
645 * \brief Returns list of it's IDs of created elements
646 * \retval SMESH::long_array* - list of elements' ID
648 //================================================================================
650 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
651 throw (SALOME::SALOME_Exception)
654 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
656 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
657 myLastCreatedElems->length( aSeq.Length() );
658 for ( int i = 1; i <= aSeq.Length(); i++ )
659 myLastCreatedElems[i-1] = aSeq.Value(i)->GetID();
661 return myLastCreatedElems._retn();
662 SMESH_CATCH( SMESH::throwCorbaException );
666 //=======================================================================
667 //function : ClearLastCreated
668 //purpose : Clears sequences of last created elements and nodes
669 //=======================================================================
671 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
674 getEditor().ClearLastCreated();
675 SMESH_CATCH( SMESH::throwCorbaException );
678 //=======================================================================
680 * Returns description of an error/warning occured during the last operation
681 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
683 //=======================================================================
685 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
686 throw (SALOME::SALOME_Exception)
689 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
690 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
691 if ( errIn && !errIn->IsOK() )
693 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
694 errOut->comment = errIn->myComment.c_str();
695 errOut->subShapeID = -1;
696 errOut->hasBadMesh = !errIn->myBadElements.empty();
701 errOut->subShapeID = -1;
702 errOut->hasBadMesh = false;
705 return errOut._retn();
706 SMESH_CATCH( SMESH::throwCorbaException );
710 //=======================================================================
711 //function : MakeIDSource
712 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
713 // Call UnRegister() as you fininsh using it!!
714 //=======================================================================
716 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
717 public virtual SALOME::GenericObj_i
719 SMESH::long_array _ids;
720 SMESH::ElementType _type;
721 SMESH::SMESH_Mesh_ptr _mesh;
722 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
723 SMESH::long_array* GetMeshInfo() { return 0; }
724 SMESH::long_array* GetNbElementsByType()
726 SMESH::long_array_var aRes = new SMESH::long_array();
727 aRes->length(SMESH::NB_ELEMENT_TYPES);
728 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
729 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
732 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
733 bool IsMeshInfoCorrect() { return true; }
734 SMESH::array_of_ElementType* GetTypes()
736 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
737 if ( _ids.length() > 0 ) {
741 return types._retn();
743 SALOMEDS::TMPFile* GetVtkUgStream()
745 SALOMEDS::TMPFile_var SeqFile;
746 return SeqFile._retn();
750 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
751 SMESH::ElementType type)
753 _IDSource* idSrc = new _IDSource;
754 idSrc->_mesh = myMesh_i->_this();
757 if ( type == SMESH::ALL && ids.length() > 0 )
758 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
760 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
762 return anIDSourceVar._retn();
765 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
767 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
770 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
773 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
775 nbIds = (int) tmpIdSource->_ids.length();
776 return & tmpIdSource->_ids[0];
782 // void SMESH_MeshEditor_i::deleteAuxIDSources()
784 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
785 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
787 // myAuxIDSources.clear();
790 //=============================================================================
794 //=============================================================================
797 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
798 throw (SALOME::SALOME_Exception)
805 for (int i = 0; i < IDsOfElements.length(); i++)
806 IdList.push_back( IDsOfElements[i] );
808 // Update Python script
809 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
812 bool ret = getEditor().Remove( IdList, false );
814 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
817 SMESH_CATCH( SMESH::throwCorbaException );
821 //=============================================================================
825 //=============================================================================
827 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
828 throw (SALOME::SALOME_Exception)
834 for (int i = 0; i < IDsOfNodes.length(); i++)
835 IdList.push_back( IDsOfNodes[i] );
837 // Update Python script
838 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
840 bool ret = getEditor().Remove( IdList, true );
842 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
845 SMESH_CATCH( SMESH::throwCorbaException );
849 //=============================================================================
853 //=============================================================================
855 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
856 throw (SALOME::SALOME_Exception)
861 // Update Python script
862 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
864 // Create filter to find all orphan nodes
865 SMESH::Controls::Filter::TIdSequence seq;
866 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
867 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
869 // remove orphan nodes (if there are any)
871 for ( int i = 0; i < seq.size(); i++ )
872 IdList.push_back( seq[i] );
874 int nbNodesBefore = myMesh->NbNodes();
875 getEditor().Remove( IdList, true );
876 int nbNodesAfter = myMesh->NbNodes();
878 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
879 return nbNodesBefore - nbNodesAfter;
881 SMESH_CATCH( SMESH::throwCorbaException );
885 //=============================================================================
889 //=============================================================================
891 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
892 throw (SALOME::SALOME_Exception)
897 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
899 // Update Python script
900 TPythonDump() << "nodeID = " << this << ".AddNode( "
901 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
903 declareMeshModified( /*isReComputeSafe=*/false );
906 SMESH_CATCH( SMESH::throwCorbaException );
910 //=============================================================================
912 * Create 0D element on the given node.
914 //=============================================================================
916 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
917 throw (SALOME::SALOME_Exception)
922 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
923 SMDS_MeshElement* elem = getMeshDS()->Add0DElement(aNode);
925 // Update Python script
926 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
928 declareMeshModified( /*isReComputeSafe=*/false );
930 return elem ? elem->GetID() : 0;
932 SMESH_CATCH( SMESH::throwCorbaException );
936 //=============================================================================
938 * Create a ball element on the given node.
940 //=============================================================================
942 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
943 throw (SALOME::SALOME_Exception)
948 if ( diameter < std::numeric_limits<double>::min() )
949 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
951 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
952 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
954 // Update Python script
955 TPythonDump() << "ballElem = "
956 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
958 declareMeshModified( /*isReComputeSafe=*/false );
959 return elem ? elem->GetID() : 0;
961 SMESH_CATCH( SMESH::throwCorbaException );
965 //=============================================================================
967 * Create an edge, either linear and quadratic (this is determed
968 * by number of given nodes, two or three)
970 //=============================================================================
972 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
973 throw (SALOME::SALOME_Exception)
978 int NbNodes = IDsOfNodes.length();
979 SMDS_MeshElement* elem = 0;
982 CORBA::Long index1 = IDsOfNodes[0];
983 CORBA::Long index2 = IDsOfNodes[1];
984 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
985 getMeshDS()->FindNode(index2));
987 // Update Python script
988 TPythonDump() << "edge = " << this << ".AddEdge([ "
989 << index1 << ", " << index2 <<" ])";
992 CORBA::Long n1 = IDsOfNodes[0];
993 CORBA::Long n2 = IDsOfNodes[1];
994 CORBA::Long n12 = IDsOfNodes[2];
995 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
996 getMeshDS()->FindNode(n2),
997 getMeshDS()->FindNode(n12));
998 // Update Python script
999 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
1000 <<n1<<", "<<n2<<", "<<n12<<" ])";
1003 declareMeshModified( /*isReComputeSafe=*/false );
1004 return elem ? elem->GetID() : 0;
1006 SMESH_CATCH( SMESH::throwCorbaException );
1010 //=============================================================================
1014 //=============================================================================
1016 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1017 throw (SALOME::SALOME_Exception)
1022 int NbNodes = IDsOfNodes.length();
1028 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1029 for (int i = 0; i < NbNodes; i++)
1030 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1032 SMDS_MeshElement* elem = 0;
1034 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1035 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1036 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1037 nodes[4], nodes[5]); break;
1038 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1039 nodes[4], nodes[5], nodes[6]); break;
1040 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1041 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1042 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1043 nodes[4], nodes[5], nodes[6], nodes[7],
1045 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1048 // Update Python script
1049 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1051 declareMeshModified( /*isReComputeSafe=*/false );
1053 return elem ? elem->GetID() : 0;
1055 SMESH_CATCH( SMESH::throwCorbaException );
1059 //=============================================================================
1063 //=============================================================================
1064 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1065 throw (SALOME::SALOME_Exception)
1070 int NbNodes = IDsOfNodes.length();
1071 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1072 for (int i = 0; i < NbNodes; i++)
1073 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1075 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1077 // Update Python script
1078 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1080 declareMeshModified( /*isReComputeSafe=*/false );
1081 return elem ? elem->GetID() : 0;
1083 SMESH_CATCH( SMESH::throwCorbaException );
1087 //=============================================================================
1089 * Create volume, either linear and quadratic (this is determed
1090 * by number of given nodes)
1092 //=============================================================================
1094 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1095 throw (SALOME::SALOME_Exception)
1100 int NbNodes = IDsOfNodes.length();
1101 vector< const SMDS_MeshNode*> n(NbNodes);
1102 for(int i=0;i<NbNodes;i++)
1103 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1105 SMDS_MeshElement* elem = 0;
1108 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1109 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1110 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1111 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1112 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1113 n[6],n[7],n[8],n[9]);
1115 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1116 n[6],n[7],n[8],n[9],n[10],n[11]);
1118 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1119 n[7],n[8],n[9],n[10],n[11],n[12]);
1121 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1122 n[9],n[10],n[11],n[12],n[13],n[14]);
1124 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1125 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1126 n[15],n[16],n[17],n[18],n[19]);
1128 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1129 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1130 n[15],n[16],n[17],n[18],n[19],
1131 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1135 // Update Python script
1136 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1138 declareMeshModified( /*isReComputeSafe=*/false );
1139 return elem ? elem->GetID() : 0;
1141 SMESH_CATCH( SMESH::throwCorbaException );
1145 //=============================================================================
1147 * AddPolyhedralVolume
1149 //=============================================================================
1150 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1151 const SMESH::long_array & Quantities)
1152 throw (SALOME::SALOME_Exception)
1157 int NbNodes = IDsOfNodes.length();
1158 std::vector<const SMDS_MeshNode*> n (NbNodes);
1159 for (int i = 0; i < NbNodes; i++)
1161 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1162 if (!aNode) return 0;
1166 int NbFaces = Quantities.length();
1167 std::vector<int> q (NbFaces);
1168 for (int j = 0; j < NbFaces; j++)
1169 q[j] = Quantities[j];
1171 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1173 // Update Python script
1174 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1175 << IDsOfNodes << ", " << Quantities << " )";
1177 declareMeshModified( /*isReComputeSafe=*/false );
1178 return elem ? elem->GetID() : 0;
1180 SMESH_CATCH( SMESH::throwCorbaException );
1184 //=============================================================================
1186 * AddPolyhedralVolumeByFaces
1188 //=============================================================================
1190 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1191 throw (SALOME::SALOME_Exception)
1196 int NbFaces = IdsOfFaces.length();
1197 std::vector<const SMDS_MeshNode*> poly_nodes;
1198 std::vector<int> quantities (NbFaces);
1200 for (int i = 0; i < NbFaces; i++) {
1201 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1202 quantities[i] = aFace->NbNodes();
1204 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1205 while (It->more()) {
1206 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1210 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1212 // Update Python script
1213 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1214 << IdsOfFaces << " )";
1216 declareMeshModified( /*isReComputeSafe=*/false );
1217 return elem ? elem->GetID() : 0;
1219 SMESH_CATCH( SMESH::throwCorbaException );
1223 //=============================================================================
1225 // \brief Create 0D elements on all nodes of the given object except those
1226 // nodes on which a 0D element already exists.
1227 // \param theObject object on whose nodes 0D elements will be created.
1228 // \param theGroupName optional name of a group to add 0D elements created
1229 // and/or found on nodes of \a theObject.
1230 // \return an object (a new group or a temporary SMESH_IDSource) holding
1231 // ids of new and/or found 0D elements.
1233 //=============================================================================
1235 SMESH::SMESH_IDSource_ptr
1236 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1237 const char* theGroupName)
1238 throw (SALOME::SALOME_Exception)
1243 SMESH::SMESH_IDSource_var result;
1246 TIDSortedElemSet elements, elems0D;
1247 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1248 getEditor().Create0DElementsOnAllNodes( elements, elems0D );
1250 SMESH::long_array_var newElems = new SMESH::long_array;
1251 newElems->length( elems0D.size() );
1252 TIDSortedElemSet::iterator eIt = elems0D.begin();
1253 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1254 newElems[ i ] = (*eIt)->GetID();
1256 SMESH::SMESH_GroupBase_var groupToFill;
1257 if ( theGroupName && strlen( theGroupName ))
1259 // Get existing group named theGroupName
1260 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1261 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1262 SMESH::SMESH_GroupBase_var group = groups[i];
1263 if ( !group->_is_nil() ) {
1264 CORBA::String_var name = group->GetName();
1265 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1266 groupToFill = group;
1271 if ( groupToFill->_is_nil() )
1272 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1273 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1274 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1277 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1279 group_i->Add( newElems );
1280 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1281 pyDump << groupToFill;
1285 result = MakeIDSource( newElems, SMESH::ELEM0D );
1286 pyDump << "elem0DIDs";
1289 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1290 << theObject << ", '" << theGroupName << "' )";
1292 return result._retn();
1294 SMESH_CATCH( SMESH::throwCorbaException );
1298 //=============================================================================
1300 * \brief Bind a node to a vertex
1301 * \param NodeID - node ID
1302 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1303 * \retval boolean - false if NodeID or VertexID is invalid
1305 //=============================================================================
1307 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1308 throw (SALOME::SALOME_Exception)
1312 SMESHDS_Mesh * mesh = getMeshDS();
1313 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1315 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1317 if ( mesh->MaxShapeIndex() < VertexID )
1318 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1320 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1321 if ( shape.ShapeType() != TopAbs_VERTEX )
1322 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1324 mesh->SetNodeOnVertex( node, VertexID );
1326 myMesh->SetIsModified( true );
1328 SMESH_CATCH( SMESH::throwCorbaException );
1331 //=============================================================================
1333 * \brief Store node position on an edge
1334 * \param NodeID - node ID
1335 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1336 * \param paramOnEdge - parameter on edge where the node is located
1337 * \retval boolean - false if any parameter is invalid
1339 //=============================================================================
1341 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1342 CORBA::Double paramOnEdge)
1343 throw (SALOME::SALOME_Exception)
1347 SMESHDS_Mesh * mesh = getMeshDS();
1348 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1350 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1352 if ( mesh->MaxShapeIndex() < EdgeID )
1353 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1355 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1356 if ( shape.ShapeType() != TopAbs_EDGE )
1357 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1360 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1361 if ( paramOnEdge < f || paramOnEdge > l )
1362 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1364 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1366 myMesh->SetIsModified( true );
1368 SMESH_CATCH( SMESH::throwCorbaException );
1371 //=============================================================================
1373 * \brief Store node position on a face
1374 * \param NodeID - node ID
1375 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1376 * \param u - U parameter on face where the node is located
1377 * \param v - V parameter on face where the node is located
1378 * \retval boolean - false if any parameter is invalid
1380 //=============================================================================
1382 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1383 CORBA::Double u, CORBA::Double v)
1384 throw (SALOME::SALOME_Exception)
1387 SMESHDS_Mesh * mesh = getMeshDS();
1388 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1390 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1392 if ( mesh->MaxShapeIndex() < FaceID )
1393 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1395 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1396 if ( shape.ShapeType() != TopAbs_FACE )
1397 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1399 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1400 bool isOut = ( u < surf.FirstUParameter() ||
1401 u > surf.LastUParameter() ||
1402 v < surf.FirstVParameter() ||
1403 v > surf.LastVParameter() );
1407 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1408 << " u( " << surf.FirstUParameter()
1409 << "," << surf.LastUParameter()
1410 << ") v( " << surf.FirstVParameter()
1411 << "," << surf.LastVParameter() << ")" );
1413 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1416 mesh->SetNodeOnFace( node, FaceID, u, v );
1417 myMesh->SetIsModified( true );
1419 SMESH_CATCH( SMESH::throwCorbaException );
1422 //=============================================================================
1424 * \brief Bind a node to a solid
1425 * \param NodeID - node ID
1426 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1427 * \retval boolean - false if NodeID or SolidID is invalid
1429 //=============================================================================
1431 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1432 throw (SALOME::SALOME_Exception)
1435 SMESHDS_Mesh * mesh = getMeshDS();
1436 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1438 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1440 if ( mesh->MaxShapeIndex() < SolidID )
1441 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1443 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1444 if ( shape.ShapeType() != TopAbs_SOLID &&
1445 shape.ShapeType() != TopAbs_SHELL)
1446 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1448 mesh->SetNodeInVolume( node, SolidID );
1450 SMESH_CATCH( SMESH::throwCorbaException );
1453 //=============================================================================
1455 * \brief Bind an element to a shape
1456 * \param ElementID - element ID
1457 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1459 //=============================================================================
1461 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1462 CORBA::Long ShapeID)
1463 throw (SALOME::SALOME_Exception)
1466 SMESHDS_Mesh * mesh = getMeshDS();
1467 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1469 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1471 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1472 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1474 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1475 if ( shape.ShapeType() != TopAbs_EDGE &&
1476 shape.ShapeType() != TopAbs_FACE &&
1477 shape.ShapeType() != TopAbs_SOLID &&
1478 shape.ShapeType() != TopAbs_SHELL )
1479 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1481 mesh->SetMeshElementOnShape( elem, ShapeID );
1483 myMesh->SetIsModified( true );
1485 SMESH_CATCH( SMESH::throwCorbaException );
1488 //=============================================================================
1492 //=============================================================================
1494 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1495 CORBA::Long NodeID2)
1496 throw (SALOME::SALOME_Exception)
1501 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1502 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1506 // Update Python script
1507 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1508 << NodeID1 << ", " << NodeID2 << " )";
1510 int ret = getEditor().InverseDiag ( n1, n2 );
1512 declareMeshModified( /*isReComputeSafe=*/false );
1515 SMESH_CATCH( SMESH::throwCorbaException );
1519 //=============================================================================
1523 //=============================================================================
1525 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1526 CORBA::Long NodeID2)
1527 throw (SALOME::SALOME_Exception)
1532 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1533 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1537 // Update Python script
1538 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1539 << NodeID1 << ", " << NodeID2 << " )";
1542 bool stat = getEditor().DeleteDiag ( n1, n2 );
1544 declareMeshModified( /*isReComputeSafe=*/!stat );
1548 SMESH_CATCH( SMESH::throwCorbaException );
1552 //=============================================================================
1556 //=============================================================================
1558 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1559 throw (SALOME::SALOME_Exception)
1564 for (int i = 0; i < IDsOfElements.length(); i++)
1566 CORBA::Long index = IDsOfElements[i];
1567 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1569 getEditor().Reorient( elem );
1571 // Update Python script
1572 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1574 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1577 SMESH_CATCH( SMESH::throwCorbaException );
1581 //=============================================================================
1585 //=============================================================================
1587 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1588 throw (SALOME::SALOME_Exception)
1593 TPythonDump aTPythonDump; // suppress dump in Reorient()
1595 prepareIdSource( theObject );
1597 SMESH::long_array_var anElementsId = theObject->GetIDs();
1598 CORBA::Boolean isDone = Reorient(anElementsId);
1600 // Update Python script
1601 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1603 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1606 SMESH_CATCH( SMESH::throwCorbaException );
1610 //=======================================================================
1611 //function : Reorient2D
1612 //purpose : Reorient faces contained in \a the2Dgroup.
1613 // the2Dgroup - the mesh or its part to reorient
1614 // theDirection - desired direction of normal of \a theFace
1615 // theFace - ID of face whose orientation is checked.
1616 // It can be < 1 then \a thePoint is used to find a face.
1617 // thePoint - is used to find a face if \a theFace < 1.
1618 // return number of reoriented elements.
1619 //=======================================================================
1621 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1622 const SMESH::DirStruct& theDirection,
1623 CORBA::Long theFace,
1624 const SMESH::PointStruct& thePoint)
1625 throw (SALOME::SALOME_Exception)
1628 initData(/*deleteSearchers=*/false);
1630 TIDSortedElemSet elements;
1631 IDSource_Error error;
1632 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1633 if ( error == IDSource_EMPTY )
1635 if ( error == IDSource_INVALID )
1636 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1639 const SMDS_MeshElement* face = 0;
1642 face = getMeshDS()->FindElement( theFace );
1644 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1645 if ( face->GetType() != SMDSAbs_Face )
1646 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1650 // create theElementSearcher if needed
1651 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1652 if ( !theElementSearcher )
1654 if ( elements.empty() ) // search in the whole mesh
1656 if ( myMesh->NbFaces() == 0 )
1657 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1659 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1663 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1664 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1666 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1670 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1671 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1674 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1675 if ( !elements.empty() && !elements.count( face ))
1676 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1679 const SMESH::PointStruct * P = &theDirection.PS;
1680 gp_Vec dirVec( P->x, P->y, P->z );
1681 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1682 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1684 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1687 declareMeshModified( /*isReComputeSafe=*/false );
1689 TPythonDump() << this << ".Reorient2D( "
1690 << the2Dgroup << ", "
1691 << theDirection << ", "
1693 << thePoint << " )";
1697 SMESH_CATCH( SMESH::throwCorbaException );
1701 //=======================================================================
1702 //function : Reorient2DBy3D
1703 //purpose : Reorient faces basing on orientation of adjacent volumes.
1704 //=======================================================================
1706 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1707 SMESH::SMESH_IDSource_ptr volumeGroup,
1708 CORBA::Boolean outsideNormal)
1709 throw (SALOME::SALOME_Exception)
1714 TIDSortedElemSet volumes;
1715 IDSource_Error volsError;
1716 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1719 for ( size_t i = 0; i < faceGroups.length(); ++i )
1721 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1723 TIDSortedElemSet faces;
1724 IDSource_Error error;
1725 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1726 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1727 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1728 if ( error == IDSource_OK && volsError != IDSource_OK )
1729 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1731 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1733 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1738 declareMeshModified( /*isReComputeSafe=*/false );
1740 TPythonDump() << this << ".Reorient2DBy3D( "
1741 << faceGroups << ", "
1742 << volumeGroup << ", "
1743 << outsideNormal << " )";
1747 SMESH_CATCH( SMESH::throwCorbaException );
1751 //=============================================================================
1753 * \brief Fuse neighbour triangles into quadrangles.
1755 //=============================================================================
1757 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1758 SMESH::NumericalFunctor_ptr Criterion,
1759 CORBA::Double MaxAngle)
1760 throw (SALOME::SALOME_Exception)
1765 SMESHDS_Mesh* aMesh = getMeshDS();
1766 TIDSortedElemSet faces,copyFaces;
1767 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1768 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1769 TIDSortedElemSet* workElements = & faces;
1771 if ( myIsPreviewMode ) {
1772 SMDSAbs_ElementType select = SMDSAbs_Face;
1773 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1774 workElements = & copyFaces;
1777 SMESH::NumericalFunctor_i* aNumericalFunctor =
1778 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1779 SMESH::Controls::NumericalFunctorPtr aCrit;
1780 if ( !aNumericalFunctor )
1781 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1783 aCrit = aNumericalFunctor->GetNumericalFunctor();
1785 if ( !myIsPreviewMode ) {
1786 // Update Python script
1787 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1788 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1791 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1793 declareMeshModified( /*isReComputeSafe=*/!stat );
1796 SMESH_CATCH( SMESH::throwCorbaException );
1800 //=============================================================================
1802 * \brief Fuse neighbour triangles into quadrangles.
1804 //=============================================================================
1806 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1807 SMESH::NumericalFunctor_ptr Criterion,
1808 CORBA::Double MaxAngle)
1809 throw (SALOME::SALOME_Exception)
1814 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1816 prepareIdSource( theObject );
1817 SMESH::long_array_var anElementsId = theObject->GetIDs();
1818 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1820 if ( !myIsPreviewMode ) {
1821 SMESH::NumericalFunctor_i* aNumericalFunctor =
1822 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1824 // Update Python script
1825 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1826 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1831 SMESH_CATCH( SMESH::throwCorbaException );
1835 //=============================================================================
1837 * \brief Split quadrangles into triangles.
1839 //=============================================================================
1841 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1842 SMESH::NumericalFunctor_ptr Criterion)
1843 throw (SALOME::SALOME_Exception)
1848 SMESHDS_Mesh* aMesh = getMeshDS();
1849 TIDSortedElemSet faces;
1850 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1852 SMESH::NumericalFunctor_i* aNumericalFunctor =
1853 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1854 SMESH::Controls::NumericalFunctorPtr aCrit;
1855 if ( !aNumericalFunctor )
1856 aCrit.reset( new SMESH::Controls::AspectRatio() );
1858 aCrit = aNumericalFunctor->GetNumericalFunctor();
1861 // Update Python script
1862 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1864 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1866 declareMeshModified( /*isReComputeSafe=*/false );
1869 SMESH_CATCH( SMESH::throwCorbaException );
1873 //=============================================================================
1875 * \brief Split quadrangles into triangles.
1877 //=============================================================================
1879 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1880 SMESH::NumericalFunctor_ptr Criterion)
1881 throw (SALOME::SALOME_Exception)
1886 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1888 prepareIdSource( theObject );
1889 SMESH::long_array_var anElementsId = theObject->GetIDs();
1890 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1892 SMESH::NumericalFunctor_i* aNumericalFunctor =
1893 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1895 // Update Python script
1896 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1898 declareMeshModified( /*isReComputeSafe=*/false );
1901 SMESH_CATCH( SMESH::throwCorbaException );
1905 //================================================================================
1907 * \brief Split each of quadrangles into 4 triangles.
1908 * \param [in] theObject - theQuads Container of quadrangles to split.
1910 //================================================================================
1912 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1913 throw (SALOME::SALOME_Exception)
1918 TIDSortedElemSet faces;
1919 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1921 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1923 getEditor().QuadTo4Tri( faces );
1924 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1926 SMESH_CATCH( SMESH::throwCorbaException );
1929 //=============================================================================
1931 * \brief Split quadrangles into triangles.
1933 //=============================================================================
1935 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1936 CORBA::Boolean Diag13)
1937 throw (SALOME::SALOME_Exception)
1942 SMESHDS_Mesh* aMesh = getMeshDS();
1943 TIDSortedElemSet faces;
1944 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1946 // Update Python script
1947 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1948 << IDsOfElements << ", " << Diag13 << " )";
1950 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1952 declareMeshModified( /*isReComputeSafe=*/ !stat );
1955 SMESH_CATCH( SMESH::throwCorbaException );
1959 //=============================================================================
1961 * \brief Split quadrangles into triangles.
1963 //=============================================================================
1965 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1966 CORBA::Boolean Diag13)
1967 throw (SALOME::SALOME_Exception)
1972 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
1974 prepareIdSource( theObject );
1975 SMESH::long_array_var anElementsId = theObject->GetIDs();
1976 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1978 // Update Python script
1979 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
1980 << theObject << ", " << Diag13 << " )";
1982 declareMeshModified( /*isReComputeSafe=*/!isDone );
1985 SMESH_CATCH( SMESH::throwCorbaException );
1990 //=============================================================================
1992 * Find better splitting of the given quadrangle.
1993 * \param IDOfQuad ID of the quadrangle to be splitted.
1994 * \param Criterion A criterion to choose a diagonal for splitting.
1995 * \return 1 if 1-3 diagonal is better, 2 if 2-4
1996 * diagonal is better, 0 if error occurs.
1998 //=============================================================================
2000 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2001 SMESH::NumericalFunctor_ptr Criterion)
2002 throw (SALOME::SALOME_Exception)
2007 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2008 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2010 SMESH::NumericalFunctor_i* aNumericalFunctor =
2011 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2012 SMESH::Controls::NumericalFunctorPtr aCrit;
2013 if (aNumericalFunctor)
2014 aCrit = aNumericalFunctor->GetNumericalFunctor();
2016 aCrit.reset(new SMESH::Controls::AspectRatio());
2018 int id = getEditor().BestSplit(quad, aCrit);
2019 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2023 SMESH_CATCH( SMESH::throwCorbaException );
2027 //================================================================================
2029 * \brief Split volumic elements into tetrahedrons
2031 //================================================================================
2033 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2034 CORBA::Short methodFlags)
2035 throw (SALOME::SALOME_Exception)
2040 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2041 const int noneFacet = -1;
2042 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2043 while( volIt->more() )
2044 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2046 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2047 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2049 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2050 << elems << ", " << methodFlags << " )";
2052 SMESH_CATCH( SMESH::throwCorbaException );
2055 //================================================================================
2057 * \brief Split hexahedra into triangular prisms
2058 * \param elems - elements to split
2059 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2060 * to split into triangles
2061 * \param methodFlags - flags passing splitting method:
2062 * 1 - split the hexahedron into 2 prisms
2063 * 2 - split the hexahedron into 4 prisms
2065 //================================================================================
2067 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr elems,
2068 const SMESH::PointStruct & startHexPoint,
2069 const SMESH::DirStruct& facetToSplitNormal,
2070 CORBA::Short methodFlags,
2071 CORBA::Boolean allDomains)
2072 throw (SALOME::SALOME_Exception)
2076 prepareIdSource( elems );
2078 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2081 gp_Dir( facetToSplitNormal.PS.x,
2082 facetToSplitNormal.PS.y,
2083 facetToSplitNormal.PS.z ));
2084 TIDSortedElemSet elemSet;
2085 SMESH::long_array_var anElementsId = elems->GetIDs();
2086 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2087 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2089 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2090 while ( !elemSet.empty() )
2092 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2096 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2097 for ( ; ef != elemFacets.end(); ++ef )
2098 elemSet.erase( ef->first );
2101 if ( methodFlags == 2 )
2102 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2104 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2106 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2107 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2109 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2111 << startHexPoint << ", "
2112 << facetToSplitNormal<< ", "
2113 << methodFlags<< ", "
2114 << allDomains << " )";
2116 SMESH_CATCH( SMESH::throwCorbaException );
2119 //=======================================================================
2122 //=======================================================================
2125 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2126 const SMESH::long_array & IDsOfFixedNodes,
2127 CORBA::Long MaxNbOfIterations,
2128 CORBA::Double MaxAspectRatio,
2129 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2130 throw (SALOME::SALOME_Exception)
2132 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2133 MaxAspectRatio, Method, false );
2137 //=======================================================================
2138 //function : SmoothParametric
2140 //=======================================================================
2143 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2144 const SMESH::long_array & IDsOfFixedNodes,
2145 CORBA::Long MaxNbOfIterations,
2146 CORBA::Double MaxAspectRatio,
2147 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2148 throw (SALOME::SALOME_Exception)
2150 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2151 MaxAspectRatio, Method, true );
2155 //=======================================================================
2156 //function : SmoothObject
2158 //=======================================================================
2161 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2162 const SMESH::long_array & IDsOfFixedNodes,
2163 CORBA::Long MaxNbOfIterations,
2164 CORBA::Double MaxAspectRatio,
2165 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2166 throw (SALOME::SALOME_Exception)
2168 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2169 MaxAspectRatio, Method, false);
2173 //=======================================================================
2174 //function : SmoothParametricObject
2176 //=======================================================================
2179 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2180 const SMESH::long_array & IDsOfFixedNodes,
2181 CORBA::Long MaxNbOfIterations,
2182 CORBA::Double MaxAspectRatio,
2183 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2184 throw (SALOME::SALOME_Exception)
2186 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2187 MaxAspectRatio, Method, true);
2191 //=============================================================================
2195 //=============================================================================
2198 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2199 const SMESH::long_array & IDsOfFixedNodes,
2200 CORBA::Long MaxNbOfIterations,
2201 CORBA::Double MaxAspectRatio,
2202 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2204 throw (SALOME::SALOME_Exception)
2209 SMESHDS_Mesh* aMesh = getMeshDS();
2211 TIDSortedElemSet elements;
2212 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2214 set<const SMDS_MeshNode*> fixedNodes;
2215 for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
2216 CORBA::Long index = IDsOfFixedNodes[i];
2217 const SMDS_MeshNode * node = aMesh->FindNode(index);
2219 fixedNodes.insert( node );
2221 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2222 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2223 method = ::SMESH_MeshEditor::CENTROIDAL;
2225 getEditor().Smooth(elements, fixedNodes, method,
2226 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2228 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2230 // Update Python script
2231 TPythonDump() << "isDone = " << this << "."
2232 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2233 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2234 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2235 << "SMESH.SMESH_MeshEditor."
2236 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2237 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2241 SMESH_CATCH( SMESH::throwCorbaException );
2245 //=============================================================================
2249 //=============================================================================
2252 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2253 const SMESH::long_array & IDsOfFixedNodes,
2254 CORBA::Long MaxNbOfIterations,
2255 CORBA::Double MaxAspectRatio,
2256 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2258 throw (SALOME::SALOME_Exception)
2263 TPythonDump aTPythonDump; // suppress dump in smooth()
2265 prepareIdSource( theObject );
2266 SMESH::long_array_var anElementsId = theObject->GetIDs();
2267 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2268 MaxAspectRatio, Method, IsParametric);
2270 // Update Python script
2271 aTPythonDump << "isDone = " << this << "."
2272 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2273 << theObject << ", " << IDsOfFixedNodes << ", "
2274 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2275 << "SMESH.SMESH_MeshEditor."
2276 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2277 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2281 SMESH_CATCH( SMESH::throwCorbaException );
2285 //=============================================================================
2289 //=============================================================================
2291 void SMESH_MeshEditor_i::RenumberNodes()
2292 throw (SALOME::SALOME_Exception)
2295 // Update Python script
2296 TPythonDump() << this << ".RenumberNodes()";
2298 getMeshDS()->Renumber( true );
2300 SMESH_CATCH( SMESH::throwCorbaException );
2303 //=============================================================================
2307 //=============================================================================
2309 void SMESH_MeshEditor_i::RenumberElements()
2310 throw (SALOME::SALOME_Exception)
2313 // Update Python script
2314 TPythonDump() << this << ".RenumberElements()";
2316 getMeshDS()->Renumber( false );
2318 SMESH_CATCH( SMESH::throwCorbaException );
2321 //=======================================================================
2323 * \brief Return groups by their IDs
2325 //=======================================================================
2327 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2328 throw (SALOME::SALOME_Exception)
2333 myMesh_i->CreateGroupServants();
2334 return myMesh_i->GetGroups( *groupIDs );
2336 SMESH_CATCH( SMESH::throwCorbaException );
2340 //=======================================================================
2341 //function : RotationSweepObjects
2343 //=======================================================================
2345 SMESH::ListOfGroups*
2346 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2347 const SMESH::ListOfIDSources & theEdges,
2348 const SMESH::ListOfIDSources & theFaces,
2349 const SMESH::AxisStruct & theAxis,
2350 CORBA::Double theAngleInRadians,
2351 CORBA::Long theNbOfSteps,
2352 CORBA::Double theTolerance,
2353 const bool theMakeGroups)
2354 throw (SALOME::SALOME_Exception)
2359 TIDSortedElemSet elemsNodes[2];
2360 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2361 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2362 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2364 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2365 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2366 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2367 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2369 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2370 bool makeWalls=true;
2371 if ( myIsPreviewMode )
2373 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2374 TPreviewMesh * tmpMesh = getPreviewMesh();
2375 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2376 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2377 workElements = & copyElements[0];
2378 //makeWalls = false; -- faces are needed for preview
2381 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2383 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2384 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2386 ::SMESH_MeshEditor::PGroupIDs groupIds =
2387 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2388 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2390 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2392 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2394 if ( !myIsPreviewMode )
2396 dumpGroupsList( aPythonDump, aGroups );
2397 aPythonDump << this<< ".RotationSweepObjects( "
2402 << TVar( theAngleInRadians ) << ", "
2403 << TVar( theNbOfSteps ) << ", "
2404 << TVar( theTolerance ) << ", "
2405 << theMakeGroups << " )";
2409 getPreviewMesh()->Remove( SMDSAbs_Volume );
2412 return aGroups ? aGroups : new SMESH::ListOfGroups;
2414 SMESH_CATCH( SMESH::throwCorbaException );
2418 namespace MeshEditor_I
2421 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2423 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2425 bool myIsExtrusionByNormal;
2427 static int makeFlags( CORBA::Boolean MakeGroups,
2428 CORBA::Boolean ByAverageNormal = false,
2429 CORBA::Boolean UseInputElemsOnly = false,
2430 CORBA::Long Flags = 0,
2431 CORBA::Boolean MakeBoundary = true )
2433 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2434 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2435 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2436 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2440 ExtrusionParams(const SMESH::DirStruct & theDir,
2441 CORBA::Long theNbOfSteps,
2442 CORBA::Boolean theMakeGroups):
2443 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2447 makeFlags( theMakeGroups )),
2448 myIsExtrusionByNormal( false )
2452 ExtrusionParams(const SMESH::DirStruct & theDir,
2453 CORBA::Long theNbOfSteps,
2454 CORBA::Boolean theMakeGroups,
2455 CORBA::Long theExtrFlags,
2456 CORBA::Double theSewTolerance):
2457 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2461 makeFlags( theMakeGroups, false, false,
2462 theExtrFlags, false ),
2464 myIsExtrusionByNormal( false )
2467 // params for extrusion by normal
2468 ExtrusionParams(CORBA::Double theStepSize,
2469 CORBA::Long theNbOfSteps,
2470 CORBA::Short theDim,
2471 CORBA::Boolean theByAverageNormal,
2472 CORBA::Boolean theUseInputElemsOnly,
2473 CORBA::Boolean theMakeGroups ):
2474 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2476 makeFlags( theMakeGroups,
2477 theByAverageNormal, theUseInputElemsOnly ),
2479 myIsExtrusionByNormal( true )
2485 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2490 //=======================================================================
2492 * \brief Generate dim+1 elements by extrusion of elements along vector
2493 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2494 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2495 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2496 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2497 * \param [in] nbOfSteps - number of elements to generate from one element
2498 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2499 * corresponding to groups the input elements included in.
2500 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2502 //=======================================================================
2504 SMESH::ListOfGroups*
2505 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2506 const SMESH::ListOfIDSources & theEdges,
2507 const SMESH::ListOfIDSources & theFaces,
2508 const SMESH::DirStruct & theStepVector,
2509 CORBA::Long theNbOfSteps,
2510 CORBA::Boolean theToMakeGroups)
2511 throw (SALOME::SALOME_Exception)
2516 ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
2518 TIDSortedElemSet elemsNodes[2];
2519 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2520 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2521 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2523 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2524 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2525 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2526 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2528 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2529 if ( myIsPreviewMode )
2531 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2532 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2533 // previewType = SMDSAbs_Edge;
2535 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2536 TPreviewMesh * tmpMesh = getPreviewMesh();
2537 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2538 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2539 workElements = & copyElements[0];
2541 params.SetNoGroups();
2543 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2545 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2546 ::SMESH_MeshEditor::PGroupIDs groupIds =
2547 getEditor().ExtrusionSweep( workElements, params, aHistory );
2549 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2551 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2553 if ( !myIsPreviewMode )
2555 dumpGroupsList( aPythonDump, aGroups );
2556 aPythonDump << this<< ".ExtrusionSweepObjects( "
2560 << theStepVector << ", "
2561 << TVar( theNbOfSteps ) << ", "
2562 << theToMakeGroups << " )";
2566 getPreviewMesh()->Remove( SMDSAbs_Volume );
2569 return aGroups ? aGroups : new SMESH::ListOfGroups;
2571 SMESH_CATCH( SMESH::throwCorbaException );
2575 //=======================================================================
2576 //function : ExtrusionByNormal
2578 //=======================================================================
2580 SMESH::ListOfGroups*
2581 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2582 CORBA::Double stepSize,
2583 CORBA::Long nbOfSteps,
2584 CORBA::Boolean byAverageNormal,
2585 CORBA::Boolean useInputElemsOnly,
2586 CORBA::Boolean makeGroups,
2588 throw (SALOME::SALOME_Exception)
2593 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2595 ExtrusionParams params( stepSize, nbOfSteps, dim,
2596 byAverageNormal, useInputElemsOnly, makeGroups );
2598 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2599 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2601 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2602 if (( elemTypes->length() == 1 ) &&
2603 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2604 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2607 TIDSortedElemSet elemsNodes[2];
2608 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2609 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2611 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2612 if ( myIsPreviewMode )
2614 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2615 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2616 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2617 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2618 workElements = & copyElements[0];
2620 params.SetNoGroups();
2623 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2624 ::SMESH_MeshEditor::PGroupIDs groupIds =
2625 getEditor().ExtrusionSweep( workElements, params, aHistory );
2627 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2629 if (!myIsPreviewMode) {
2630 dumpGroupsList(aPythonDump, aGroups);
2631 aPythonDump << this << ".ExtrusionByNormal( " << objects
2632 << ", " << TVar( stepSize )
2633 << ", " << TVar( nbOfSteps )
2634 << ", " << byAverageNormal
2635 << ", " << useInputElemsOnly
2636 << ", " << makeGroups
2642 getPreviewMesh()->Remove( SMDSAbs_Volume );
2645 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2647 return aGroups ? aGroups : new SMESH::ListOfGroups;
2649 SMESH_CATCH( SMESH::throwCorbaException );
2653 //=======================================================================
2654 //function : AdvancedExtrusion
2656 //=======================================================================
2658 SMESH::ListOfGroups*
2659 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2660 const SMESH::DirStruct & theStepVector,
2661 CORBA::Long theNbOfSteps,
2662 CORBA::Long theExtrFlags,
2663 CORBA::Double theSewTolerance,
2664 CORBA::Boolean theMakeGroups)
2665 throw (SALOME::SALOME_Exception)
2670 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2672 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2673 theExtrFlags, theSewTolerance );
2675 TIDSortedElemSet elemsNodes[2];
2676 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2678 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2679 ::SMESH_MeshEditor::PGroupIDs groupIds =
2680 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2682 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2684 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2686 if ( !myIsPreviewMode ) {
2687 dumpGroupsList(aPythonDump, aGroups);
2688 aPythonDump << this << ".AdvancedExtrusion( "
2689 << theIDsOfElements << ", "
2690 << theStepVector << ", "
2691 << theNbOfSteps << ", "
2692 << theExtrFlags << ", "
2693 << theSewTolerance << ", "
2694 << theMakeGroups << " )";
2698 getPreviewMesh()->Remove( SMDSAbs_Volume );
2701 return aGroups ? aGroups : new SMESH::ListOfGroups;
2703 SMESH_CATCH( SMESH::throwCorbaException );
2707 //================================================================================
2709 * \brief Convert extrusion error to IDL enum
2711 //================================================================================
2715 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2717 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2721 RETCASE( EXTR_NO_ELEMENTS );
2722 RETCASE( EXTR_PATH_NOT_EDGE );
2723 RETCASE( EXTR_BAD_PATH_SHAPE );
2724 RETCASE( EXTR_BAD_STARTING_NODE );
2725 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2726 RETCASE( EXTR_CANT_GET_TANGENT );
2728 return SMESH::SMESH_MeshEditor::EXTR_OK;
2732 //=======================================================================
2733 //function : extrusionAlongPath
2735 //=======================================================================
2736 SMESH::ListOfGroups*
2737 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2738 const SMESH::ListOfIDSources & theEdges,
2739 const SMESH::ListOfIDSources & theFaces,
2740 SMESH::SMESH_IDSource_ptr thePathMesh,
2741 GEOM::GEOM_Object_ptr thePathShape,
2742 CORBA::Long theNodeStart,
2743 CORBA::Boolean theHasAngles,
2744 const SMESH::double_array & theAngles,
2745 CORBA::Boolean theLinearVariation,
2746 CORBA::Boolean theHasRefPoint,
2747 const SMESH::PointStruct & theRefPoint,
2749 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2750 throw (SALOME::SALOME_Exception)
2755 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2757 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2758 if ( thePathMesh->_is_nil() )
2759 return aGroups._retn();
2762 SMESH_subMesh* aSubMesh = 0;
2763 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2764 if ( thePathShape->_is_nil() )
2766 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2767 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2769 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2770 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2771 if ( !aMeshImp ) return aGroups._retn();
2772 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2773 if ( !aSubMesh ) return aGroups._retn();
2775 else if ( !aMeshImp ||
2776 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2778 return aGroups._retn();
2783 if ( !aMeshImp ) return aGroups._retn();
2784 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2785 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2786 if ( !aSubMesh || !aSubMesh->GetSubMeshDS() )
2787 return aGroups._retn();
2790 SMDS_MeshNode* nodeStart =
2791 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2793 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2794 return aGroups._retn();
2797 TIDSortedElemSet elemsNodes[2];
2798 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2799 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2800 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2802 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2803 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2804 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2805 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2807 list<double> angles;
2808 for (int i = 0; i < theAngles.length(); i++) {
2809 angles.push_back( theAngles[i] );
2812 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2814 int nbOldGroups = myMesh->NbGroup();
2816 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2817 if ( myIsPreviewMode )
2819 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2820 TPreviewMesh * tmpMesh = getPreviewMesh();
2821 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2822 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2823 workElements = & copyElements[0];
2824 theMakeGroups = false;
2827 ::SMESH_MeshEditor::Extrusion_Error error;
2829 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2830 theHasAngles, angles, theLinearVariation,
2831 theHasRefPoint, refPnt, theMakeGroups );
2833 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2834 theHasAngles, angles, theLinearVariation,
2835 theHasRefPoint, refPnt, theMakeGroups );
2837 declareMeshModified( /*isReComputeSafe=*/true );
2838 theError = convExtrError( error );
2840 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2841 if ( theMakeGroups ) {
2842 list<int> groupIDs = myMesh->GetGroupIds();
2843 list<int>::iterator newBegin = groupIDs.begin();
2844 std::advance( newBegin, nbOldGroups ); // skip old groups
2845 groupIDs.erase( groupIDs.begin(), newBegin );
2846 aGroups = getGroups( & groupIDs );
2847 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2850 if ( !myIsPreviewMode ) {
2851 aPythonDump << "(" << aGroups << ", error) = "
2852 << this << ".ExtrusionAlongPathObjects( "
2856 << thePathMesh << ", "
2857 << thePathShape << ", "
2858 << theNodeStart << ", "
2859 << theHasAngles << ", "
2860 << theAngles << ", "
2861 << theLinearVariation << ", "
2862 << theHasRefPoint << ", "
2863 << "SMESH.PointStruct( "
2864 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2865 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2866 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2867 << theMakeGroups << " )";
2871 getPreviewMesh()->Remove( SMDSAbs_Volume );
2874 return aGroups._retn();
2876 SMESH_CATCH( SMESH::throwCorbaException );
2880 //================================================================================
2882 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2883 * of given angles along path steps
2884 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2885 * which proceeds the extrusion
2886 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2887 * is used to define the sub-mesh for the path
2889 //================================================================================
2891 SMESH::double_array*
2892 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2893 GEOM::GEOM_Object_ptr thePathShape,
2894 const SMESH::double_array & theAngles)
2896 SMESH::double_array_var aResult = new SMESH::double_array();
2897 int nbAngles = theAngles.length();
2898 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2900 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2901 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2902 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2903 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2904 return aResult._retn();
2905 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2906 if ( nbSteps == nbAngles )
2908 aResult.inout() = theAngles;
2912 aResult->length( nbSteps );
2913 double rAn2St = double( nbAngles ) / double( nbSteps );
2914 double angPrev = 0, angle;
2915 for ( int iSt = 0; iSt < nbSteps; ++iSt )
2917 double angCur = rAn2St * ( iSt+1 );
2918 double angCurFloor = floor( angCur );
2919 double angPrevFloor = floor( angPrev );
2920 if ( angPrevFloor == angCurFloor )
2921 angle = rAn2St * theAngles[ int( angCurFloor ) ];
2924 int iP = int( angPrevFloor );
2925 double angPrevCeil = ceil(angPrev);
2926 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2928 int iC = int( angCurFloor );
2929 if ( iC < nbAngles )
2930 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2932 iP = int( angPrevCeil );
2934 angle += theAngles[ iC ];
2936 aResult[ iSt ] = angle;
2941 // Update Python script
2942 TPythonDump() << "rotAngles = " << theAngles;
2943 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
2944 << thePathMesh << ", "
2945 << thePathShape << ", "
2948 return aResult._retn();
2951 //=======================================================================
2954 //=======================================================================
2956 SMESH::ListOfGroups*
2957 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
2958 const SMESH::AxisStruct & theAxis,
2959 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2960 CORBA::Boolean theCopy,
2962 ::SMESH_Mesh* theTargetMesh)
2963 throw (SALOME::SALOME_Exception)
2968 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2969 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2971 if ( theTargetMesh )
2975 switch ( theMirrorType ) {
2976 case SMESH::SMESH_MeshEditor::POINT:
2977 aTrsf.SetMirror( P );
2979 case SMESH::SMESH_MeshEditor::AXIS:
2980 aTrsf.SetMirror( gp_Ax1( P, V ));
2983 aTrsf.SetMirror( gp_Ax2( P, V ));
2986 TIDSortedElemSet copyElements;
2987 TIDSortedElemSet* workElements = & theElements;
2989 if ( myIsPreviewMode )
2991 TPreviewMesh * tmpMesh = getPreviewMesh();
2992 tmpMesh->Copy( theElements, copyElements);
2993 if ( !theCopy && !theTargetMesh )
2995 TIDSortedElemSet elemsAround, elemsAroundCopy;
2996 getElementsAround( theElements, getMeshDS(), elemsAround );
2997 tmpMesh->Copy( elemsAround, elemsAroundCopy);
2999 workElements = & copyElements;
3000 theMakeGroups = false;
3003 ::SMESH_MeshEditor::PGroupIDs groupIds =
3004 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3006 if ( theCopy && !myIsPreviewMode)
3008 if ( theTargetMesh )
3010 theTargetMesh->GetMeshDS()->Modified();
3014 declareMeshModified( /*isReComputeSafe=*/false );
3017 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3019 SMESH_CATCH( SMESH::throwCorbaException );
3023 //=======================================================================
3026 //=======================================================================
3028 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3029 const SMESH::AxisStruct & theAxis,
3030 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3031 CORBA::Boolean theCopy)
3032 throw (SALOME::SALOME_Exception)
3034 if ( !myIsPreviewMode ) {
3035 TPythonDump() << this << ".Mirror( "
3036 << theIDsOfElements << ", "
3038 << mirrorTypeName(theMirrorType) << ", "
3041 if ( theIDsOfElements.length() > 0 )
3043 TIDSortedElemSet elements;
3044 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3045 mirror(elements, theAxis, theMirrorType, theCopy, false);
3050 //=======================================================================
3051 //function : MirrorObject
3053 //=======================================================================
3055 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3056 const SMESH::AxisStruct & theAxis,
3057 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3058 CORBA::Boolean theCopy)
3059 throw (SALOME::SALOME_Exception)
3061 if ( !myIsPreviewMode ) {
3062 TPythonDump() << this << ".MirrorObject( "
3063 << theObject << ", "
3065 << mirrorTypeName(theMirrorType) << ", "
3068 TIDSortedElemSet elements;
3070 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3072 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3073 mirror(elements, theAxis, theMirrorType, theCopy, false);
3076 //=======================================================================
3077 //function : MirrorMakeGroups
3079 //=======================================================================
3081 SMESH::ListOfGroups*
3082 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3083 const SMESH::AxisStruct& theMirror,
3084 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3085 throw (SALOME::SALOME_Exception)
3087 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3089 SMESH::ListOfGroups * aGroups = 0;
3090 if ( theIDsOfElements.length() > 0 )
3092 TIDSortedElemSet elements;
3093 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3094 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3096 if (!myIsPreviewMode) {
3097 dumpGroupsList(aPythonDump, aGroups);
3098 aPythonDump << this << ".MirrorMakeGroups( "
3099 << theIDsOfElements << ", "
3100 << theMirror << ", "
3101 << mirrorTypeName(theMirrorType) << " )";
3106 //=======================================================================
3107 //function : MirrorObjectMakeGroups
3109 //=======================================================================
3111 SMESH::ListOfGroups*
3112 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3113 const SMESH::AxisStruct& theMirror,
3114 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3115 throw (SALOME::SALOME_Exception)
3117 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3119 SMESH::ListOfGroups * aGroups = 0;
3120 TIDSortedElemSet elements;
3121 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3122 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3124 if (!myIsPreviewMode)
3126 dumpGroupsList(aPythonDump,aGroups);
3127 aPythonDump << this << ".MirrorObjectMakeGroups( "
3128 << theObject << ", "
3129 << theMirror << ", "
3130 << mirrorTypeName(theMirrorType) << " )";
3135 //=======================================================================
3136 //function : MirrorMakeMesh
3138 //=======================================================================
3140 SMESH::SMESH_Mesh_ptr
3141 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3142 const SMESH::AxisStruct& theMirror,
3143 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3144 CORBA::Boolean theCopyGroups,
3145 const char* theMeshName)
3146 throw (SALOME::SALOME_Exception)
3148 SMESH_Mesh_i* mesh_i;
3149 SMESH::SMESH_Mesh_var mesh;
3150 { // open new scope to dump "MakeMesh" command
3151 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3153 TPythonDump pydump; // to prevent dump at mesh creation
3155 mesh = makeMesh( theMeshName );
3156 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3157 if (mesh_i && theIDsOfElements.length() > 0 )
3159 TIDSortedElemSet elements;
3160 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3161 mirror(elements, theMirror, theMirrorType,
3162 false, theCopyGroups, & mesh_i->GetImpl());
3163 mesh_i->CreateGroupServants();
3166 if (!myIsPreviewMode) {
3167 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3168 << theIDsOfElements << ", "
3169 << theMirror << ", "
3170 << mirrorTypeName(theMirrorType) << ", "
3171 << theCopyGroups << ", '"
3172 << theMeshName << "' )";
3177 if (!myIsPreviewMode && mesh_i)
3178 mesh_i->GetGroups();
3180 return mesh._retn();
3183 //=======================================================================
3184 //function : MirrorObjectMakeMesh
3186 //=======================================================================
3188 SMESH::SMESH_Mesh_ptr
3189 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3190 const SMESH::AxisStruct& theMirror,
3191 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3192 CORBA::Boolean theCopyGroups,
3193 const char* theMeshName)
3194 throw (SALOME::SALOME_Exception)
3196 SMESH_Mesh_i* mesh_i;
3197 SMESH::SMESH_Mesh_var mesh;
3198 { // open new scope to dump "MakeMesh" command
3199 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3201 TPythonDump pydump; // to prevent dump at mesh creation
3203 mesh = makeMesh( theMeshName );
3204 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3205 TIDSortedElemSet elements;
3207 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3209 mirror(elements, theMirror, theMirrorType,
3210 false, theCopyGroups, & mesh_i->GetImpl());
3211 mesh_i->CreateGroupServants();
3213 if (!myIsPreviewMode) {
3214 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3215 << theObject << ", "
3216 << theMirror << ", "
3217 << mirrorTypeName(theMirrorType) << ", "
3218 << theCopyGroups << ", '"
3219 << theMeshName << "' )";
3224 if (!myIsPreviewMode && mesh_i)
3225 mesh_i->GetGroups();
3227 return mesh._retn();
3230 //=======================================================================
3231 //function : translate
3233 //=======================================================================
3235 SMESH::ListOfGroups*
3236 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3237 const SMESH::DirStruct & theVector,
3238 CORBA::Boolean theCopy,
3240 ::SMESH_Mesh* theTargetMesh)
3241 throw (SALOME::SALOME_Exception)
3246 if ( theTargetMesh )
3250 const SMESH::PointStruct * P = &theVector.PS;
3251 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3253 TIDSortedElemSet copyElements;
3254 TIDSortedElemSet* workElements = &theElements;
3256 if ( myIsPreviewMode )
3258 TPreviewMesh * tmpMesh = getPreviewMesh();
3259 tmpMesh->Copy( theElements, copyElements);
3260 if ( !theCopy && !theTargetMesh )
3262 TIDSortedElemSet elemsAround, elemsAroundCopy;
3263 getElementsAround( theElements, getMeshDS(), elemsAround );
3264 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3266 workElements = & copyElements;
3267 theMakeGroups = false;
3270 ::SMESH_MeshEditor::PGroupIDs groupIds =
3271 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3273 if ( theCopy && !myIsPreviewMode )
3275 if ( theTargetMesh )
3277 theTargetMesh->GetMeshDS()->Modified();
3281 declareMeshModified( /*isReComputeSafe=*/false );
3285 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3287 SMESH_CATCH( SMESH::throwCorbaException );
3291 //=======================================================================
3292 //function : Translate
3294 //=======================================================================
3296 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3297 const SMESH::DirStruct & theVector,
3298 CORBA::Boolean theCopy)
3299 throw (SALOME::SALOME_Exception)
3301 if (!myIsPreviewMode) {
3302 TPythonDump() << this << ".Translate( "
3303 << theIDsOfElements << ", "
3304 << theVector << ", "
3307 if (theIDsOfElements.length()) {
3308 TIDSortedElemSet elements;
3309 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3310 translate(elements, theVector, theCopy, false);
3314 //=======================================================================
3315 //function : TranslateObject
3317 //=======================================================================
3319 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3320 const SMESH::DirStruct & theVector,
3321 CORBA::Boolean theCopy)
3322 throw (SALOME::SALOME_Exception)
3324 if (!myIsPreviewMode) {
3325 TPythonDump() << this << ".TranslateObject( "
3326 << theObject << ", "
3327 << theVector << ", "
3330 TIDSortedElemSet elements;
3332 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3334 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3335 translate(elements, theVector, theCopy, false);
3338 //=======================================================================
3339 //function : TranslateMakeGroups
3341 //=======================================================================
3343 SMESH::ListOfGroups*
3344 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3345 const SMESH::DirStruct& theVector)
3346 throw (SALOME::SALOME_Exception)
3348 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3350 SMESH::ListOfGroups * aGroups = 0;
3351 if (theIDsOfElements.length()) {
3352 TIDSortedElemSet elements;
3353 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3354 aGroups = translate(elements,theVector,true,true);
3356 if (!myIsPreviewMode) {
3357 dumpGroupsList(aPythonDump, aGroups);
3358 aPythonDump << this << ".TranslateMakeGroups( "
3359 << theIDsOfElements << ", "
3360 << theVector << " )";
3365 //=======================================================================
3366 //function : TranslateObjectMakeGroups
3368 //=======================================================================
3370 SMESH::ListOfGroups*
3371 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3372 const SMESH::DirStruct& theVector)
3373 throw (SALOME::SALOME_Exception)
3375 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3377 SMESH::ListOfGroups * aGroups = 0;
3378 TIDSortedElemSet elements;
3379 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3380 aGroups = translate(elements, theVector, true, true);
3382 if (!myIsPreviewMode) {
3383 dumpGroupsList(aPythonDump, aGroups);
3384 aPythonDump << this << ".TranslateObjectMakeGroups( "
3385 << theObject << ", "
3386 << theVector << " )";
3391 //=======================================================================
3392 //function : TranslateMakeMesh
3394 //=======================================================================
3396 SMESH::SMESH_Mesh_ptr
3397 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3398 const SMESH::DirStruct& theVector,
3399 CORBA::Boolean theCopyGroups,
3400 const char* theMeshName)
3401 throw (SALOME::SALOME_Exception)
3403 SMESH_Mesh_i* mesh_i;
3404 SMESH::SMESH_Mesh_var mesh;
3406 { // open new scope to dump "MakeMesh" command
3407 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3409 TPythonDump pydump; // to prevent dump at mesh creation
3411 mesh = makeMesh( theMeshName );
3412 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3414 if ( mesh_i && theIDsOfElements.length() )
3416 TIDSortedElemSet elements;
3417 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3418 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3419 mesh_i->CreateGroupServants();
3422 if ( !myIsPreviewMode ) {
3423 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3424 << theIDsOfElements << ", "
3425 << theVector << ", "
3426 << theCopyGroups << ", '"
3427 << theMeshName << "' )";
3432 if (!myIsPreviewMode && mesh_i)
3433 mesh_i->GetGroups();
3435 return mesh._retn();
3438 //=======================================================================
3439 //function : TranslateObjectMakeMesh
3441 //=======================================================================
3443 SMESH::SMESH_Mesh_ptr
3444 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3445 const SMESH::DirStruct& theVector,
3446 CORBA::Boolean theCopyGroups,
3447 const char* theMeshName)
3448 throw (SALOME::SALOME_Exception)
3451 SMESH_Mesh_i* mesh_i;
3452 SMESH::SMESH_Mesh_var mesh;
3453 { // open new scope to dump "MakeMesh" command
3454 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3456 TPythonDump pydump; // to prevent dump at mesh creation
3457 mesh = makeMesh( theMeshName );
3458 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3460 TIDSortedElemSet elements;
3462 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3464 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3465 mesh_i->CreateGroupServants();
3467 if ( !myIsPreviewMode ) {
3468 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3469 << theObject << ", "
3470 << theVector << ", "
3471 << theCopyGroups << ", '"
3472 << theMeshName << "' )";
3477 if (!myIsPreviewMode && mesh_i)
3478 mesh_i->GetGroups();
3480 return mesh._retn();
3482 SMESH_CATCH( SMESH::throwCorbaException );
3486 //=======================================================================
3489 //=======================================================================
3491 SMESH::ListOfGroups*
3492 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3493 const SMESH::AxisStruct & theAxis,
3494 CORBA::Double theAngle,
3495 CORBA::Boolean theCopy,
3497 ::SMESH_Mesh* theTargetMesh)
3498 throw (SALOME::SALOME_Exception)
3503 if ( theTargetMesh )
3506 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3507 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3510 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3512 TIDSortedElemSet copyElements;
3513 TIDSortedElemSet* workElements = &theElements;
3514 if ( myIsPreviewMode ) {
3515 TPreviewMesh * tmpMesh = getPreviewMesh();
3516 tmpMesh->Copy( theElements, copyElements );
3517 if ( !theCopy && !theTargetMesh )
3519 TIDSortedElemSet elemsAround, elemsAroundCopy;
3520 getElementsAround( theElements, getMeshDS(), elemsAround );
3521 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3523 workElements = ©Elements;
3524 theMakeGroups = false;
3527 ::SMESH_MeshEditor::PGroupIDs groupIds =
3528 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3530 if ( theCopy && !myIsPreviewMode)
3532 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3533 else declareMeshModified( /*isReComputeSafe=*/false );
3536 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3538 SMESH_CATCH( SMESH::throwCorbaException );
3542 //=======================================================================
3545 //=======================================================================
3547 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3548 const SMESH::AxisStruct & theAxis,
3549 CORBA::Double theAngle,
3550 CORBA::Boolean theCopy)
3551 throw (SALOME::SALOME_Exception)
3553 if (!myIsPreviewMode) {
3554 TPythonDump() << this << ".Rotate( "
3555 << theIDsOfElements << ", "
3557 << TVar( theAngle ) << ", "
3560 if (theIDsOfElements.length() > 0)
3562 TIDSortedElemSet elements;
3563 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3564 rotate(elements,theAxis,theAngle,theCopy,false);
3568 //=======================================================================
3569 //function : RotateObject
3571 //=======================================================================
3573 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3574 const SMESH::AxisStruct & theAxis,
3575 CORBA::Double theAngle,
3576 CORBA::Boolean theCopy)
3577 throw (SALOME::SALOME_Exception)
3579 if ( !myIsPreviewMode ) {
3580 TPythonDump() << this << ".RotateObject( "
3581 << theObject << ", "
3583 << TVar( theAngle ) << ", "
3586 TIDSortedElemSet elements;
3587 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3588 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3589 rotate(elements,theAxis,theAngle,theCopy,false);
3592 //=======================================================================
3593 //function : RotateMakeGroups
3595 //=======================================================================
3597 SMESH::ListOfGroups*
3598 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3599 const SMESH::AxisStruct& theAxis,
3600 CORBA::Double theAngle)
3601 throw (SALOME::SALOME_Exception)
3603 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3605 SMESH::ListOfGroups * aGroups = 0;
3606 if (theIDsOfElements.length() > 0)
3608 TIDSortedElemSet elements;
3609 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3610 aGroups = rotate(elements,theAxis,theAngle,true,true);
3612 if (!myIsPreviewMode) {
3613 dumpGroupsList(aPythonDump, aGroups);
3614 aPythonDump << this << ".RotateMakeGroups( "
3615 << theIDsOfElements << ", "
3617 << TVar( theAngle ) << " )";
3622 //=======================================================================
3623 //function : RotateObjectMakeGroups
3625 //=======================================================================
3627 SMESH::ListOfGroups*
3628 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3629 const SMESH::AxisStruct& theAxis,
3630 CORBA::Double theAngle)
3631 throw (SALOME::SALOME_Exception)
3633 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3635 SMESH::ListOfGroups * aGroups = 0;
3636 TIDSortedElemSet elements;
3637 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3638 aGroups = rotate(elements, theAxis, theAngle, true, true);
3640 if (!myIsPreviewMode) {
3641 dumpGroupsList(aPythonDump, aGroups);
3642 aPythonDump << this << ".RotateObjectMakeGroups( "
3643 << theObject << ", "
3645 << TVar( theAngle ) << " )";
3650 //=======================================================================
3651 //function : RotateMakeMesh
3653 //=======================================================================
3655 SMESH::SMESH_Mesh_ptr
3656 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3657 const SMESH::AxisStruct& theAxis,
3658 CORBA::Double theAngleInRadians,
3659 CORBA::Boolean theCopyGroups,
3660 const char* theMeshName)
3661 throw (SALOME::SALOME_Exception)
3664 SMESH::SMESH_Mesh_var mesh;
3665 SMESH_Mesh_i* mesh_i;
3667 { // open new scope to dump "MakeMesh" command
3668 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3670 TPythonDump pydump; // to prevent dump at mesh creation
3672 mesh = makeMesh( theMeshName );
3673 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3675 if ( mesh_i && theIDsOfElements.length() > 0 )
3677 TIDSortedElemSet elements;
3678 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3679 rotate(elements, theAxis, theAngleInRadians,
3680 false, theCopyGroups, & mesh_i->GetImpl());
3681 mesh_i->CreateGroupServants();
3683 if ( !myIsPreviewMode ) {
3684 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3685 << theIDsOfElements << ", "
3687 << TVar( theAngleInRadians ) << ", "
3688 << theCopyGroups << ", '"
3689 << theMeshName << "' )";
3694 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3695 mesh_i->GetGroups();
3697 return mesh._retn();
3699 SMESH_CATCH( SMESH::throwCorbaException );
3703 //=======================================================================
3704 //function : RotateObjectMakeMesh
3706 //=======================================================================
3708 SMESH::SMESH_Mesh_ptr
3709 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3710 const SMESH::AxisStruct& theAxis,
3711 CORBA::Double theAngleInRadians,
3712 CORBA::Boolean theCopyGroups,
3713 const char* theMeshName)
3714 throw (SALOME::SALOME_Exception)
3717 SMESH::SMESH_Mesh_var mesh;
3718 SMESH_Mesh_i* mesh_i;
3720 {// open new scope to dump "MakeMesh" command
3721 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3723 TPythonDump pydump; // to prevent dump at mesh creation
3724 mesh = makeMesh( theMeshName );
3725 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3727 TIDSortedElemSet elements;
3729 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3731 rotate(elements, theAxis, theAngleInRadians,
3732 false, theCopyGroups, & mesh_i->GetImpl());
3733 mesh_i->CreateGroupServants();
3735 if ( !myIsPreviewMode ) {
3736 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3737 << theObject << ", "
3739 << TVar( theAngleInRadians ) << ", "
3740 << theCopyGroups << ", '"
3741 << theMeshName << "' )";
3746 if (!myIsPreviewMode && mesh_i)
3747 mesh_i->GetGroups();
3749 return mesh._retn();
3751 SMESH_CATCH( SMESH::throwCorbaException );
3755 //=======================================================================
3758 //=======================================================================
3760 SMESH::ListOfGroups*
3761 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3762 const SMESH::PointStruct& thePoint,
3763 const SMESH::double_array& theScaleFact,
3764 CORBA::Boolean theCopy,
3766 ::SMESH_Mesh* theTargetMesh)
3767 throw (SALOME::SALOME_Exception)
3771 if ( theScaleFact.length() < 1 )
3772 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3773 if ( theScaleFact.length() == 2 )
3774 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3776 if ( theTargetMesh )
3779 TIDSortedElemSet elements;
3780 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3781 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3786 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3787 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3789 double tol = std::numeric_limits<double>::max();
3792 #if OCC_VERSION_LARGE > 0x06070100
3793 // fight against ortagonalization
3794 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3795 // 0, S[1], 0, thePoint.y * (1-S[1]),
3796 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3797 aTrsf.SetTranslation( gp_Vec( thePoint.x * (1-S[0]),
3798 thePoint.y * (1-S[1]),
3799 thePoint.z * (1-S[2])));
3800 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3801 M.SetDiagonal( S[0], S[1], S[2] );
3804 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3805 0, S[1], 0, thePoint.y * (1-S[1]),
3806 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3809 TIDSortedElemSet copyElements;
3810 TIDSortedElemSet* workElements = &elements;
3811 if ( myIsPreviewMode )
3813 TPreviewMesh * tmpMesh = getPreviewMesh();
3814 tmpMesh->Copy( elements, copyElements);
3815 if ( !theCopy && !theTargetMesh )
3817 TIDSortedElemSet elemsAround, elemsAroundCopy;
3818 getElementsAround( elements, getMeshDS(), elemsAround );
3819 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3821 workElements = & copyElements;
3822 theMakeGroups = false;
3825 ::SMESH_MeshEditor::PGroupIDs groupIds =
3826 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3828 if ( theCopy && !myIsPreviewMode )
3830 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3831 else declareMeshModified( /*isReComputeSafe=*/false );
3833 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3835 SMESH_CATCH( SMESH::throwCorbaException );
3839 //=======================================================================
3842 //=======================================================================
3844 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3845 const SMESH::PointStruct& thePoint,
3846 const SMESH::double_array& theScaleFact,
3847 CORBA::Boolean theCopy)
3848 throw (SALOME::SALOME_Exception)
3850 if ( !myIsPreviewMode ) {
3851 TPythonDump() << this << ".Scale( "
3852 << theObject << ", "
3854 << TVar( theScaleFact ) << ", "
3857 scale(theObject, thePoint, theScaleFact, theCopy, false);
3861 //=======================================================================
3862 //function : ScaleMakeGroups
3864 //=======================================================================
3866 SMESH::ListOfGroups*
3867 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3868 const SMESH::PointStruct& thePoint,
3869 const SMESH::double_array& theScaleFact)
3870 throw (SALOME::SALOME_Exception)
3872 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3874 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3875 if (!myIsPreviewMode) {
3876 dumpGroupsList(aPythonDump, aGroups);
3877 aPythonDump << this << ".Scale("
3880 << TVar( theScaleFact ) << ",True,True)";
3886 //=======================================================================
3887 //function : ScaleMakeMesh
3889 //=======================================================================
3891 SMESH::SMESH_Mesh_ptr
3892 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3893 const SMESH::PointStruct& thePoint,
3894 const SMESH::double_array& theScaleFact,
3895 CORBA::Boolean theCopyGroups,
3896 const char* theMeshName)
3897 throw (SALOME::SALOME_Exception)
3899 SMESH_Mesh_i* mesh_i;
3900 SMESH::SMESH_Mesh_var mesh;
3901 { // open new scope to dump "MakeMesh" command
3902 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3904 TPythonDump pydump; // to prevent dump at mesh creation
3905 mesh = makeMesh( theMeshName );
3906 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3910 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3911 mesh_i->CreateGroupServants();
3913 if ( !myIsPreviewMode )
3914 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3915 << theObject << ", "
3917 << TVar( theScaleFact ) << ", "
3918 << theCopyGroups << ", '"
3919 << theMeshName << "' )";
3923 if (!myIsPreviewMode && mesh_i)
3924 mesh_i->GetGroups();
3926 return mesh._retn();
3930 //=======================================================================
3931 //function : FindCoincidentNodes
3933 //=======================================================================
3935 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tolerance,
3936 SMESH::array_of_long_array_out GroupsOfNodes)
3937 throw (SALOME::SALOME_Exception)
3942 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3943 TIDSortedNodeSet nodes; // no input nodes
3944 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3946 GroupsOfNodes = new SMESH::array_of_long_array;
3947 GroupsOfNodes->length( aListOfListOfNodes.size() );
3948 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3949 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3950 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3951 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3952 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3953 aGroup.length( aListOfNodes.size() );
3954 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3955 aGroup[ j ] = (*lIt)->GetID();
3957 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3958 << Tolerance << " )";
3960 SMESH_CATCH( SMESH::throwCorbaException );
3963 //=======================================================================
3964 //function : FindCoincidentNodesOnPart
3966 //=======================================================================
3968 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
3969 CORBA::Double Tolerance,
3970 SMESH::array_of_long_array_out GroupsOfNodes)
3971 throw (SALOME::SALOME_Exception)
3976 TIDSortedNodeSet nodes;
3977 idSourceToNodeSet( theObject, getMeshDS(), nodes );
3979 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3981 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3983 GroupsOfNodes = new SMESH::array_of_long_array;
3984 GroupsOfNodes->length( aListOfListOfNodes.size() );
3985 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3986 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3988 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3989 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3990 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3991 aGroup.length( aListOfNodes.size() );
3992 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3993 aGroup[ j ] = (*lIt)->GetID();
3995 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
3997 << Tolerance << " )";
3999 SMESH_CATCH( SMESH::throwCorbaException );
4002 //================================================================================
4004 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4005 * ExceptSubMeshOrGroups
4007 //================================================================================
4009 void SMESH_MeshEditor_i::
4010 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4011 CORBA::Double theTolerance,
4012 SMESH::array_of_long_array_out theGroupsOfNodes,
4013 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups)
4014 throw (SALOME::SALOME_Exception)
4019 TIDSortedNodeSet nodes;
4020 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4022 for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4024 TIDSortedNodeSet exceptNodes;
4025 idSourceToNodeSet( theExceptSubMeshOrGroups[i], getMeshDS(), exceptNodes );
4026 TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
4027 for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
4028 nodes.erase( *avoidNode );
4030 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4032 getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
4034 theGroupsOfNodes = new SMESH::array_of_long_array;
4035 theGroupsOfNodes->length( aListOfListOfNodes.size() );
4036 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4037 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4039 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4040 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4041 SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
4042 aGroup.length( aListOfNodes.size() );
4043 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4044 aGroup[ j ] = (*lIt)->GetID();
4046 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4048 << theTolerance << ", "
4049 << theExceptSubMeshOrGroups << " )";
4051 SMESH_CATCH( SMESH::throwCorbaException );
4054 //=======================================================================
4055 //function : MergeNodes
4057 //=======================================================================
4059 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
4060 throw (SALOME::SALOME_Exception)
4065 SMESHDS_Mesh* aMesh = getMeshDS();
4067 TPythonDump aTPythonDump;
4068 aTPythonDump << this << ".MergeNodes([";
4069 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4070 for (int i = 0; i < GroupsOfNodes.length(); i++)
4072 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4073 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4074 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4075 for ( int j = 0; j < aNodeGroup.length(); j++ )
4077 CORBA::Long index = aNodeGroup[ j ];
4078 const SMDS_MeshNode * node = aMesh->FindNode(index);
4080 aListOfNodes.push_back( node );
4082 if ( aListOfNodes.size() < 2 )
4083 aListOfListOfNodes.pop_back();
4085 if ( i > 0 ) aTPythonDump << ", ";
4086 aTPythonDump << aNodeGroup;
4088 getEditor().MergeNodes( aListOfListOfNodes );
4090 aTPythonDump << "])";
4092 declareMeshModified( /*isReComputeSafe=*/false );
4094 SMESH_CATCH( SMESH::throwCorbaException );
4097 //=======================================================================
4098 //function : FindEqualElements
4100 //=======================================================================
4102 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4103 SMESH::array_of_long_array_out GroupsOfElementsID)
4104 throw (SALOME::SALOME_Exception)
4109 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4110 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4112 TIDSortedElemSet elems;
4113 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4115 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4116 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4118 GroupsOfElementsID = new SMESH::array_of_long_array;
4119 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4121 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4122 aListOfListOfElementsID.begin();
4123 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4125 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4126 list<int>& listOfIDs = *arraysIt;
4127 aGroup.length( listOfIDs.size() );
4128 list<int>::iterator idIt = listOfIDs.begin();
4129 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4130 aGroup[ k ] = *idIt;
4133 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4137 SMESH_CATCH( SMESH::throwCorbaException );
4140 //=======================================================================
4141 //function : MergeElements
4143 //=======================================================================
4145 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4146 throw (SALOME::SALOME_Exception)
4151 TPythonDump aTPythonDump;
4152 aTPythonDump << this << ".MergeElements( [";
4154 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4156 for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4157 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4158 aListOfListOfElementsID.push_back( list< int >() );
4159 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4160 for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4161 CORBA::Long id = anElemsIDGroup[ j ];
4162 aListOfElemsID.push_back( id );
4164 if ( aListOfElemsID.size() < 2 )
4165 aListOfListOfElementsID.pop_back();
4166 if ( i > 0 ) aTPythonDump << ", ";
4167 aTPythonDump << anElemsIDGroup;
4170 getEditor().MergeElements(aListOfListOfElementsID);
4172 declareMeshModified( /*isReComputeSafe=*/true );
4174 aTPythonDump << "] )";
4176 SMESH_CATCH( SMESH::throwCorbaException );
4179 //=======================================================================
4180 //function : MergeEqualElements
4182 //=======================================================================
4184 void SMESH_MeshEditor_i::MergeEqualElements()
4185 throw (SALOME::SALOME_Exception)
4190 getEditor().MergeEqualElements();
4192 declareMeshModified( /*isReComputeSafe=*/true );
4194 TPythonDump() << this << ".MergeEqualElements()";
4196 SMESH_CATCH( SMESH::throwCorbaException );
4199 //=============================================================================
4201 * Move the node to a given point
4203 //=============================================================================
4205 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4209 throw (SALOME::SALOME_Exception)
4212 initData(/*deleteSearchers=*/false);
4214 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4218 if ( theNodeSearcher )
4219 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4221 if ( myIsPreviewMode ) // make preview data
4223 // in a preview mesh, make edges linked to a node
4224 TPreviewMesh& tmpMesh = *getPreviewMesh();
4225 TIDSortedElemSet linkedNodes;
4226 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4227 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4228 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4229 for ( ; nIt != linkedNodes.end(); ++nIt )
4231 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4232 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4236 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4237 // fill preview data
4239 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4240 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4242 getMeshDS()->MoveNode(node, x, y, z);
4244 if ( !myIsPreviewMode )
4246 // Update Python script
4247 TPythonDump() << "isDone = " << this << ".MoveNode( "
4248 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4249 declareMeshModified( /*isReComputeSafe=*/false );
4252 SMESH_CATCH( SMESH::throwCorbaException );
4257 //================================================================================
4259 * \brief Return ID of node closest to a given point
4261 //================================================================================
4263 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4266 throw (SALOME::SALOME_Exception)
4269 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4271 if ( !theNodeSearcher ) {
4272 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4275 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4276 return node->GetID();
4278 SMESH_CATCH( SMESH::throwCorbaException );
4282 //================================================================================
4284 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4285 * move the node closest to the point to point's location and return ID of the node
4287 //================================================================================
4289 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4292 CORBA::Long theNodeID)
4293 throw (SALOME::SALOME_Exception)
4296 // We keep theNodeSearcher until any mesh modification:
4297 // 1) initData() deletes theNodeSearcher at any edition,
4298 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4300 initData(/*deleteSearchers=*/false);
4302 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4304 int nodeID = theNodeID;
4305 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4306 if ( !node ) // preview moving node
4308 if ( !theNodeSearcher ) {
4309 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4312 node = theNodeSearcher->FindClosestTo( p );
4315 nodeID = node->GetID();
4316 if ( myIsPreviewMode ) // make preview data
4318 // in a preview mesh, make edges linked to a node
4319 TPreviewMesh tmpMesh = *getPreviewMesh();
4320 TIDSortedElemSet linkedNodes;
4321 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4322 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4323 for ( ; nIt != linkedNodes.end(); ++nIt )
4325 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4326 tmpMesh.Copy( &edge );
4329 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4331 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4332 // fill preview data
4334 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4336 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4340 getMeshDS()->MoveNode(node, x, y, z);
4344 if ( !myIsPreviewMode )
4346 TPythonDump() << "nodeID = " << this
4347 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4348 << ", " << nodeID << " )";
4350 declareMeshModified( /*isReComputeSafe=*/false );
4355 SMESH_CATCH( SMESH::throwCorbaException );
4359 //=======================================================================
4361 * Return elements of given type where the given point is IN or ON.
4363 * 'ALL' type means elements of any type excluding nodes
4365 //=======================================================================
4367 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4370 SMESH::ElementType type)
4371 throw (SALOME::SALOME_Exception)
4374 SMESH::long_array_var res = new SMESH::long_array;
4375 vector< const SMDS_MeshElement* > foundElems;
4377 theSearchersDeleter.Set( myMesh );
4378 if ( !theElementSearcher ) {
4379 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4381 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4382 SMDSAbs_ElementType( type ),
4384 res->length( foundElems.size() );
4385 for ( int i = 0; i < foundElems.size(); ++i )
4386 res[i] = foundElems[i]->GetID();
4390 SMESH_CATCH( SMESH::throwCorbaException );
4394 //=======================================================================
4395 //function : FindAmongElementsByPoint
4396 //purpose : Searching among the given elements, return elements of given type
4397 // where the given point is IN or ON.
4398 // 'ALL' type means elements of any type excluding nodes
4399 //=======================================================================
4402 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4406 SMESH::ElementType type)
4407 throw (SALOME::SALOME_Exception)
4410 SMESH::long_array_var res = new SMESH::long_array;
4412 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4413 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4414 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4415 type != types[0] ) // but search of elements of dim > 0
4418 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4419 return FindElementsByPoint( x,y,z, type );
4421 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4423 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4424 if ( !theElementSearcher )
4426 // create a searcher from elementIDs
4427 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4428 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4430 if ( !idSourceToSet( elementIDs, meshDS, elements,
4431 SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4434 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4435 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4437 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4440 vector< const SMDS_MeshElement* > foundElems;
4442 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4443 SMDSAbs_ElementType( type ),
4445 res->length( foundElems.size() );
4446 for ( int i = 0; i < foundElems.size(); ++i )
4447 res[i] = foundElems[i]->GetID();
4451 SMESH_CATCH( SMESH::throwCorbaException );
4455 //=======================================================================
4456 //function : GetPointState
4457 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4458 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4459 //=======================================================================
4461 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4464 throw (SALOME::SALOME_Exception)
4467 theSearchersDeleter.Set( myMesh );
4468 if ( !theElementSearcher ) {
4469 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4471 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4473 SMESH_CATCH( SMESH::throwCorbaException );
4477 //=======================================================================
4478 //function : convError
4480 //=======================================================================
4482 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4484 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4488 RETCASE( SEW_BORDER1_NOT_FOUND );
4489 RETCASE( SEW_BORDER2_NOT_FOUND );
4490 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4491 RETCASE( SEW_BAD_SIDE_NODES );
4492 RETCASE( SEW_VOLUMES_TO_SPLIT );
4493 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4494 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4495 RETCASE( SEW_BAD_SIDE1_NODES );
4496 RETCASE( SEW_BAD_SIDE2_NODES );
4498 return SMESH::SMESH_MeshEditor::SEW_OK;
4501 //=======================================================================
4502 //function : SewFreeBorders
4504 //=======================================================================
4506 SMESH::SMESH_MeshEditor::Sew_Error
4507 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4508 CORBA::Long SecondNodeID1,
4509 CORBA::Long LastNodeID1,
4510 CORBA::Long FirstNodeID2,
4511 CORBA::Long SecondNodeID2,
4512 CORBA::Long LastNodeID2,
4513 CORBA::Boolean CreatePolygons,
4514 CORBA::Boolean CreatePolyedrs)
4515 throw (SALOME::SALOME_Exception)
4520 SMESHDS_Mesh* aMesh = getMeshDS();
4522 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4523 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4524 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4525 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4526 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4527 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4529 if (!aBorderFirstNode ||
4530 !aBorderSecondNode||
4532 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4533 if (!aSide2FirstNode ||
4534 !aSide2SecondNode ||
4536 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4538 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4539 << FirstNodeID1 << ", "
4540 << SecondNodeID1 << ", "
4541 << LastNodeID1 << ", "
4542 << FirstNodeID2 << ", "
4543 << SecondNodeID2 << ", "
4544 << LastNodeID2 << ", "
4545 << CreatePolygons<< ", "
4546 << CreatePolyedrs<< " )";
4548 SMESH::SMESH_MeshEditor::Sew_Error error =
4549 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4560 declareMeshModified( /*isReComputeSafe=*/false );
4563 SMESH_CATCH( SMESH::throwCorbaException );
4564 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4568 //=======================================================================
4569 //function : SewConformFreeBorders
4571 //=======================================================================
4573 SMESH::SMESH_MeshEditor::Sew_Error
4574 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4575 CORBA::Long SecondNodeID1,
4576 CORBA::Long LastNodeID1,
4577 CORBA::Long FirstNodeID2,
4578 CORBA::Long SecondNodeID2)
4579 throw (SALOME::SALOME_Exception)
4584 SMESHDS_Mesh* aMesh = getMeshDS();
4586 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4587 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4588 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4589 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4590 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4591 const SMDS_MeshNode* aSide2ThirdNode = 0;
4593 if (!aBorderFirstNode ||
4594 !aBorderSecondNode||
4596 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4597 if (!aSide2FirstNode ||
4599 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4601 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4602 << FirstNodeID1 << ", "
4603 << SecondNodeID1 << ", "
4604 << LastNodeID1 << ", "
4605 << FirstNodeID2 << ", "
4606 << SecondNodeID2 << " )";
4608 SMESH::SMESH_MeshEditor::Sew_Error error =
4609 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4618 declareMeshModified( /*isReComputeSafe=*/false );
4621 SMESH_CATCH( SMESH::throwCorbaException );
4622 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4626 //=======================================================================
4627 //function : SewBorderToSide
4629 //=======================================================================
4631 SMESH::SMESH_MeshEditor::Sew_Error
4632 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4633 CORBA::Long SecondNodeIDOnFreeBorder,
4634 CORBA::Long LastNodeIDOnFreeBorder,
4635 CORBA::Long FirstNodeIDOnSide,
4636 CORBA::Long LastNodeIDOnSide,
4637 CORBA::Boolean CreatePolygons,
4638 CORBA::Boolean CreatePolyedrs)
4639 throw (SALOME::SALOME_Exception)
4644 SMESHDS_Mesh* aMesh = getMeshDS();
4646 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4647 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4648 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4649 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4650 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4651 const SMDS_MeshNode* aSide2ThirdNode = 0;
4653 if (!aBorderFirstNode ||
4654 !aBorderSecondNode||
4656 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4657 if (!aSide2FirstNode ||
4659 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4661 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4662 << FirstNodeIDOnFreeBorder << ", "
4663 << SecondNodeIDOnFreeBorder << ", "
4664 << LastNodeIDOnFreeBorder << ", "
4665 << FirstNodeIDOnSide << ", "
4666 << LastNodeIDOnSide << ", "
4667 << CreatePolygons << ", "
4668 << CreatePolyedrs << ") ";
4670 SMESH::SMESH_MeshEditor::Sew_Error error =
4671 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4681 declareMeshModified( /*isReComputeSafe=*/false );
4684 SMESH_CATCH( SMESH::throwCorbaException );
4685 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4689 //=======================================================================
4690 //function : SewSideElements
4692 //=======================================================================
4694 SMESH::SMESH_MeshEditor::Sew_Error
4695 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4696 const SMESH::long_array& IDsOfSide2Elements,
4697 CORBA::Long NodeID1OfSide1ToMerge,
4698 CORBA::Long NodeID1OfSide2ToMerge,
4699 CORBA::Long NodeID2OfSide1ToMerge,
4700 CORBA::Long NodeID2OfSide2ToMerge)
4701 throw (SALOME::SALOME_Exception)
4706 SMESHDS_Mesh* aMesh = getMeshDS();
4708 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
4709 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
4710 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4711 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4713 if (!aFirstNode1ToMerge ||
4714 !aFirstNode2ToMerge )
4715 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4716 if (!aSecondNode1ToMerge||
4717 !aSecondNode2ToMerge)
4718 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4720 TIDSortedElemSet aSide1Elems, aSide2Elems;
4721 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4722 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4724 TPythonDump() << "error = " << this << ".SewSideElements( "
4725 << IDsOfSide1Elements << ", "
4726 << IDsOfSide2Elements << ", "
4727 << NodeID1OfSide1ToMerge << ", "
4728 << NodeID1OfSide2ToMerge << ", "
4729 << NodeID2OfSide1ToMerge << ", "
4730 << NodeID2OfSide2ToMerge << ")";
4732 SMESH::SMESH_MeshEditor::Sew_Error error =
4733 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
4736 aSecondNode1ToMerge,
4737 aSecondNode2ToMerge));
4739 declareMeshModified( /*isReComputeSafe=*/false );
4742 SMESH_CATCH( SMESH::throwCorbaException );
4743 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4746 //================================================================================
4748 * \brief Set new nodes for given element
4749 * \param ide - element id
4750 * \param newIDs - new node ids
4751 * \retval CORBA::Boolean - true if result is OK
4753 //================================================================================
4755 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4756 const SMESH::long_array& newIDs)
4757 throw (SALOME::SALOME_Exception)
4762 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
4763 if(!elem) return false;
4765 int nbn = newIDs.length();
4767 vector<const SMDS_MeshNode*> aNodes(nbn);
4770 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
4773 aNodes[nbn1] = aNode;
4776 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4777 << ide << ", " << newIDs << " )";
4779 MESSAGE("ChangeElementNodes");
4780 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4782 declareMeshModified( /*isReComputeSafe=*/ !res );
4786 SMESH_CATCH( SMESH::throwCorbaException );
4790 //=======================================================================
4792 * \brief Makes a part of the mesh quadratic or bi-quadratic
4794 //=======================================================================
4796 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
4797 CORBA::Boolean theToBiQuad,
4798 SMESH::SMESH_IDSource_ptr theObject)
4799 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)
4831 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
4832 TPythonDump() << this << ".ConvertFromQuadratic()";
4833 declareMeshModified( /*isReComputeSafe=*/!isDone );
4837 //=======================================================================
4838 //function : ConvertToQuadratic
4840 //=======================================================================
4842 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4843 throw (SALOME::SALOME_Exception)
4845 convertToQuadratic( theForce3d, false );
4846 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
4849 //================================================================================
4851 * \brief Makes a part of the mesh quadratic
4853 //================================================================================
4855 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
4856 SMESH::SMESH_IDSource_ptr theObject)
4857 throw (SALOME::SALOME_Exception)
4859 convertToQuadratic( theForce3d, false, theObject );
4860 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
4863 //================================================================================
4865 * \brief Makes a part of the mesh bi-quadratic
4867 //================================================================================
4869 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
4870 SMESH::SMESH_IDSource_ptr theObject)
4871 throw (SALOME::SALOME_Exception)
4873 convertToQuadratic( theForce3d, true, theObject );
4874 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
4877 //================================================================================
4879 * \brief Makes a part of the mesh linear
4881 //================================================================================
4883 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
4884 throw (SALOME::SALOME_Exception)
4890 TIDSortedElemSet elems;
4891 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
4893 if ( elems.empty() )
4895 ConvertFromQuadratic();
4897 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
4899 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4903 getEditor().ConvertFromQuadratic(elems);
4906 declareMeshModified( /*isReComputeSafe=*/false );
4908 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
4910 SMESH_CATCH( SMESH::throwCorbaException );
4913 //=======================================================================
4914 //function : makeMesh
4915 //purpose : create a named imported mesh
4916 //=======================================================================
4918 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4920 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4921 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4922 SALOMEDS::Study_var study = gen->GetCurrentStudy();
4923 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
4924 gen->SetName( meshSO, theMeshName, "Mesh" );
4925 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4927 return mesh._retn();
4930 //=======================================================================
4931 //function : dumpGroupsList
4933 //=======================================================================
4935 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
4936 const SMESH::ListOfGroups * theGroupList)
4938 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
4939 if ( isDumpGroupList )
4940 theDumpPython << theGroupList << " = ";
4943 //================================================================================
4945 \brief Generates the unique group name.
4946 \param thePrefix name prefix
4949 //================================================================================
4951 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
4953 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4954 set<string> groupNames;
4956 // Get existing group names
4957 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
4958 SMESH::SMESH_GroupBase_var aGroup = groups[i];
4959 if (CORBA::is_nil(aGroup))
4962 CORBA::String_var name = aGroup->GetName();
4963 groupNames.insert( name.in() );
4967 string name = thePrefix;
4970 while (!groupNames.insert(name).second)
4971 name = SMESH_Comment( thePrefix ) << "_" << index++;
4976 //================================================================================
4978 * \brief Prepare SMESH_IDSource for work
4980 //================================================================================
4982 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
4984 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
4986 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
4987 filter->SetMesh( mesh );
4990 //================================================================================
4992 * \brief Retrieve elements of given type from SMESH_IDSource
4994 //================================================================================
4996 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
4997 const SMESHDS_Mesh* theMeshDS,
4998 TIDSortedElemSet& theElemSet,
4999 const SMDSAbs_ElementType theType,
5000 const bool emptyIfIsMesh,
5001 IDSource_Error* error)
5004 if ( error ) *error = IDSource_OK;
5006 if ( CORBA::is_nil( theIDSource ) )
5008 if ( error ) *error = IDSource_INVALID;
5011 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5013 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5014 *error = IDSource_EMPTY;
5017 prepareIdSource( theIDSource );
5018 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5019 if ( anIDs->length() == 0 )
5021 if ( error ) *error = IDSource_EMPTY;
5024 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5025 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5027 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5029 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5033 if ( error ) *error = IDSource_INVALID;
5039 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5040 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5042 if ( error ) *error = IDSource_INVALID;
5049 //================================================================================
5051 * \brief Duplicates given elements, i.e. creates new elements based on the
5052 * same nodes as the given ones.
5053 * \param theElements - container of elements to duplicate.
5054 * \param theGroupName - a name of group to contain the generated elements.
5055 * If a group with such a name already exists, the new elements
5056 * are added to the existng group, else a new group is created.
5057 * If \a theGroupName is empty, new elements are not added
5059 * \return a group where the new elements are added. NULL if theGroupName == "".
5062 //================================================================================
5064 SMESH::SMESH_Group_ptr
5065 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5066 const char* theGroupName)
5067 throw (SALOME::SALOME_Exception)
5069 SMESH::SMESH_Group_var newGroup;
5076 TIDSortedElemSet elems;
5077 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5079 getEditor().DoubleElements( elems );
5081 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5084 SMESH::ElementType type =
5085 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5086 // find existing group
5087 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5088 for ( size_t i = 0; i < groups->length(); ++i )
5089 if ( groups[i]->GetType() == type )
5091 CORBA::String_var name = groups[i]->GetName();
5092 if ( strcmp( name, theGroupName ) == 0 ) {
5093 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5097 // create a new group
5098 if ( newGroup->_is_nil() )
5099 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5101 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5103 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5104 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5105 for ( int i = 1; i <= aSeq.Length(); i++ )
5106 groupDS->SMDSGroup().Add( aSeq(i) );
5111 if ( !newGroup->_is_nil() )
5112 pyDump << newGroup << " = ";
5113 pyDump << this << ".DoubleElements( "
5114 << theElements << ", " << "'" << theGroupName <<"')";
5116 SMESH_CATCH( SMESH::throwCorbaException );
5118 return newGroup._retn();
5121 //================================================================================
5123 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5124 \param theNodes - identifiers of nodes to be doubled
5125 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5126 nodes. If list of element identifiers is empty then nodes are doubled but
5127 they not assigned to elements
5128 \return TRUE if operation has been completed successfully, FALSE otherwise
5129 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5131 //================================================================================
5133 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5134 const SMESH::long_array& theModifiedElems )
5135 throw (SALOME::SALOME_Exception)
5140 list< int > aListOfNodes;
5142 for ( i = 0, n = theNodes.length(); i < n; i++ )
5143 aListOfNodes.push_back( theNodes[ i ] );
5145 list< int > aListOfElems;
5146 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5147 aListOfElems.push_back( theModifiedElems[ i ] );
5149 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5151 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5153 // Update Python script
5154 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5158 SMESH_CATCH( SMESH::throwCorbaException );
5162 //================================================================================
5164 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5165 This method provided for convenience works as DoubleNodes() described above.
5166 \param theNodeId - identifier of node to be doubled.
5167 \param theModifiedElems - identifiers of elements to be updated.
5168 \return TRUE if operation has been completed successfully, FALSE otherwise
5169 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5171 //================================================================================
5173 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5174 const SMESH::long_array& theModifiedElems )
5175 throw (SALOME::SALOME_Exception)
5178 SMESH::long_array_var aNodes = new SMESH::long_array;
5179 aNodes->length( 1 );
5180 aNodes[ 0 ] = theNodeId;
5182 TPythonDump pyDump; // suppress dump by the next line
5184 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5186 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5190 SMESH_CATCH( SMESH::throwCorbaException );
5194 //================================================================================
5196 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5197 This method provided for convenience works as DoubleNodes() described above.
5198 \param theNodes - group of nodes to be doubled.
5199 \param theModifiedElems - group of elements to be updated.
5200 \return TRUE if operation has been completed successfully, FALSE otherwise
5201 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5203 //================================================================================
5205 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5206 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5207 throw (SALOME::SALOME_Exception)
5210 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5213 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5214 SMESH::long_array_var aModifiedElems;
5215 if ( !CORBA::is_nil( theModifiedElems ) )
5216 aModifiedElems = theModifiedElems->GetListOfID();
5219 aModifiedElems = new SMESH::long_array;
5220 aModifiedElems->length( 0 );
5223 TPythonDump pyDump; // suppress dump by the next line
5225 bool done = DoubleNodes( aNodes, aModifiedElems );
5227 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5231 SMESH_CATCH( SMESH::throwCorbaException );
5235 //================================================================================
5237 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5238 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5239 * \param theNodes - group of nodes to be doubled.
5240 * \param theModifiedElems - group of elements to be updated.
5241 * \return a new group with newly created nodes
5242 * \sa DoubleNodeGroup()
5244 //================================================================================
5246 SMESH::SMESH_Group_ptr
5247 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5248 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5249 throw (SALOME::SALOME_Exception)
5252 SMESH::SMESH_Group_var aNewGroup;
5254 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5255 return aNewGroup._retn();
5258 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5259 SMESH::long_array_var aModifiedElems;
5260 if ( !CORBA::is_nil( theModifiedElems ) )
5261 aModifiedElems = theModifiedElems->GetListOfID();
5263 aModifiedElems = new SMESH::long_array;
5264 aModifiedElems->length( 0 );
5267 TPythonDump pyDump; // suppress dump by the next line
5269 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5272 // Create group with newly created nodes
5273 SMESH::long_array_var anIds = GetLastCreatedNodes();
5274 if (anIds->length() > 0) {
5275 string anUnindexedName (theNodes->GetName());
5276 string aNewName = generateGroupName(anUnindexedName + "_double");
5277 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5278 aNewGroup->Add(anIds);
5279 pyDump << aNewGroup << " = ";
5283 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5284 << theModifiedElems << " )";
5286 return aNewGroup._retn();
5288 SMESH_CATCH( SMESH::throwCorbaException );
5292 //================================================================================
5294 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5295 This method provided for convenience works as DoubleNodes() described above.
5296 \param theNodes - list of groups of nodes to be doubled
5297 \param theModifiedElems - list of groups of elements to be updated.
5298 \return TRUE if operation has been completed successfully, FALSE otherwise
5299 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5301 //================================================================================
5303 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5304 const SMESH::ListOfGroups& theModifiedElems )
5305 throw (SALOME::SALOME_Exception)
5310 std::list< int > aNodes;
5312 for ( i = 0, n = theNodes.length(); i < n; i++ )
5314 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5315 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5317 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5318 for ( j = 0, m = aCurr->length(); j < m; j++ )
5319 aNodes.push_back( aCurr[ j ] );
5323 std::list< int > anElems;
5324 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5326 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5327 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5329 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5330 for ( j = 0, m = aCurr->length(); j < m; j++ )
5331 anElems.push_back( aCurr[ j ] );
5335 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5337 declareMeshModified( /*isReComputeSafe=*/false );
5339 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5343 SMESH_CATCH( SMESH::throwCorbaException );
5347 //================================================================================
5349 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5350 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5351 * \param theNodes - group of nodes to be doubled.
5352 * \param theModifiedElems - group of elements to be updated.
5353 * \return a new group with newly created nodes
5354 * \sa DoubleNodeGroups()
5356 //================================================================================
5358 SMESH::SMESH_Group_ptr
5359 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5360 const SMESH::ListOfGroups& theModifiedElems )
5361 throw (SALOME::SALOME_Exception)
5363 SMESH::SMESH_Group_var aNewGroup;
5365 TPythonDump pyDump; // suppress dump by the next line
5367 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5371 // Create group with newly created nodes
5372 SMESH::long_array_var anIds = GetLastCreatedNodes();
5373 if (anIds->length() > 0) {
5374 string anUnindexedName (theNodes[0]->GetName());
5375 string aNewName = generateGroupName(anUnindexedName + "_double");
5376 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5377 aNewGroup->Add(anIds);
5378 pyDump << aNewGroup << " = ";
5382 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5383 << theModifiedElems << " )";
5385 return aNewGroup._retn();
5389 //================================================================================
5391 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5392 \param theElems - the list of elements (edges or faces) to be replicated
5393 The nodes for duplication could be found from these elements
5394 \param theNodesNot - list of nodes to NOT replicate
5395 \param theAffectedElems - the list of elements (cells and edges) to which the
5396 replicated nodes should be associated to.
5397 \return TRUE if operation has been completed successfully, FALSE otherwise
5398 \sa DoubleNodeGroup(), DoubleNodeGroups()
5400 //================================================================================
5402 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5403 const SMESH::long_array& theNodesNot,
5404 const SMESH::long_array& theAffectedElems )
5405 throw (SALOME::SALOME_Exception)
5410 SMESHDS_Mesh* aMeshDS = getMeshDS();
5411 TIDSortedElemSet anElems, aNodes, anAffected;
5412 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5413 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5414 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5416 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5418 // Update Python script
5419 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5420 << theNodesNot << ", " << theAffectedElems << " )";
5422 declareMeshModified( /*isReComputeSafe=*/false );
5425 SMESH_CATCH( SMESH::throwCorbaException );
5429 //================================================================================
5431 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5432 \param theElems - the list of elements (edges or faces) to be replicated
5433 The nodes for duplication could be found from these elements
5434 \param theNodesNot - list of nodes to NOT replicate
5435 \param theShape - shape to detect affected elements (element which geometric center
5436 located on or inside shape).
5437 The replicated nodes should be associated to affected elements.
5438 \return TRUE if operation has been completed successfully, FALSE otherwise
5439 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5441 //================================================================================
5443 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5444 const SMESH::long_array& theNodesNot,
5445 GEOM::GEOM_Object_ptr theShape )
5446 throw (SALOME::SALOME_Exception)
5452 SMESHDS_Mesh* aMeshDS = getMeshDS();
5453 TIDSortedElemSet anElems, aNodes;
5454 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5455 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5457 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5458 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5460 // Update Python script
5461 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5462 << theNodesNot << ", " << theShape << " )";
5464 declareMeshModified( /*isReComputeSafe=*/false );
5467 SMESH_CATCH( SMESH::throwCorbaException );
5471 //================================================================================
5473 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5474 \param theElems - group of of elements (edges or faces) to be replicated
5475 \param theNodesNot - group of nodes not to replicated
5476 \param theAffectedElems - group of elements to which the replicated nodes
5477 should be associated to.
5478 \return TRUE if operation has been completed successfully, FALSE otherwise
5479 \sa DoubleNodes(), DoubleNodeGroups()
5481 //================================================================================
5484 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5485 SMESH::SMESH_GroupBase_ptr theNodesNot,
5486 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5487 throw (SALOME::SALOME_Exception)
5490 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5496 SMESHDS_Mesh* aMeshDS = getMeshDS();
5497 TIDSortedElemSet anElems, aNodes, anAffected;
5498 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5499 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5500 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5502 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5504 // Update Python script
5505 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5506 << theNodesNot << ", " << theAffectedElems << " )";
5508 declareMeshModified( /*isReComputeSafe=*/false );
5511 SMESH_CATCH( SMESH::throwCorbaException );
5515 //================================================================================
5517 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5518 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5519 * \param theElems - group of of elements (edges or faces) to be replicated
5520 * \param theNodesNot - group of nodes not to replicated
5521 * \param theAffectedElems - group of elements to which the replicated nodes
5522 * should be associated to.
5523 * \return a new group with newly created elements
5524 * \sa DoubleNodeElemGroup()
5526 //================================================================================
5528 SMESH::SMESH_Group_ptr
5529 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5530 SMESH::SMESH_GroupBase_ptr theNodesNot,
5531 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5532 throw (SALOME::SALOME_Exception)
5535 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5539 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5540 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5542 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5544 << theNodesNot << ", "
5545 << theAffectedElems << " )";
5547 return elemGroup._retn();
5550 //================================================================================
5552 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5553 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5554 * \param theElems - group of of elements (edges or faces) to be replicated
5555 * \param theNodesNot - group of nodes not to replicated
5556 * \param theAffectedElems - group of elements to which the replicated nodes
5557 * should be associated to.
5558 * \return a new group with newly created elements
5559 * \sa DoubleNodeElemGroup()
5561 //================================================================================
5563 SMESH::ListOfGroups*
5564 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5565 SMESH::SMESH_GroupBase_ptr theNodesNot,
5566 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5567 CORBA::Boolean theElemGroupNeeded,
5568 CORBA::Boolean theNodeGroupNeeded)
5569 throw (SALOME::SALOME_Exception)
5572 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5573 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5574 aTwoGroups->length( 2 );
5576 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5577 return aTwoGroups._retn();
5582 SMESHDS_Mesh* aMeshDS = getMeshDS();
5583 TIDSortedElemSet anElems, aNodes, anAffected;
5584 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5585 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5586 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5589 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5591 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5597 // Create group with newly created elements
5598 CORBA::String_var elemGroupName = theElems->GetName();
5599 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5600 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5602 SMESH::long_array_var anIds = GetLastCreatedElems();
5603 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5604 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5605 aNewElemGroup->Add(anIds);
5607 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5609 SMESH::long_array_var anIds = GetLastCreatedNodes();
5610 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5611 aNewNodeGroup->Add(anIds);
5615 // Update Python script
5618 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5619 else pyDump << aNewElemGroup << ", ";
5620 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5621 else pyDump << aNewNodeGroup << " ] = ";
5623 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5624 << theNodesNot << ", "
5625 << theAffectedElems << ", "
5626 << theElemGroupNeeded << ", "
5627 << theNodeGroupNeeded <<" )";
5629 aTwoGroups[0] = aNewElemGroup._retn();
5630 aTwoGroups[1] = aNewNodeGroup._retn();
5631 return aTwoGroups._retn();
5633 SMESH_CATCH( SMESH::throwCorbaException );
5637 //================================================================================
5639 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5640 \param theElems - group of of elements (edges or faces) to be replicated
5641 \param theNodesNot - group of nodes not to replicated
5642 \param theShape - shape to detect affected elements (element which geometric center
5643 located on or inside shape).
5644 The replicated nodes should be associated to affected elements.
5645 \return TRUE if operation has been completed successfully, FALSE otherwise
5646 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5648 //================================================================================
5651 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5652 SMESH::SMESH_GroupBase_ptr theNodesNot,
5653 GEOM::GEOM_Object_ptr theShape )
5654 throw (SALOME::SALOME_Exception)
5657 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5663 SMESHDS_Mesh* aMeshDS = getMeshDS();
5664 TIDSortedElemSet anElems, aNodes, anAffected;
5665 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5666 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5668 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5669 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5672 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5674 // Update Python script
5675 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5676 << theNodesNot << ", " << theShape << " )";
5679 SMESH_CATCH( SMESH::throwCorbaException );
5683 //================================================================================
5685 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5686 * \param [in] theGrpList - groups
5687 * \param [in] theMeshDS - mesh
5688 * \param [out] theElemSet - set of elements
5689 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5691 //================================================================================
5693 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5694 SMESHDS_Mesh* theMeshDS,
5695 TIDSortedElemSet& theElemSet,
5696 const bool theIsNodeGrp)
5698 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5700 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5701 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5702 : aGrp->GetType() != SMESH::NODE ) )
5704 SMESH::long_array_var anIDs = aGrp->GetIDs();
5705 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5710 //================================================================================
5712 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5713 This method provided for convenience works as DoubleNodes() described above.
5714 \param theElems - list of groups of elements (edges or faces) to be replicated
5715 \param theNodesNot - list of groups of nodes not to replicated
5716 \param theAffectedElems - group of elements to which the replicated nodes
5717 should be associated to.
5718 \return TRUE if operation has been completed successfully, FALSE otherwise
5719 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5721 //================================================================================
5724 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5725 const SMESH::ListOfGroups& theNodesNot,
5726 const SMESH::ListOfGroups& theAffectedElems)
5727 throw (SALOME::SALOME_Exception)
5733 SMESHDS_Mesh* aMeshDS = getMeshDS();
5734 TIDSortedElemSet anElems, aNodes, anAffected;
5735 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5736 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5737 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5739 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5741 // Update Python script
5742 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5743 << &theNodesNot << ", " << &theAffectedElems << " )";
5745 declareMeshModified( /*isReComputeSafe=*/false );
5748 SMESH_CATCH( SMESH::throwCorbaException );
5752 //================================================================================
5754 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5755 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5756 \param theElems - list of groups of elements (edges or faces) to be replicated
5757 \param theNodesNot - list of groups of nodes not to replicated
5758 \param theAffectedElems - group of elements to which the replicated nodes
5759 should be associated to.
5760 * \return a new group with newly created elements
5761 * \sa DoubleNodeElemGroups()
5763 //================================================================================
5765 SMESH::SMESH_Group_ptr
5766 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5767 const SMESH::ListOfGroups& theNodesNot,
5768 const SMESH::ListOfGroups& theAffectedElems)
5769 throw (SALOME::SALOME_Exception)
5772 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
5776 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5777 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5779 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
5781 << theNodesNot << ", "
5782 << theAffectedElems << " )";
5784 return elemGroup._retn();
5787 //================================================================================
5789 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5790 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5791 \param theElems - list of groups of elements (edges or faces) to be replicated
5792 \param theNodesNot - list of groups of nodes not to replicated
5793 \param theAffectedElems - group of elements to which the replicated nodes
5794 should be associated to.
5795 * \return a new group with newly created elements
5796 * \sa DoubleNodeElemGroups()
5798 //================================================================================
5800 SMESH::ListOfGroups*
5801 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
5802 const SMESH::ListOfGroups& theNodesNot,
5803 const SMESH::ListOfGroups& theAffectedElems,
5804 CORBA::Boolean theElemGroupNeeded,
5805 CORBA::Boolean theNodeGroupNeeded)
5806 throw (SALOME::SALOME_Exception)
5809 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5810 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5811 aTwoGroups->length( 2 );
5816 SMESHDS_Mesh* aMeshDS = getMeshDS();
5817 TIDSortedElemSet anElems, aNodes, anAffected;
5818 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5819 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5820 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5822 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5824 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5829 // Create group with newly created elements
5830 CORBA::String_var elemGroupName = theElems[0]->GetName();
5831 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5832 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5834 SMESH::long_array_var anIds = GetLastCreatedElems();
5835 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5836 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5837 aNewElemGroup->Add(anIds);
5839 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5841 SMESH::long_array_var anIds = GetLastCreatedNodes();
5842 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5843 aNewNodeGroup->Add(anIds);
5847 // Update Python script
5850 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5851 else pyDump << aNewElemGroup << ", ";
5852 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5853 else pyDump << aNewNodeGroup << " ] = ";
5855 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
5856 << &theNodesNot << ", "
5857 << &theAffectedElems << ", "
5858 << theElemGroupNeeded << ", "
5859 << theNodeGroupNeeded << " )";
5861 aTwoGroups[0] = aNewElemGroup._retn();
5862 aTwoGroups[1] = aNewNodeGroup._retn();
5863 return aTwoGroups._retn();
5865 SMESH_CATCH( SMESH::throwCorbaException );
5869 //================================================================================
5871 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5872 This method provided for convenience works as DoubleNodes() described above.
5873 \param theElems - list of groups of elements (edges or faces) to be replicated
5874 \param theNodesNot - list of groups of nodes not to replicated
5875 \param theShape - shape to detect affected elements (element which geometric center
5876 located on or inside shape).
5877 The replicated nodes should be associated to affected elements.
5878 \return TRUE if operation has been completed successfully, FALSE otherwise
5879 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5881 //================================================================================
5884 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5885 const SMESH::ListOfGroups& theNodesNot,
5886 GEOM::GEOM_Object_ptr theShape )
5887 throw (SALOME::SALOME_Exception)
5893 SMESHDS_Mesh* aMeshDS = getMeshDS();
5894 TIDSortedElemSet anElems, aNodes;
5895 listOfGroupToSet(theElems, aMeshDS, anElems,false );
5896 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5898 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5899 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5901 // Update Python script
5902 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5903 << &theNodesNot << ", " << theShape << " )";
5905 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5908 SMESH_CATCH( SMESH::throwCorbaException );
5912 //================================================================================
5914 \brief Identify the elements that will be affected by node duplication (actual
5915 duplication is not performed.
5916 This method is the first step of DoubleNodeElemGroupsInRegion.
5917 \param theElems - list of groups of elements (edges or faces) to be replicated
5918 \param theNodesNot - list of groups of nodes not to replicated
5919 \param theShape - shape to detect affected elements (element which geometric center
5920 located on or inside shape).
5921 The replicated nodes should be associated to affected elements.
5922 \return groups of affected elements
5923 \sa DoubleNodeElemGroupsInRegion()
5925 //================================================================================
5926 SMESH::ListOfGroups*
5927 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
5928 const SMESH::ListOfGroups& theNodesNot,
5929 GEOM::GEOM_Object_ptr theShape )
5930 throw (SALOME::SALOME_Exception)
5933 MESSAGE("AffectedElemGroupsInRegion");
5934 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
5935 bool isEdgeGroup = false;
5936 bool isFaceGroup = false;
5937 bool isVolumeGroup = false;
5938 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
5939 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
5940 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
5944 ::SMESH_MeshEditor aMeshEditor(myMesh);
5946 SMESHDS_Mesh* aMeshDS = getMeshDS();
5947 TIDSortedElemSet anElems, aNodes;
5948 listOfGroupToSet(theElems, aMeshDS, anElems, false);
5949 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
5951 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
5952 TIDSortedElemSet anAffected;
5953 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
5956 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5961 int lg = anAffected.size();
5962 MESSAGE("lg="<< lg);
5963 SMESH::long_array_var volumeIds = new SMESH::long_array;
5964 volumeIds->length(lg);
5965 SMESH::long_array_var faceIds = new SMESH::long_array;
5966 faceIds->length(lg);
5967 SMESH::long_array_var edgeIds = new SMESH::long_array;
5968 edgeIds->length(lg);
5973 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
5974 for (; eIt != anAffected.end(); ++eIt)
5976 const SMDS_MeshElement* anElem = *eIt;
5979 int elemId = anElem->GetID();
5980 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
5981 volumeIds[ivol++] = elemId;
5982 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
5983 faceIds[iface++] = elemId;
5984 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
5985 edgeIds[iedge++] = elemId;
5987 volumeIds->length(ivol);
5988 faceIds->length(iface);
5989 edgeIds->length(iedge);
5991 aNewVolumeGroup->Add(volumeIds);
5992 aNewFaceGroup->Add(faceIds);
5993 aNewEdgeGroup->Add(edgeIds);
5994 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
5995 isFaceGroup = (aNewFaceGroup->Size() > 0);
5996 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6000 if (isEdgeGroup) nbGroups++;
6001 if (isFaceGroup) nbGroups++;
6002 if (isVolumeGroup) nbGroups++;
6003 aListOfGroups->length(nbGroups);
6006 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6007 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6008 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6010 // Update Python script
6013 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6014 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6015 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6017 pyDump << this << ".AffectedElemGroupsInRegion( "
6018 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6020 return aListOfGroups._retn();
6022 SMESH_CATCH( SMESH::throwCorbaException );
6026 //================================================================================
6028 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6029 The created 2D mesh elements based on nodes of free faces of boundary volumes
6030 \return TRUE if operation has been completed successfully, FALSE otherwise
6032 //================================================================================
6034 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6035 throw (SALOME::SALOME_Exception)
6040 bool aResult = getEditor().Make2DMeshFrom3D();
6042 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6044 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6047 SMESH_CATCH( SMESH::throwCorbaException );
6051 //================================================================================
6053 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6054 * The list of groups must contain at least two groups. The groups have to be disjoint:
6055 * no common element into two different groups.
6056 * The nodes of the internal faces at the boundaries of the groups are doubled.
6057 * Optionally, the internal faces are replaced by flat elements.
6058 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6059 * The flat elements are stored in groups of volumes.
6060 * These groups are named according to the position of the group in the list:
6061 * 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.
6062 * 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.
6063 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6064 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6065 * \param theDomains - list of groups of volumes
6066 * \param createJointElems - if TRUE, create the elements
6067 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6068 * the boundary between \a theDomains and the rest mesh
6069 * \return TRUE if operation has been completed successfully, FALSE otherwise
6071 //================================================================================
6074 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6075 CORBA::Boolean createJointElems,
6076 CORBA::Boolean onAllBoundaries )
6077 throw (SALOME::SALOME_Exception)
6084 SMESHDS_Mesh* aMeshDS = getMeshDS();
6086 // MESSAGE("theDomains.length = "<<theDomains.length());
6087 if ( theDomains.length() <= 1 && !onAllBoundaries )
6088 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6090 vector<TIDSortedElemSet> domains;
6091 domains.resize( theDomains.length() );
6093 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6095 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6096 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6098 // if ( aGrp->GetType() != SMESH::VOLUME )
6099 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6100 SMESH::long_array_var anIDs = aGrp->GetIDs();
6101 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6105 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6106 // TODO publish the groups of flat elements in study
6108 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6110 // Update Python script
6111 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6112 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6114 SMESH_CATCH( SMESH::throwCorbaException );
6116 myMesh_i->CreateGroupServants(); // publish created groups if any
6121 //================================================================================
6123 * \brief Double nodes on some external faces and create flat elements.
6124 * Flat elements are mainly used by some types of mechanic calculations.
6126 * Each group of the list must be constituted of faces.
6127 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6128 * @param theGroupsOfFaces - list of groups of faces
6129 * @return TRUE if operation has been completed successfully, FALSE otherwise
6131 //================================================================================
6134 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6135 throw (SALOME::SALOME_Exception)
6140 SMESHDS_Mesh* aMeshDS = getMeshDS();
6142 vector<TIDSortedElemSet> faceGroups;
6145 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6147 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6148 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6150 TIDSortedElemSet faceGroup;
6152 faceGroups.push_back(faceGroup);
6153 SMESH::long_array_var anIDs = aGrp->GetIDs();
6154 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6158 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6159 // TODO publish the groups of flat elements in study
6161 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6163 // Update Python script
6164 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6167 SMESH_CATCH( SMESH::throwCorbaException );
6171 //================================================================================
6173 * \brief Identify all the elements around a geom shape, get the faces delimiting
6176 * Build groups of volume to remove, groups of faces to replace on the skin of the
6177 * object, groups of faces to remove inside the object, (idem edges).
6178 * Build ordered list of nodes at the border of each group of faces to replace
6179 * (to be used to build a geom subshape).
6181 //================================================================================
6183 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6184 GEOM::GEOM_Object_ptr theShape,
6185 const char* groupName,
6186 const SMESH::double_array& theNodesCoords,
6187 SMESH::array_of_long_array_out GroupsOfNodes)
6188 throw (SALOME::SALOME_Exception)
6193 std::vector<std::vector<int> > aListOfListOfNodes;
6194 ::SMESH_MeshEditor aMeshEditor( myMesh );
6196 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6197 if ( !theNodeSearcher )
6198 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6200 vector<double> nodesCoords;
6201 for (int i = 0; i < theNodesCoords.length(); i++)
6203 nodesCoords.push_back( theNodesCoords[i] );
6206 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6207 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6208 nodesCoords, aListOfListOfNodes);
6210 GroupsOfNodes = new SMESH::array_of_long_array;
6211 GroupsOfNodes->length( aListOfListOfNodes.size() );
6212 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6213 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6215 vector<int>& aListOfNodes = *llIt;
6216 vector<int>::iterator lIt = aListOfNodes.begin();;
6217 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6218 aGroup.length( aListOfNodes.size() );
6219 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6220 aGroup[ j ] = (*lIt);
6222 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6225 << ", '" << groupName << "', "
6226 << theNodesCoords << " )";
6228 SMESH_CATCH( SMESH::throwCorbaException );
6231 // issue 20749 ===================================================================
6233 * \brief Creates missing boundary elements
6234 * \param elements - elements whose boundary is to be checked
6235 * \param dimension - defines type of boundary elements to create
6236 * \param groupName - a name of group to store created boundary elements in,
6237 * "" means not to create the group
6238 * \param meshName - a name of new mesh to store created boundary elements in,
6239 * "" means not to create the new mesh
6240 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6241 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6242 * boundary elements will be copied into the new mesh
6243 * \param group - returns the create group, if any
6244 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6246 // ================================================================================
6248 SMESH::SMESH_Mesh_ptr
6249 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6250 SMESH::Bnd_Dimension dim,
6251 const char* groupName,
6252 const char* meshName,
6253 CORBA::Boolean toCopyElements,
6254 CORBA::Boolean toCopyExistingBondary,
6255 SMESH::SMESH_Group_out group)
6256 throw (SALOME::SALOME_Exception)
6261 if ( dim > SMESH::BND_1DFROM2D )
6262 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6264 SMESHDS_Mesh* aMeshDS = getMeshDS();
6266 SMESH::SMESH_Mesh_var mesh_var;
6267 SMESH::SMESH_Group_var group_var;
6271 TIDSortedElemSet elements;
6272 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6273 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6277 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6278 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6280 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6282 // group of new boundary elements
6283 SMESH_Group* smesh_group = 0;
6284 if ( strlen(groupName) )
6286 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6287 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6288 smesh_group = group_i->GetSmeshGroup();
6292 getEditor().MakeBoundaryMesh( elements,
6293 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6297 toCopyExistingBondary);
6300 smesh_mesh->GetMeshDS()->Modified();
6303 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6305 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6306 if ( mesh_var->_is_nil() )
6307 pyDump << myMesh_i->_this() << ", ";
6309 pyDump << mesh_var << ", ";
6310 if ( group_var->_is_nil() )
6311 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6313 pyDump << group_var << " = ";
6314 pyDump << this << ".MakeBoundaryMesh( "
6316 << "SMESH." << dimName[int(dim)] << ", "
6317 << "'" << groupName << "', "
6318 << "'" << meshName<< "', "
6319 << toCopyElements << ", "
6320 << toCopyExistingBondary << ")";
6322 group = group_var._retn();
6323 return mesh_var._retn();
6325 SMESH_CATCH( SMESH::throwCorbaException );
6326 return SMESH::SMESH_Mesh::_nil();
6329 //================================================================================
6331 * \brief Creates missing boundary elements
6332 * \param dimension - defines type of boundary elements to create
6333 * \param groupName - a name of group to store all boundary elements in,
6334 * "" means not to create the group
6335 * \param meshName - a name of a new mesh, which is a copy of the initial
6336 * mesh + created boundary elements; "" means not to create the new mesh
6337 * \param toCopyAll - if true, the whole initial mesh will be copied into
6338 * the new mesh else only boundary elements will be copied into the new mesh
6339 * \param groups - optional groups of elements to make boundary around
6340 * \param mesh - returns the mesh where elements were added to
6341 * \param group - returns the created group, if any
6342 * \retval long - number of added boundary elements
6344 //================================================================================
6346 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6347 const char* groupName,
6348 const char* meshName,
6349 CORBA::Boolean toCopyAll,
6350 const SMESH::ListOfIDSources& groups,
6351 SMESH::SMESH_Mesh_out mesh,
6352 SMESH::SMESH_Group_out group)
6353 throw (SALOME::SALOME_Exception)
6358 if ( dim > SMESH::BND_1DFROM2D )
6359 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6361 // separate groups belonging to this and other mesh
6362 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6363 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6364 groupsOfThisMesh->length( groups.length() );
6365 groupsOfOtherMesh->length( groups.length() );
6366 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6367 for ( int i = 0; i < groups.length(); ++i )
6369 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6370 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6371 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6373 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6374 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6375 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6377 groupsOfThisMesh->length( nbGroups );
6378 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6383 if ( nbGroupsOfOtherMesh > 0 )
6385 // process groups belonging to another mesh
6386 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6387 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6388 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6389 groupsOfOtherMesh, mesh, group );
6392 SMESH::SMESH_Mesh_var mesh_var;
6393 SMESH::SMESH_Group_var group_var;
6396 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6397 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6401 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6403 /*toCopyGroups=*/false,
6404 /*toKeepIDs=*/true);
6406 mesh_var = makeMesh(meshName);
6408 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6409 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6412 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6413 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6415 // group of boundary elements
6416 SMESH_Group* smesh_group = 0;
6417 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6418 if ( strlen(groupName) )
6420 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6421 group_var = mesh_i->CreateGroup( groupType, groupName );
6422 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6423 smesh_group = group_i->GetSmeshGroup();
6426 TIDSortedElemSet elements;
6428 if ( groups.length() > 0 )
6430 for ( int i = 0; i < nbGroups; ++i )
6433 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6435 SMESH::Bnd_Dimension bdim =
6436 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6437 nbAdded += getEditor().MakeBoundaryMesh( elements,
6438 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6441 /*toCopyElements=*/false,
6442 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6443 /*toAddExistingBondary=*/true,
6444 /*aroundElements=*/true);
6450 nbAdded += getEditor().MakeBoundaryMesh( elements,
6451 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6454 /*toCopyElements=*/false,
6455 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6456 /*toAddExistingBondary=*/true);
6458 tgtMesh->GetMeshDS()->Modified();
6460 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6462 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6463 pyDump << "nbAdded, ";
6464 if ( mesh_var->_is_nil() )
6465 pyDump << myMesh_i->_this() << ", ";
6467 pyDump << mesh_var << ", ";
6468 if ( group_var->_is_nil() )
6469 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6471 pyDump << group_var << " = ";
6472 pyDump << this << ".MakeBoundaryElements( "
6473 << "SMESH." << dimName[int(dim)] << ", "
6474 << "'" << groupName << "', "
6475 << "'" << meshName<< "', "
6476 << toCopyAll << ", "
6479 mesh = mesh_var._retn();
6480 group = group_var._retn();
6483 SMESH_CATCH( SMESH::throwCorbaException );