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