1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
46 #include "SMDS_SetIterator.hxx"
47 #include "SMDS_VolumeTool.hxx"
48 #include "SMESHDS_Group.hxx"
49 #include "SMESHDS_GroupOnGeom.hxx"
50 #include "SMESH_ControlsDef.hxx"
51 #include "SMESH_Filter_i.hxx"
52 #include "SMESH_Gen_i.hxx"
53 #include "SMESH_Group.hxx"
54 #include "SMESH_Group_i.hxx"
55 #include "SMESH_MeshAlgos.hxx"
56 #include "SMESH_MeshPartDS.hxx"
57 #include "SMESH_MesherHelper.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMeshEventListener.hxx"
60 #include "SMESH_subMesh_i.hxx"
62 #include <utilities.h>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <Utils_CorbaException.hxx>
65 #include <SALOMEDS_wrap.hxx>
66 #include <SALOME_GenericObj_i.hh>
67 #include <Basics_OCCTVersion.hxx>
69 #include <BRepAdaptor_Surface.hxx>
70 #include <BRep_Tool.hxx>
71 #include <TopExp_Explorer.hxx>
73 #include <TopoDS_Edge.hxx>
74 #include <TopoDS_Face.hxx>
79 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
83 #include <Standard_Failure.hxx>
86 #include <Standard_ErrorHandler.hxx>
92 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
94 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
97 using SMESH::TPythonDump;
100 namespace MeshEditor_I {
102 //=============================================================================
104 * \brief Mesh to apply modifications for preview purposes
106 //=============================================================================
108 struct TPreviewMesh: public SMESH_Mesh
110 SMDSAbs_ElementType myPreviewType; // type to show
112 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
113 _isShapeToMesh = (_id =_studyId = 0);
114 _myMeshDS = new SMESHDS_Mesh( _id, true );
115 myPreviewType = previewElements;
118 virtual ~TPreviewMesh() { delete _myMeshDS; _myMeshDS = 0; }
119 //!< Copy a set of elements
120 void Copy(const TIDSortedElemSet & theElements,
121 TIDSortedElemSet& theCopyElements,
122 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
123 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
125 // loop on theIDsOfElements
126 TIDSortedElemSet::const_iterator eIt = theElements.begin();
127 for ( ; eIt != theElements.end(); ++eIt )
129 const SMDS_MeshElement* anElem = *eIt;
130 if ( !anElem ) continue;
131 SMDSAbs_ElementType type = anElem->GetType();
132 if ( type == theAvoidType ||
133 ( theSelectType != SMDSAbs_All && type != theSelectType ))
135 const SMDS_MeshElement* anElemCopy;
136 if ( type == SMDSAbs_Node)
137 anElemCopy = Copy( cast2Node(anElem) );
139 anElemCopy = Copy( anElem );
141 theCopyElements.insert( theCopyElements.end(), anElemCopy );
145 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
147 // copy element nodes
148 int anElemNbNodes = anElem->NbNodes();
149 vector< int > anElemNodesID( anElemNbNodes ) ;
150 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
151 for ( int i = 0; itElemNodes->more(); i++)
153 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
155 anElemNodesID[i] = anElemNode->GetID();
158 // creates a corresponding element on copied nodes
159 SMDS_MeshElement* anElemCopy = 0;
160 if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume )
162 const SMDS_VtkVolume* ph =
163 dynamic_cast<const SMDS_VtkVolume*> (anElem);
165 anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID
166 (anElemNodesID, ph->GetQuantities(),anElem->GetID());
169 anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID,
176 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
178 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
179 anElemNode->GetID());
183 GetMeshDS()->ClearMesh();
185 };// struct TPreviewMesh
187 static SMESH_NodeSearcher * theNodeSearcher = 0;
188 static SMESH_ElementSearcher * theElementSearcher = 0;
190 //=============================================================================
192 * \brief Deleter of theNodeSearcher at any compute event occured
194 //=============================================================================
196 struct TSearchersDeleter : public SMESH_subMeshEventListener
199 string myMeshPartIOR;
201 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
202 "SMESH_MeshEditor_i::TSearchersDeleter"),
204 //!< Delete theNodeSearcher
207 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
208 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
210 typedef map < int, SMESH_subMesh * > TDependsOnMap;
211 //!< The meshod called by submesh: do my main job
212 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
213 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
215 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
217 Unset( sm->GetFather() );
220 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
221 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
223 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
230 myMeshPartIOR = meshPartIOR;
231 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
232 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
233 while ( smIt->more() )
236 sm->SetEventListener( this, 0, sm );
240 //!< delete self from all submeshes
241 void Unset(SMESH_Mesh* mesh)
243 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
244 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
245 while ( smIt->more() )
246 smIt->next()->DeleteEventListener( this );
251 } theSearchersDeleter;
253 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
255 TCollection_AsciiString typeStr;
256 switch ( theMirrorType ) {
257 case SMESH::SMESH_MeshEditor::POINT:
258 typeStr = "SMESH.SMESH_MeshEditor.POINT";
260 case SMESH::SMESH_MeshEditor::AXIS:
261 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
264 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
268 //================================================================================
270 * \brief function for conversion of long_array to TIDSortedElemSet
271 * \param IDs - array of IDs
272 * \param aMesh - mesh
273 * \param aMap - collection to fill
274 * \param aType - element type
276 //================================================================================
278 void arrayToSet(const SMESH::long_array & IDs,
279 const SMESHDS_Mesh* aMesh,
280 TIDSortedElemSet& aMap,
281 const SMDSAbs_ElementType aType = SMDSAbs_All,
282 SMDS_MeshElement::Filter* aFilter = NULL)
284 SMDS_MeshElement::NonNullFilter filter1;
285 SMDS_MeshElement::TypeFilter filter2( aType );
287 if ( aFilter == NULL )
288 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
290 SMDS_MeshElement::Filter & filter = *aFilter;
292 if ( aType == SMDSAbs_Node )
293 for (int i=0; i<IDs.length(); i++) {
294 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
296 aMap.insert( aMap.end(), elem );
299 for (int i=0; i<IDs.length(); i++) {
300 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
302 aMap.insert( aMap.end(), elem );
306 //================================================================================
308 * \brief Retrieve nodes from SMESH_IDSource
310 //================================================================================
312 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
313 const SMESHDS_Mesh* theMeshDS,
314 TIDSortedNodeSet& theNodeSet)
317 if ( CORBA::is_nil( theObject ) )
319 SMESH::array_of_ElementType_var types = theObject->GetTypes();
320 SMESH::long_array_var aElementsId = theObject->GetIDs();
321 if ( types->length() == 1 && types[0] == SMESH::NODE)
323 for(int i = 0; i < aElementsId->length(); i++)
324 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
325 theNodeSet.insert( theNodeSet.end(), n);
327 else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
329 SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
330 while ( nIt->more( ))
331 if( const SMDS_MeshElement * elem = nIt->next() )
332 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
336 for(int i = 0; i < aElementsId->length(); i++)
337 if( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
338 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
342 //================================================================================
344 * \brief Returns elements connected to the given elements
346 //================================================================================
348 void getElementsAround(const TIDSortedElemSet& theElements,
349 const SMESHDS_Mesh* theMeshDS,
350 TIDSortedElemSet& theElementsAround)
352 if ( theElements.empty() ) return;
354 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
355 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
357 theMeshDS->GetMeshInfo().NbElements( elemType ) == theElements.size() )
358 return; // all the elements are in theElements
361 elemType = SMDSAbs_All;
363 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
365 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
366 for ( ; elemIt != theElements.end(); ++elemIt )
368 const SMDS_MeshElement* e = *elemIt;
369 int i = e->NbCornerNodes();
372 const SMDS_MeshNode* n = e->GetNode( i );
373 if ( !isNodeChecked[ n->GetID() ])
375 isNodeChecked[ n->GetID() ] = true;
376 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
377 while ( invIt->more() )
379 const SMDS_MeshElement* elemAround = invIt->next();
380 if ( !theElements.count( elemAround ))
381 theElementsAround.insert( elemAround );
388 //================================================================================
390 * \brief Return a string used to detect change of mesh part on which theElementSearcher
391 * is going to be used
393 //================================================================================
395 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
397 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
398 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
399 // take into account passible group modification
400 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
401 partIOR += SMESH_Comment( type );
405 } // namespace MeshEditor_I
407 using namespace MeshEditor_I;
409 //=============================================================================
413 //=============================================================================
415 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
417 myMesh( &theMesh->GetImpl() ),
419 myIsPreviewMode ( isPreview ),
425 //================================================================================
429 //================================================================================
431 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
433 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
434 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
435 poa->deactivate_object(anObjectId.in());
437 //deleteAuxIDSources();
438 delete myPreviewMesh; myPreviewMesh = 0;
439 delete myPreviewEditor; myPreviewEditor = 0;
442 //================================================================================
444 * \brief Clear members
446 //================================================================================
448 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
450 if ( myIsPreviewMode ) {
451 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
454 if ( deleteSearchers )
455 TSearchersDeleter::Delete();
457 getEditor().GetError().reset();
458 getEditor().ClearLastCreated();
461 //================================================================================
463 * \brief Increment mesh modif time and optionally record that the performed
464 * modification may influence futher mesh re-compute.
465 * \param [in] isReComputeSafe - true if the modification does not infulence
466 * futher mesh re-compute
468 //================================================================================
470 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
472 myMesh->GetMeshDS()->Modified();
473 if ( !isReComputeSafe )
474 myMesh->SetIsModified( true );
477 //================================================================================
479 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
480 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
482 //================================================================================
484 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
486 if ( myIsPreviewMode && !myPreviewEditor ) {
487 if ( !myPreviewMesh ) getPreviewMesh();
488 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
490 return myIsPreviewMode ? *myPreviewEditor : myEditor;
493 //================================================================================
495 * \brief Initialize and return myPreviewMesh
496 * \param previewElements - type of elements to show in preview
498 * WARNING: call it once par a method!
500 //================================================================================
502 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
504 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
506 delete myPreviewEditor;
508 delete myPreviewMesh;
509 myPreviewMesh = new TPreviewMesh( previewElements );
511 myPreviewMesh->Clear();
512 return myPreviewMesh;
515 //================================================================================
517 * Return data of mesh edition preview
519 //================================================================================
521 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
522 throw (SALOME::SALOME_Exception)
525 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
527 if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
529 list<int> aNodesConnectivity;
530 typedef map<int, int> TNodesMap;
533 SMESHDS_Mesh* aMeshDS;
534 std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
536 aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
537 aMeshDS = aMeshPartDS.get();
540 aMeshDS = getEditor().GetMeshDS();
542 myPreviewData = new SMESH::MeshPreviewStruct();
543 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
546 SMDSAbs_ElementType previewType = SMDSAbs_All;
548 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
549 previewType = aPreviewMesh->myPreviewType;
550 switch ( previewType ) {
551 case SMDSAbs_Edge : break;
552 case SMDSAbs_Face : break;
553 case SMDSAbs_Volume: break;
555 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
559 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
561 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
563 while ( itMeshElems->more() ) {
564 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
565 SMDS_NodeIteratorPtr itElemNodes = aMeshElem->nodeIterator();
566 while ( itElemNodes->more() ) {
567 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
568 int aNodeID = aMeshNode->GetID();
569 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
570 if ( anIter == nodesMap.end() ) {
571 // filling the nodes coordinates
572 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
573 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
574 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
575 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
578 aNodesConnectivity.push_back(anIter->second);
581 // filling the elements types
582 SMDSAbs_ElementType aType = aMeshElem->GetType();
583 bool isPoly = aMeshElem->IsPoly();
584 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
585 myPreviewData->elementTypes[i].isPoly = isPoly;
586 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
589 myPreviewData->nodesXYZ.length( j );
591 // filling the elements connectivities
592 list<int>::iterator aConnIter = aNodesConnectivity.begin();
593 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
594 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
595 myPreviewData->elementConnectivities[i] = *aConnIter;
597 return myPreviewData._retn();
599 SMESH_CATCH( SMESH::throwCorbaException );
603 //================================================================================
605 * \brief Returns list of it's IDs of created nodes
606 * \retval SMESH::long_array* - list of node ID
608 //================================================================================
610 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
611 throw (SALOME::SALOME_Exception)
614 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
616 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
617 myLastCreatedNodes->length( aSeq.Length() );
618 for (int i = 1; i <= aSeq.Length(); i++)
619 myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID();
621 return myLastCreatedNodes._retn();
622 SMESH_CATCH( SMESH::throwCorbaException );
626 //================================================================================
628 * \brief Returns list of it's IDs of created elements
629 * \retval SMESH::long_array* - list of elements' ID
631 //================================================================================
633 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
634 throw (SALOME::SALOME_Exception)
637 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
639 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
640 myLastCreatedElems->length( aSeq.Length() );
641 for ( int i = 1; i <= aSeq.Length(); i++ )
642 myLastCreatedElems[i-1] = aSeq.Value(i)->GetID();
644 return myLastCreatedElems._retn();
645 SMESH_CATCH( SMESH::throwCorbaException );
649 //=======================================================================
650 //function : ClearLastCreated
651 //purpose : Clears sequences of last created elements and nodes
652 //=======================================================================
654 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
657 getEditor().ClearLastCreated();
658 SMESH_CATCH( SMESH::throwCorbaException );
661 //=======================================================================
663 * Returns description of an error/warning occured during the last operation
664 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
666 //=======================================================================
668 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
669 throw (SALOME::SALOME_Exception)
672 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
673 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
674 if ( errIn && !errIn->IsOK() )
676 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
677 errOut->comment = errIn->myComment.c_str();
678 errOut->subShapeID = -1;
679 errOut->hasBadMesh = !errIn->myBadElements.empty();
684 errOut->subShapeID = -1;
685 errOut->hasBadMesh = false;
688 return errOut._retn();
689 SMESH_CATCH( SMESH::throwCorbaException );
693 //=======================================================================
694 //function : MakeIDSource
695 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
696 // Call UnRegister() as you fininsh using it!!
697 //=======================================================================
699 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
700 public virtual SALOME::GenericObj_i
702 SMESH::long_array _ids;
703 SMESH::ElementType _type;
704 SMESH::SMESH_Mesh_ptr _mesh;
705 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
706 SMESH::long_array* GetMeshInfo() { return 0; }
707 SMESH::long_array* GetNbElementsByType()
709 SMESH::long_array_var aRes = new SMESH::long_array();
710 aRes->length(SMESH::NB_ELEMENT_TYPES);
711 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
712 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
715 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
716 bool IsMeshInfoCorrect() { return true; }
717 SMESH::array_of_ElementType* GetTypes()
719 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
720 if ( _ids.length() > 0 ) {
724 return types._retn();
726 SALOMEDS::TMPFile* GetVtkUgStream()
728 SALOMEDS::TMPFile_var SeqFile;
729 return SeqFile._retn();
733 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
734 SMESH::ElementType type)
736 _IDSource* idSrc = new _IDSource;
737 idSrc->_mesh = myMesh_i->_this();
740 if ( type == SMESH::ALL && ids.length() > 0 )
741 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
743 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
745 return anIDSourceVar._retn();
748 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
750 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
753 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
756 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
758 nbIds = (int) tmpIdSource->_ids.length();
759 return & tmpIdSource->_ids[0];
765 // void SMESH_MeshEditor_i::deleteAuxIDSources()
767 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
768 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
770 // myAuxIDSources.clear();
773 //=============================================================================
777 //=============================================================================
780 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
781 throw (SALOME::SALOME_Exception)
788 for (int i = 0; i < IDsOfElements.length(); i++)
789 IdList.push_back( IDsOfElements[i] );
791 // Update Python script
792 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
795 bool ret = getEditor().Remove( IdList, false );
797 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
800 SMESH_CATCH( SMESH::throwCorbaException );
804 //=============================================================================
808 //=============================================================================
810 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
811 throw (SALOME::SALOME_Exception)
817 for (int i = 0; i < IDsOfNodes.length(); i++)
818 IdList.push_back( IDsOfNodes[i] );
820 // Update Python script
821 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
823 bool ret = getEditor().Remove( IdList, true );
825 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
828 SMESH_CATCH( SMESH::throwCorbaException );
832 //=============================================================================
836 //=============================================================================
838 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
839 throw (SALOME::SALOME_Exception)
844 // Update Python script
845 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
847 // Create filter to find all orphan nodes
848 SMESH::Controls::Filter::TIdSequence seq;
849 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
850 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
852 // remove orphan nodes (if there are any)
854 for ( int i = 0; i < seq.size(); i++ )
855 IdList.push_back( seq[i] );
857 int nbNodesBefore = myMesh->NbNodes();
858 getEditor().Remove( IdList, true );
859 int nbNodesAfter = myMesh->NbNodes();
861 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
862 return nbNodesBefore - nbNodesAfter;
864 SMESH_CATCH( SMESH::throwCorbaException );
868 //=============================================================================
872 //=============================================================================
874 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
875 throw (SALOME::SALOME_Exception)
880 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
882 // Update Python script
883 TPythonDump() << "nodeID = " << this << ".AddNode( "
884 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
886 declareMeshModified( /*isReComputeSafe=*/false );
889 SMESH_CATCH( SMESH::throwCorbaException );
893 //=============================================================================
895 * Create 0D element on the given node.
897 //=============================================================================
899 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
900 throw (SALOME::SALOME_Exception)
905 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
906 SMDS_MeshElement* elem = getMeshDS()->Add0DElement(aNode);
908 // Update Python script
909 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
911 declareMeshModified( /*isReComputeSafe=*/false );
913 return elem ? elem->GetID() : 0;
915 SMESH_CATCH( SMESH::throwCorbaException );
919 //=============================================================================
921 * Create a ball element on the given node.
923 //=============================================================================
925 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
926 throw (SALOME::SALOME_Exception)
931 if ( diameter < std::numeric_limits<double>::min() )
932 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
934 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
935 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
937 // Update Python script
938 TPythonDump() << "ballElem = "
939 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
941 declareMeshModified( /*isReComputeSafe=*/false );
942 return elem ? elem->GetID() : 0;
944 SMESH_CATCH( SMESH::throwCorbaException );
948 //=============================================================================
950 * Create an edge, either linear and quadratic (this is determed
951 * by number of given nodes, two or three)
953 //=============================================================================
955 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
956 throw (SALOME::SALOME_Exception)
961 int NbNodes = IDsOfNodes.length();
962 SMDS_MeshElement* elem = 0;
965 CORBA::Long index1 = IDsOfNodes[0];
966 CORBA::Long index2 = IDsOfNodes[1];
967 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
968 getMeshDS()->FindNode(index2));
970 // Update Python script
971 TPythonDump() << "edge = " << this << ".AddEdge([ "
972 << index1 << ", " << index2 <<" ])";
975 CORBA::Long n1 = IDsOfNodes[0];
976 CORBA::Long n2 = IDsOfNodes[1];
977 CORBA::Long n12 = IDsOfNodes[2];
978 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
979 getMeshDS()->FindNode(n2),
980 getMeshDS()->FindNode(n12));
981 // Update Python script
982 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
983 <<n1<<", "<<n2<<", "<<n12<<" ])";
986 declareMeshModified( /*isReComputeSafe=*/false );
987 return elem ? elem->GetID() : 0;
989 SMESH_CATCH( SMESH::throwCorbaException );
993 //=============================================================================
997 //=============================================================================
999 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1000 throw (SALOME::SALOME_Exception)
1005 int NbNodes = IDsOfNodes.length();
1011 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1012 for (int i = 0; i < NbNodes; i++)
1013 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1015 SMDS_MeshElement* elem = 0;
1017 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1018 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1019 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1020 nodes[4], nodes[5]); break;
1021 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1022 nodes[4], nodes[5], nodes[6]); break;
1023 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1024 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1025 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1026 nodes[4], nodes[5], nodes[6], nodes[7],
1028 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1031 // Update Python script
1032 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1034 declareMeshModified( /*isReComputeSafe=*/false );
1036 return elem ? elem->GetID() : 0;
1038 SMESH_CATCH( SMESH::throwCorbaException );
1042 //=============================================================================
1046 //=============================================================================
1047 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1048 throw (SALOME::SALOME_Exception)
1053 int NbNodes = IDsOfNodes.length();
1054 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1055 for (int i = 0; i < NbNodes; i++)
1056 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1058 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1060 // Update Python script
1061 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1063 declareMeshModified( /*isReComputeSafe=*/false );
1064 return elem ? elem->GetID() : 0;
1066 SMESH_CATCH( SMESH::throwCorbaException );
1070 //=============================================================================
1072 * Create volume, either linear and quadratic (this is determed
1073 * by number of given nodes)
1075 //=============================================================================
1077 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1078 throw (SALOME::SALOME_Exception)
1083 int NbNodes = IDsOfNodes.length();
1084 vector< const SMDS_MeshNode*> n(NbNodes);
1085 for(int i=0;i<NbNodes;i++)
1086 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1088 SMDS_MeshElement* elem = 0;
1091 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1092 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1093 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1094 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1095 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1096 n[6],n[7],n[8],n[9]);
1098 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1099 n[6],n[7],n[8],n[9],n[10],n[11]);
1101 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1102 n[7],n[8],n[9],n[10],n[11],n[12]);
1104 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1105 n[9],n[10],n[11],n[12],n[13],n[14]);
1107 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1108 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1109 n[15],n[16],n[17],n[18],n[19]);
1111 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1112 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1113 n[15],n[16],n[17],n[18],n[19],
1114 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1118 // Update Python script
1119 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1121 declareMeshModified( /*isReComputeSafe=*/false );
1122 return elem ? elem->GetID() : 0;
1124 SMESH_CATCH( SMESH::throwCorbaException );
1128 //=============================================================================
1130 * AddPolyhedralVolume
1132 //=============================================================================
1133 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1134 const SMESH::long_array & Quantities)
1135 throw (SALOME::SALOME_Exception)
1140 int NbNodes = IDsOfNodes.length();
1141 std::vector<const SMDS_MeshNode*> n (NbNodes);
1142 for (int i = 0; i < NbNodes; i++)
1144 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1145 if (!aNode) return 0;
1149 int NbFaces = Quantities.length();
1150 std::vector<int> q (NbFaces);
1151 for (int j = 0; j < NbFaces; j++)
1152 q[j] = Quantities[j];
1154 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1156 // Update Python script
1157 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1158 << IDsOfNodes << ", " << Quantities << " )";
1160 declareMeshModified( /*isReComputeSafe=*/false );
1161 return elem ? elem->GetID() : 0;
1163 SMESH_CATCH( SMESH::throwCorbaException );
1167 //=============================================================================
1169 * AddPolyhedralVolumeByFaces
1171 //=============================================================================
1173 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1174 throw (SALOME::SALOME_Exception)
1179 int NbFaces = IdsOfFaces.length();
1180 std::vector<const SMDS_MeshNode*> poly_nodes;
1181 std::vector<int> quantities (NbFaces);
1183 for (int i = 0; i < NbFaces; i++) {
1184 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1185 quantities[i] = aFace->NbNodes();
1187 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1188 while (It->more()) {
1189 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1193 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1195 // Update Python script
1196 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1197 << IdsOfFaces << " )";
1199 declareMeshModified( /*isReComputeSafe=*/false );
1200 return elem ? elem->GetID() : 0;
1202 SMESH_CATCH( SMESH::throwCorbaException );
1206 //=============================================================================
1208 // \brief Create 0D elements on all nodes of the given object except those
1209 // nodes on which a 0D element already exists.
1210 // \param theObject object on whose nodes 0D elements will be created.
1211 // \param theGroupName optional name of a group to add 0D elements created
1212 // and/or found on nodes of \a theObject.
1213 // \return an object (a new group or a temporary SMESH_IDSource) holding
1214 // ids of new and/or found 0D elements.
1216 //=============================================================================
1218 SMESH::SMESH_IDSource_ptr
1219 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1220 const char* theGroupName)
1221 throw (SALOME::SALOME_Exception)
1226 SMESH::SMESH_IDSource_var result;
1229 TIDSortedElemSet elements, elems0D;
1230 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1231 getEditor().Create0DElementsOnAllNodes( elements, elems0D );
1233 SMESH::long_array_var newElems = new SMESH::long_array;
1234 newElems->length( elems0D.size() );
1235 TIDSortedElemSet::iterator eIt = elems0D.begin();
1236 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1237 newElems[ i ] = (*eIt)->GetID();
1239 SMESH::SMESH_GroupBase_var groupToFill;
1240 if ( theGroupName && strlen( theGroupName ))
1242 // Get existing group named theGroupName
1243 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1244 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1245 SMESH::SMESH_GroupBase_var group = groups[i];
1246 if ( !group->_is_nil() ) {
1247 CORBA::String_var name = group->GetName();
1248 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1249 groupToFill = group;
1254 if ( groupToFill->_is_nil() )
1255 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1256 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1257 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1260 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1262 group_i->Add( newElems );
1263 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1264 pyDump << groupToFill;
1268 result = MakeIDSource( newElems, SMESH::ELEM0D );
1269 pyDump << "elem0DIDs";
1272 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1273 << theObject << ", '" << theGroupName << "' )";
1275 return result._retn();
1277 SMESH_CATCH( SMESH::throwCorbaException );
1281 //=============================================================================
1283 * \brief Bind a node to a vertex
1284 * \param NodeID - node ID
1285 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1286 * \retval boolean - false if NodeID or VertexID is invalid
1288 //=============================================================================
1290 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1291 throw (SALOME::SALOME_Exception)
1295 SMESHDS_Mesh * mesh = getMeshDS();
1296 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1298 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1300 if ( mesh->MaxShapeIndex() < VertexID )
1301 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1303 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1304 if ( shape.ShapeType() != TopAbs_VERTEX )
1305 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1307 mesh->SetNodeOnVertex( node, VertexID );
1309 myMesh->SetIsModified( true );
1311 SMESH_CATCH( SMESH::throwCorbaException );
1314 //=============================================================================
1316 * \brief Store node position on an edge
1317 * \param NodeID - node ID
1318 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1319 * \param paramOnEdge - parameter on edge where the node is located
1320 * \retval boolean - false if any parameter is invalid
1322 //=============================================================================
1324 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1325 CORBA::Double paramOnEdge)
1326 throw (SALOME::SALOME_Exception)
1330 SMESHDS_Mesh * mesh = getMeshDS();
1331 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1333 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1335 if ( mesh->MaxShapeIndex() < EdgeID )
1336 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1338 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1339 if ( shape.ShapeType() != TopAbs_EDGE )
1340 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1343 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1344 if ( paramOnEdge < f || paramOnEdge > l )
1345 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1347 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1349 myMesh->SetIsModified( true );
1351 SMESH_CATCH( SMESH::throwCorbaException );
1354 //=============================================================================
1356 * \brief Store node position on a face
1357 * \param NodeID - node ID
1358 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1359 * \param u - U parameter on face where the node is located
1360 * \param v - V parameter on face where the node is located
1361 * \retval boolean - false if any parameter is invalid
1363 //=============================================================================
1365 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1366 CORBA::Double u, CORBA::Double v)
1367 throw (SALOME::SALOME_Exception)
1370 SMESHDS_Mesh * mesh = getMeshDS();
1371 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1373 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1375 if ( mesh->MaxShapeIndex() < FaceID )
1376 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1378 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1379 if ( shape.ShapeType() != TopAbs_FACE )
1380 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1382 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1383 bool isOut = ( u < surf.FirstUParameter() ||
1384 u > surf.LastUParameter() ||
1385 v < surf.FirstVParameter() ||
1386 v > surf.LastVParameter() );
1390 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1391 << " u( " << surf.FirstUParameter()
1392 << "," << surf.LastUParameter()
1393 << ") v( " << surf.FirstVParameter()
1394 << "," << surf.LastVParameter() << ")" );
1396 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1399 mesh->SetNodeOnFace( node, FaceID, u, v );
1400 myMesh->SetIsModified( true );
1402 SMESH_CATCH( SMESH::throwCorbaException );
1405 //=============================================================================
1407 * \brief Bind a node to a solid
1408 * \param NodeID - node ID
1409 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1410 * \retval boolean - false if NodeID or SolidID is invalid
1412 //=============================================================================
1414 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1415 throw (SALOME::SALOME_Exception)
1418 SMESHDS_Mesh * mesh = getMeshDS();
1419 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1421 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1423 if ( mesh->MaxShapeIndex() < SolidID )
1424 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1426 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1427 if ( shape.ShapeType() != TopAbs_SOLID &&
1428 shape.ShapeType() != TopAbs_SHELL)
1429 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1431 mesh->SetNodeInVolume( node, SolidID );
1433 SMESH_CATCH( SMESH::throwCorbaException );
1436 //=============================================================================
1438 * \brief Bind an element to a shape
1439 * \param ElementID - element ID
1440 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1442 //=============================================================================
1444 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1445 CORBA::Long ShapeID)
1446 throw (SALOME::SALOME_Exception)
1449 SMESHDS_Mesh * mesh = getMeshDS();
1450 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1452 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1454 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1455 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1457 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1458 if ( shape.ShapeType() != TopAbs_EDGE &&
1459 shape.ShapeType() != TopAbs_FACE &&
1460 shape.ShapeType() != TopAbs_SOLID &&
1461 shape.ShapeType() != TopAbs_SHELL )
1462 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1464 mesh->SetMeshElementOnShape( elem, ShapeID );
1466 myMesh->SetIsModified( true );
1468 SMESH_CATCH( SMESH::throwCorbaException );
1471 //=============================================================================
1475 //=============================================================================
1477 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1478 CORBA::Long NodeID2)
1479 throw (SALOME::SALOME_Exception)
1484 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1485 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1489 // Update Python script
1490 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1491 << NodeID1 << ", " << NodeID2 << " )";
1493 int ret = getEditor().InverseDiag ( n1, n2 );
1495 declareMeshModified( /*isReComputeSafe=*/false );
1498 SMESH_CATCH( SMESH::throwCorbaException );
1502 //=============================================================================
1506 //=============================================================================
1508 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1509 CORBA::Long NodeID2)
1510 throw (SALOME::SALOME_Exception)
1515 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1516 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1520 // Update Python script
1521 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1522 << NodeID1 << ", " << NodeID2 << " )";
1525 bool stat = getEditor().DeleteDiag ( n1, n2 );
1527 declareMeshModified( /*isReComputeSafe=*/!stat );
1531 SMESH_CATCH( SMESH::throwCorbaException );
1535 //=============================================================================
1539 //=============================================================================
1541 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1542 throw (SALOME::SALOME_Exception)
1547 for (int i = 0; i < IDsOfElements.length(); i++)
1549 CORBA::Long index = IDsOfElements[i];
1550 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1552 getEditor().Reorient( elem );
1554 // Update Python script
1555 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1557 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1560 SMESH_CATCH( SMESH::throwCorbaException );
1564 //=============================================================================
1568 //=============================================================================
1570 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1571 throw (SALOME::SALOME_Exception)
1576 TPythonDump aTPythonDump; // suppress dump in Reorient()
1578 prepareIdSource( theObject );
1580 SMESH::long_array_var anElementsId = theObject->GetIDs();
1581 CORBA::Boolean isDone = Reorient(anElementsId);
1583 // Update Python script
1584 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1586 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1589 SMESH_CATCH( SMESH::throwCorbaException );
1593 //=======================================================================
1594 //function : Reorient2D
1595 //purpose : Reorient faces contained in \a the2Dgroup.
1596 // the2Dgroup - the mesh or its part to reorient
1597 // theDirection - desired direction of normal of \a theFace
1598 // theFace - ID of face whose orientation is checked.
1599 // It can be < 1 then \a thePoint is used to find a face.
1600 // thePoint - is used to find a face if \a theFace < 1.
1601 // return number of reoriented elements.
1602 //=======================================================================
1604 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1605 const SMESH::DirStruct& theDirection,
1606 CORBA::Long theFace,
1607 const SMESH::PointStruct& thePoint)
1608 throw (SALOME::SALOME_Exception)
1611 initData(/*deleteSearchers=*/false);
1613 TIDSortedElemSet elements;
1614 IDSource_Error error;
1615 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1616 if ( error == IDSource_EMPTY )
1618 if ( error == IDSource_INVALID )
1619 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1622 const SMDS_MeshElement* face = 0;
1625 face = getMeshDS()->FindElement( theFace );
1627 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1628 if ( face->GetType() != SMDSAbs_Face )
1629 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1633 // create theElementSearcher if needed
1634 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1635 if ( !theElementSearcher )
1637 if ( elements.empty() ) // search in the whole mesh
1639 if ( myMesh->NbFaces() == 0 )
1640 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1642 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1646 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1647 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1649 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1653 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1654 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1657 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1658 if ( !elements.empty() && !elements.count( face ))
1659 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1662 const SMESH::PointStruct * P = &theDirection.PS;
1663 gp_Vec dirVec( P->x, P->y, P->z );
1664 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1665 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1667 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1670 declareMeshModified( /*isReComputeSafe=*/false );
1672 TPythonDump() << this << ".Reorient2D( "
1673 << the2Dgroup << ", "
1674 << theDirection << ", "
1676 << thePoint << " )";
1680 SMESH_CATCH( SMESH::throwCorbaException );
1684 //=======================================================================
1685 //function : Reorient2DBy3D
1686 //purpose : Reorient faces basing on orientation of adjacent volumes.
1687 //=======================================================================
1689 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1690 SMESH::SMESH_IDSource_ptr volumeGroup,
1691 CORBA::Boolean outsideNormal)
1692 throw (SALOME::SALOME_Exception)
1697 TIDSortedElemSet volumes;
1698 IDSource_Error volsError;
1699 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1702 for ( size_t i = 0; i < faceGroups.length(); ++i )
1704 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1706 TIDSortedElemSet faces;
1707 IDSource_Error error;
1708 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1709 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1710 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1711 if ( error == IDSource_OK && volsError != IDSource_OK )
1712 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1714 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1716 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1721 declareMeshModified( /*isReComputeSafe=*/false );
1723 TPythonDump() << this << ".Reorient2DBy3D( "
1724 << faceGroups << ", "
1725 << volumeGroup << ", "
1726 << outsideNormal << " )";
1730 SMESH_CATCH( SMESH::throwCorbaException );
1734 //=============================================================================
1736 * \brief Fuse neighbour triangles into quadrangles.
1738 //=============================================================================
1740 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1741 SMESH::NumericalFunctor_ptr Criterion,
1742 CORBA::Double MaxAngle)
1743 throw (SALOME::SALOME_Exception)
1748 SMESHDS_Mesh* aMesh = getMeshDS();
1749 TIDSortedElemSet faces,copyFaces;
1750 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1751 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1752 TIDSortedElemSet* workElements = & faces;
1754 if ( myIsPreviewMode ) {
1755 SMDSAbs_ElementType select = SMDSAbs_Face;
1756 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1757 workElements = & copyFaces;
1760 SMESH::NumericalFunctor_i* aNumericalFunctor =
1761 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1762 SMESH::Controls::NumericalFunctorPtr aCrit;
1763 if ( !aNumericalFunctor )
1764 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1766 aCrit = aNumericalFunctor->GetNumericalFunctor();
1768 if ( !myIsPreviewMode ) {
1769 // Update Python script
1770 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1771 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1774 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1776 declareMeshModified( /*isReComputeSafe=*/!stat );
1779 SMESH_CATCH( SMESH::throwCorbaException );
1783 //=============================================================================
1785 * \brief Fuse neighbour triangles into quadrangles.
1787 //=============================================================================
1789 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1790 SMESH::NumericalFunctor_ptr Criterion,
1791 CORBA::Double MaxAngle)
1792 throw (SALOME::SALOME_Exception)
1797 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1799 prepareIdSource( theObject );
1800 SMESH::long_array_var anElementsId = theObject->GetIDs();
1801 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1803 if ( !myIsPreviewMode ) {
1804 SMESH::NumericalFunctor_i* aNumericalFunctor =
1805 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1807 // Update Python script
1808 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1809 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1814 SMESH_CATCH( SMESH::throwCorbaException );
1818 //=============================================================================
1820 * \brief Split quadrangles into triangles.
1822 //=============================================================================
1824 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1825 SMESH::NumericalFunctor_ptr Criterion)
1826 throw (SALOME::SALOME_Exception)
1831 SMESHDS_Mesh* aMesh = getMeshDS();
1832 TIDSortedElemSet faces;
1833 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1835 SMESH::NumericalFunctor_i* aNumericalFunctor =
1836 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1837 SMESH::Controls::NumericalFunctorPtr aCrit;
1838 if ( !aNumericalFunctor )
1839 aCrit.reset( new SMESH::Controls::AspectRatio() );
1841 aCrit = aNumericalFunctor->GetNumericalFunctor();
1844 // Update Python script
1845 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1847 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1849 declareMeshModified( /*isReComputeSafe=*/false );
1852 SMESH_CATCH( SMESH::throwCorbaException );
1856 //=============================================================================
1858 * \brief Split quadrangles into triangles.
1860 //=============================================================================
1862 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1863 SMESH::NumericalFunctor_ptr Criterion)
1864 throw (SALOME::SALOME_Exception)
1869 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1871 prepareIdSource( theObject );
1872 SMESH::long_array_var anElementsId = theObject->GetIDs();
1873 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1875 SMESH::NumericalFunctor_i* aNumericalFunctor =
1876 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1878 // Update Python script
1879 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1881 declareMeshModified( /*isReComputeSafe=*/false );
1884 SMESH_CATCH( SMESH::throwCorbaException );
1888 //================================================================================
1890 * \brief Split each of quadrangles into 4 triangles.
1891 * \param [in] theObject - theQuads Container of quadrangles to split.
1893 //================================================================================
1895 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1896 throw (SALOME::SALOME_Exception)
1901 TIDSortedElemSet faces;
1902 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1904 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1906 getEditor().QuadTo4Tri( faces );
1907 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1909 SMESH_CATCH( SMESH::throwCorbaException );
1912 //=============================================================================
1914 * \brief Split quadrangles into triangles.
1916 //=============================================================================
1918 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1919 CORBA::Boolean Diag13)
1920 throw (SALOME::SALOME_Exception)
1925 SMESHDS_Mesh* aMesh = getMeshDS();
1926 TIDSortedElemSet faces;
1927 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1929 // Update Python script
1930 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1931 << IDsOfElements << ", " << Diag13 << " )";
1933 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1935 declareMeshModified( /*isReComputeSafe=*/ !stat );
1938 SMESH_CATCH( SMESH::throwCorbaException );
1942 //=============================================================================
1944 * \brief Split quadrangles into triangles.
1946 //=============================================================================
1948 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1949 CORBA::Boolean Diag13)
1950 throw (SALOME::SALOME_Exception)
1955 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
1957 prepareIdSource( theObject );
1958 SMESH::long_array_var anElementsId = theObject->GetIDs();
1959 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1961 // Update Python script
1962 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
1963 << theObject << ", " << Diag13 << " )";
1965 declareMeshModified( /*isReComputeSafe=*/!isDone );
1968 SMESH_CATCH( SMESH::throwCorbaException );
1973 //=============================================================================
1975 * Find better splitting of the given quadrangle.
1976 * \param IDOfQuad ID of the quadrangle to be splitted.
1977 * \param Criterion A criterion to choose a diagonal for splitting.
1978 * \return 1 if 1-3 diagonal is better, 2 if 2-4
1979 * diagonal is better, 0 if error occurs.
1981 //=============================================================================
1983 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
1984 SMESH::NumericalFunctor_ptr Criterion)
1985 throw (SALOME::SALOME_Exception)
1990 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
1991 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
1993 SMESH::NumericalFunctor_i* aNumericalFunctor =
1994 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
1995 SMESH::Controls::NumericalFunctorPtr aCrit;
1996 if (aNumericalFunctor)
1997 aCrit = aNumericalFunctor->GetNumericalFunctor();
1999 aCrit.reset(new SMESH::Controls::AspectRatio());
2001 int id = getEditor().BestSplit(quad, aCrit);
2002 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2006 SMESH_CATCH( SMESH::throwCorbaException );
2010 //================================================================================
2012 * \brief Split volumic elements into tetrahedrons
2014 //================================================================================
2016 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2017 CORBA::Short methodFlags)
2018 throw (SALOME::SALOME_Exception)
2023 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2024 const int noneFacet = -1;
2025 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2026 while( volIt->more() )
2027 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2029 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2030 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2032 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2033 << elems << ", " << methodFlags << " )";
2035 SMESH_CATCH( SMESH::throwCorbaException );
2038 //================================================================================
2040 * \brief Split hexahedra into triangular prisms
2041 * \param elems - elements to split
2042 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2043 * to split into triangles
2044 * \param methodFlags - flags passing splitting method:
2045 * 1 - split the hexahedron into 2 prisms
2046 * 2 - split the hexahedron into 4 prisms
2048 //================================================================================
2050 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr elems,
2051 const SMESH::PointStruct & startHexPoint,
2052 const SMESH::DirStruct& facetToSplitNormal,
2053 CORBA::Short methodFlags,
2054 CORBA::Boolean allDomains)
2055 throw (SALOME::SALOME_Exception)
2059 prepareIdSource( elems );
2061 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2064 gp_Dir( facetToSplitNormal.PS.x,
2065 facetToSplitNormal.PS.y,
2066 facetToSplitNormal.PS.z ));
2067 TIDSortedElemSet elemSet;
2068 SMESH::long_array_var anElementsId = elems->GetIDs();
2069 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2070 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2072 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2073 while ( !elemSet.empty() )
2075 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2079 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2080 for ( ; ef != elemFacets.end(); ++ef )
2081 elemSet.erase( ef->first );
2084 if ( methodFlags == 2 )
2085 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2087 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2089 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2090 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2092 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2094 << startHexPoint << ", "
2095 << facetToSplitNormal<< ", "
2096 << methodFlags<< ", "
2097 << allDomains << " )";
2099 SMESH_CATCH( SMESH::throwCorbaException );
2102 //=======================================================================
2105 //=======================================================================
2108 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2109 const SMESH::long_array & IDsOfFixedNodes,
2110 CORBA::Long MaxNbOfIterations,
2111 CORBA::Double MaxAspectRatio,
2112 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2113 throw (SALOME::SALOME_Exception)
2115 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2116 MaxAspectRatio, Method, false );
2120 //=======================================================================
2121 //function : SmoothParametric
2123 //=======================================================================
2126 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2127 const SMESH::long_array & IDsOfFixedNodes,
2128 CORBA::Long MaxNbOfIterations,
2129 CORBA::Double MaxAspectRatio,
2130 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2131 throw (SALOME::SALOME_Exception)
2133 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2134 MaxAspectRatio, Method, true );
2138 //=======================================================================
2139 //function : SmoothObject
2141 //=======================================================================
2144 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2145 const SMESH::long_array & IDsOfFixedNodes,
2146 CORBA::Long MaxNbOfIterations,
2147 CORBA::Double MaxAspectRatio,
2148 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2149 throw (SALOME::SALOME_Exception)
2151 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2152 MaxAspectRatio, Method, false);
2156 //=======================================================================
2157 //function : SmoothParametricObject
2159 //=======================================================================
2162 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2163 const SMESH::long_array & IDsOfFixedNodes,
2164 CORBA::Long MaxNbOfIterations,
2165 CORBA::Double MaxAspectRatio,
2166 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2167 throw (SALOME::SALOME_Exception)
2169 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2170 MaxAspectRatio, Method, true);
2174 //=============================================================================
2178 //=============================================================================
2181 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2182 const SMESH::long_array & IDsOfFixedNodes,
2183 CORBA::Long MaxNbOfIterations,
2184 CORBA::Double MaxAspectRatio,
2185 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2187 throw (SALOME::SALOME_Exception)
2192 SMESHDS_Mesh* aMesh = getMeshDS();
2194 TIDSortedElemSet elements;
2195 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2197 set<const SMDS_MeshNode*> fixedNodes;
2198 for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
2199 CORBA::Long index = IDsOfFixedNodes[i];
2200 const SMDS_MeshNode * node = aMesh->FindNode(index);
2202 fixedNodes.insert( node );
2204 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2205 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2206 method = ::SMESH_MeshEditor::CENTROIDAL;
2208 getEditor().Smooth(elements, fixedNodes, method,
2209 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2211 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2213 // Update Python script
2214 TPythonDump() << "isDone = " << this << "."
2215 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2216 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2217 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2218 << "SMESH.SMESH_MeshEditor."
2219 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2220 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2224 SMESH_CATCH( SMESH::throwCorbaException );
2228 //=============================================================================
2232 //=============================================================================
2235 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2236 const SMESH::long_array & IDsOfFixedNodes,
2237 CORBA::Long MaxNbOfIterations,
2238 CORBA::Double MaxAspectRatio,
2239 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2241 throw (SALOME::SALOME_Exception)
2246 TPythonDump aTPythonDump; // suppress dump in smooth()
2248 prepareIdSource( theObject );
2249 SMESH::long_array_var anElementsId = theObject->GetIDs();
2250 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2251 MaxAspectRatio, Method, IsParametric);
2253 // Update Python script
2254 aTPythonDump << "isDone = " << this << "."
2255 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2256 << theObject << ", " << IDsOfFixedNodes << ", "
2257 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2258 << "SMESH.SMESH_MeshEditor."
2259 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2260 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2264 SMESH_CATCH( SMESH::throwCorbaException );
2268 //=============================================================================
2272 //=============================================================================
2274 void SMESH_MeshEditor_i::RenumberNodes()
2275 throw (SALOME::SALOME_Exception)
2278 // Update Python script
2279 TPythonDump() << this << ".RenumberNodes()";
2281 getMeshDS()->Renumber( true );
2283 SMESH_CATCH( SMESH::throwCorbaException );
2286 //=============================================================================
2290 //=============================================================================
2292 void SMESH_MeshEditor_i::RenumberElements()
2293 throw (SALOME::SALOME_Exception)
2296 // Update Python script
2297 TPythonDump() << this << ".RenumberElements()";
2299 getMeshDS()->Renumber( false );
2301 SMESH_CATCH( SMESH::throwCorbaException );
2304 //=======================================================================
2306 * \brief Return groups by their IDs
2308 //=======================================================================
2310 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2311 throw (SALOME::SALOME_Exception)
2316 myMesh_i->CreateGroupServants();
2317 return myMesh_i->GetGroups( *groupIDs );
2319 SMESH_CATCH( SMESH::throwCorbaException );
2323 //=======================================================================
2324 //function : RotationSweepObjects
2326 //=======================================================================
2328 SMESH::ListOfGroups*
2329 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2330 const SMESH::ListOfIDSources & theEdges,
2331 const SMESH::ListOfIDSources & theFaces,
2332 const SMESH::AxisStruct & theAxis,
2333 CORBA::Double theAngleInRadians,
2334 CORBA::Long theNbOfSteps,
2335 CORBA::Double theTolerance,
2336 const bool theMakeGroups)
2337 throw (SALOME::SALOME_Exception)
2342 TIDSortedElemSet elemsNodes[2];
2343 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2344 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2345 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2347 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2348 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2349 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2350 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2352 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2353 bool makeWalls=true;
2354 if ( myIsPreviewMode )
2356 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2357 TPreviewMesh * tmpMesh = getPreviewMesh();
2358 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2359 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2360 workElements = & copyElements[0];
2361 //makeWalls = false; -- faces are needed for preview
2364 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2366 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2367 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2369 ::SMESH_MeshEditor::PGroupIDs groupIds =
2370 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2371 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2373 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2375 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2377 if ( !myIsPreviewMode )
2379 dumpGroupsList( aPythonDump, aGroups );
2380 aPythonDump << this<< ".RotationSweepObjects( "
2385 << TVar( theAngleInRadians ) << ", "
2386 << TVar( theNbOfSteps ) << ", "
2387 << TVar( theTolerance ) << ", "
2388 << theMakeGroups << " )";
2391 return aGroups ? aGroups : new SMESH::ListOfGroups;
2393 SMESH_CATCH( SMESH::throwCorbaException );
2397 namespace MeshEditor_I
2400 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2402 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2404 bool myIsExtrusionByNormal;
2406 static int makeFlags( CORBA::Boolean MakeGroups,
2407 CORBA::Boolean ByAverageNormal = false,
2408 CORBA::Boolean UseInputElemsOnly = false,
2409 CORBA::Long Flags = 0,
2410 CORBA::Boolean MakeBoundary = true )
2412 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2413 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2414 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2415 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2419 ExtrusionParams(const SMESH::DirStruct & theDir,
2420 CORBA::Long theNbOfSteps,
2421 CORBA::Boolean theMakeGroups):
2422 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2426 makeFlags( theMakeGroups )),
2427 myIsExtrusionByNormal( false )
2431 ExtrusionParams(const SMESH::DirStruct & theDir,
2432 CORBA::Long theNbOfSteps,
2433 CORBA::Boolean theMakeGroups,
2434 CORBA::Long theExtrFlags,
2435 CORBA::Double theSewTolerance):
2436 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2440 makeFlags( theMakeGroups, false, false,
2441 theExtrFlags, false ),
2443 myIsExtrusionByNormal( false )
2446 // params for extrusion by normal
2447 ExtrusionParams(CORBA::Double theStepSize,
2448 CORBA::Long theNbOfSteps,
2449 CORBA::Short theDim,
2450 CORBA::Boolean theUseInputElemsOnly,
2451 CORBA::Boolean theByAverageNormal,
2452 CORBA::Boolean theMakeGroups ):
2453 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2455 makeFlags( theMakeGroups,
2456 theByAverageNormal, theUseInputElemsOnly ),
2458 myIsExtrusionByNormal( true )
2464 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2469 //=======================================================================
2471 * \brief Generate dim+1 elements by extrusion of elements along vector
2472 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2473 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2474 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2475 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2476 * \param [in] nbOfSteps - number of elements to generate from one element
2477 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2478 * corresponding to groups the input elements included in.
2479 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2481 //=======================================================================
2483 SMESH::ListOfGroups*
2484 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2485 const SMESH::ListOfIDSources & theEdges,
2486 const SMESH::ListOfIDSources & theFaces,
2487 const SMESH::DirStruct & theStepVector,
2488 CORBA::Long theNbOfSteps,
2489 CORBA::Boolean theToMakeGroups)
2490 throw (SALOME::SALOME_Exception)
2495 ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
2497 TIDSortedElemSet elemsNodes[2];
2498 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2499 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2500 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2502 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2503 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2504 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2505 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2507 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2508 if ( myIsPreviewMode )
2510 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2511 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2512 // previewType = SMDSAbs_Edge;
2514 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2515 TPreviewMesh * tmpMesh = getPreviewMesh();
2516 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2517 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2518 workElements = & copyElements[0];
2520 params.SetNoGroups();
2522 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2524 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2525 ::SMESH_MeshEditor::PGroupIDs groupIds =
2526 getEditor().ExtrusionSweep( workElements, params, aHistory );
2528 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2530 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2532 if ( !myIsPreviewMode )
2534 dumpGroupsList( aPythonDump, aGroups );
2535 aPythonDump << this<< ".ExtrusionSweepObjects( "
2539 << theStepVector << ", "
2540 << TVar( theNbOfSteps ) << ", "
2541 << theToMakeGroups << " )";
2544 return aGroups ? aGroups : new SMESH::ListOfGroups;
2546 SMESH_CATCH( SMESH::throwCorbaException );
2550 //=======================================================================
2551 //function : ExtrusionByNormal
2553 //=======================================================================
2555 SMESH::ListOfGroups*
2556 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2557 CORBA::Double stepSize,
2558 CORBA::Long nbOfSteps,
2559 CORBA::Boolean byAverageNormal,
2560 CORBA::Boolean useInputElemsOnly,
2561 CORBA::Boolean makeGroups,
2563 throw (SALOME::SALOME_Exception)
2568 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2570 ExtrusionParams params( stepSize, nbOfSteps, dim,
2571 byAverageNormal, useInputElemsOnly, makeGroups );
2573 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2574 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2576 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2577 if (( elemTypes->length() == 1 ) &&
2578 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2579 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2582 TIDSortedElemSet elemsNodes[2];
2583 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2584 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2586 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2587 if ( myIsPreviewMode )
2589 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2590 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2591 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2592 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2593 workElements = & copyElements[0];
2595 params.SetNoGroups();
2598 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2599 ::SMESH_MeshEditor::PGroupIDs groupIds =
2600 getEditor().ExtrusionSweep( workElements, params, aHistory );
2602 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2604 if (!myIsPreviewMode) {
2605 dumpGroupsList(aPythonDump, aGroups);
2606 aPythonDump << this << ".ExtrusionByNormal( " << objects
2607 << ", " << TVar( stepSize )
2608 << ", " << TVar( nbOfSteps )
2609 << ", " << byAverageNormal
2610 << ", " << useInputElemsOnly
2611 << ", " << makeGroups
2616 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2618 return aGroups ? aGroups : new SMESH::ListOfGroups;
2620 SMESH_CATCH( SMESH::throwCorbaException );
2624 //=======================================================================
2625 //function : AdvancedExtrusion
2627 //=======================================================================
2629 SMESH::ListOfGroups*
2630 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2631 const SMESH::DirStruct & theStepVector,
2632 CORBA::Long theNbOfSteps,
2633 CORBA::Long theExtrFlags,
2634 CORBA::Double theSewTolerance,
2635 CORBA::Boolean theMakeGroups)
2636 throw (SALOME::SALOME_Exception)
2641 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2643 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2644 theExtrFlags, theSewTolerance );
2646 TIDSortedElemSet elemsNodes[2];
2647 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2649 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2650 ::SMESH_MeshEditor::PGroupIDs groupIds =
2651 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2653 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2655 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2657 if ( !myIsPreviewMode ) {
2658 dumpGroupsList(aPythonDump, aGroups);
2659 aPythonDump << this << ".AdvancedExtrusion( "
2660 << theIDsOfElements << ", "
2661 << theStepVector << ", "
2662 << theNbOfSteps << ", "
2663 << theExtrFlags << ", "
2664 << theSewTolerance << ", "
2665 << theMakeGroups << " )";
2668 return aGroups ? aGroups : new SMESH::ListOfGroups;
2670 SMESH_CATCH( SMESH::throwCorbaException );
2674 //================================================================================
2676 * \brief Convert extrusion error to IDL enum
2678 //================================================================================
2682 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2684 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2688 RETCASE( EXTR_NO_ELEMENTS );
2689 RETCASE( EXTR_PATH_NOT_EDGE );
2690 RETCASE( EXTR_BAD_PATH_SHAPE );
2691 RETCASE( EXTR_BAD_STARTING_NODE );
2692 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2693 RETCASE( EXTR_CANT_GET_TANGENT );
2695 return SMESH::SMESH_MeshEditor::EXTR_OK;
2699 //=======================================================================
2700 //function : extrusionAlongPath
2702 //=======================================================================
2703 SMESH::ListOfGroups*
2704 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2705 const SMESH::ListOfIDSources & theEdges,
2706 const SMESH::ListOfIDSources & theFaces,
2707 SMESH::SMESH_IDSource_ptr thePathMesh,
2708 GEOM::GEOM_Object_ptr thePathShape,
2709 CORBA::Long theNodeStart,
2710 CORBA::Boolean theHasAngles,
2711 const SMESH::double_array & theAngles,
2712 CORBA::Boolean theLinearVariation,
2713 CORBA::Boolean theHasRefPoint,
2714 const SMESH::PointStruct & theRefPoint,
2716 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2717 throw (SALOME::SALOME_Exception)
2722 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2724 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2725 if ( thePathMesh->_is_nil() )
2726 return aGroups._retn();
2729 SMESH_subMesh* aSubMesh = 0;
2730 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2731 if ( thePathShape->_is_nil() )
2733 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2734 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2736 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2737 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2738 if ( !aMeshImp ) return aGroups._retn();
2739 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2740 if ( !aSubMesh ) return aGroups._retn();
2742 else if ( !aMeshImp ||
2743 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2745 return aGroups._retn();
2750 if ( !aMeshImp ) return aGroups._retn();
2751 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2752 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2753 if ( !aSubMesh || !aSubMesh->GetSubMeshDS() )
2754 return aGroups._retn();
2757 SMDS_MeshNode* nodeStart =
2758 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2760 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2761 return aGroups._retn();
2764 TIDSortedElemSet elemsNodes[2];
2765 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2766 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2767 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2769 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2770 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2771 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2772 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2774 list<double> angles;
2775 for (int i = 0; i < theAngles.length(); i++) {
2776 angles.push_back( theAngles[i] );
2779 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2781 int nbOldGroups = myMesh->NbGroup();
2783 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2784 if ( myIsPreviewMode )
2786 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2787 TPreviewMesh * tmpMesh = getPreviewMesh();
2788 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2789 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2790 workElements = & copyElements[0];
2791 theMakeGroups = false;
2794 ::SMESH_MeshEditor::Extrusion_Error error;
2796 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2797 theHasAngles, angles, theLinearVariation,
2798 theHasRefPoint, refPnt, theMakeGroups );
2800 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2801 theHasAngles, angles, theLinearVariation,
2802 theHasRefPoint, refPnt, theMakeGroups );
2804 declareMeshModified( /*isReComputeSafe=*/true );
2805 theError = convExtrError( error );
2807 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2808 if ( theMakeGroups ) {
2809 list<int> groupIDs = myMesh->GetGroupIds();
2810 list<int>::iterator newBegin = groupIDs.begin();
2811 std::advance( newBegin, nbOldGroups ); // skip old groups
2812 groupIDs.erase( groupIDs.begin(), newBegin );
2813 aGroups = getGroups( & groupIDs );
2814 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2817 if ( !myIsPreviewMode ) {
2818 aPythonDump << "(" << aGroups << ", error) = "
2819 << this << ".ExtrusionAlongPathObjects( "
2823 << thePathMesh << ", "
2824 << thePathShape << ", "
2825 << theNodeStart << ", "
2826 << theHasAngles << ", "
2827 << theAngles << ", "
2828 << theLinearVariation << ", "
2829 << theHasRefPoint << ", "
2830 << "SMESH.PointStruct( "
2831 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2832 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2833 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2834 << theMakeGroups << " )";
2837 return aGroups._retn();
2839 SMESH_CATCH( SMESH::throwCorbaException );
2843 //================================================================================
2845 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2846 * of given angles along path steps
2847 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2848 * which proceeds the extrusion
2849 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2850 * is used to define the sub-mesh for the path
2852 //================================================================================
2854 SMESH::double_array*
2855 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2856 GEOM::GEOM_Object_ptr thePathShape,
2857 const SMESH::double_array & theAngles)
2859 SMESH::double_array_var aResult = new SMESH::double_array();
2860 int nbAngles = theAngles.length();
2861 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2863 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2864 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2865 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2866 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2867 return aResult._retn();
2868 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2869 if ( nbSteps == nbAngles )
2871 aResult.inout() = theAngles;
2875 aResult->length( nbSteps );
2876 double rAn2St = double( nbAngles ) / double( nbSteps );
2877 double angPrev = 0, angle;
2878 for ( int iSt = 0; iSt < nbSteps; ++iSt )
2880 double angCur = rAn2St * ( iSt+1 );
2881 double angCurFloor = floor( angCur );
2882 double angPrevFloor = floor( angPrev );
2883 if ( angPrevFloor == angCurFloor )
2884 angle = rAn2St * theAngles[ int( angCurFloor ) ];
2887 int iP = int( angPrevFloor );
2888 double angPrevCeil = ceil(angPrev);
2889 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2891 int iC = int( angCurFloor );
2892 if ( iC < nbAngles )
2893 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2895 iP = int( angPrevCeil );
2897 angle += theAngles[ iC ];
2899 aResult[ iSt ] = angle;
2904 // Update Python script
2905 TPythonDump() << "rotAngles = " << theAngles;
2906 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
2907 << thePathMesh << ", "
2908 << thePathShape << ", "
2911 return aResult._retn();
2914 //=======================================================================
2917 //=======================================================================
2919 SMESH::ListOfGroups*
2920 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
2921 const SMESH::AxisStruct & theAxis,
2922 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2923 CORBA::Boolean theCopy,
2925 ::SMESH_Mesh* theTargetMesh)
2926 throw (SALOME::SALOME_Exception)
2931 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2932 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2934 if ( theTargetMesh )
2938 switch ( theMirrorType ) {
2939 case SMESH::SMESH_MeshEditor::POINT:
2940 aTrsf.SetMirror( P );
2942 case SMESH::SMESH_MeshEditor::AXIS:
2943 aTrsf.SetMirror( gp_Ax1( P, V ));
2946 aTrsf.SetMirror( gp_Ax2( P, V ));
2949 TIDSortedElemSet copyElements;
2950 TIDSortedElemSet* workElements = & theElements;
2952 if ( myIsPreviewMode )
2954 TPreviewMesh * tmpMesh = getPreviewMesh();
2955 tmpMesh->Copy( theElements, copyElements);
2956 if ( !theCopy && !theTargetMesh )
2958 TIDSortedElemSet elemsAround, elemsAroundCopy;
2959 getElementsAround( theElements, getMeshDS(), elemsAround );
2960 tmpMesh->Copy( elemsAround, elemsAroundCopy);
2962 workElements = & copyElements;
2963 theMakeGroups = false;
2966 ::SMESH_MeshEditor::PGroupIDs groupIds =
2967 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2969 if ( theCopy && !myIsPreviewMode)
2971 if ( theTargetMesh )
2973 theTargetMesh->GetMeshDS()->Modified();
2977 declareMeshModified( /*isReComputeSafe=*/false );
2980 return theMakeGroups ? getGroups(groupIds.get()) : 0;
2982 SMESH_CATCH( SMESH::throwCorbaException );
2986 //=======================================================================
2989 //=======================================================================
2991 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
2992 const SMESH::AxisStruct & theAxis,
2993 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2994 CORBA::Boolean theCopy)
2995 throw (SALOME::SALOME_Exception)
2997 if ( !myIsPreviewMode ) {
2998 TPythonDump() << this << ".Mirror( "
2999 << theIDsOfElements << ", "
3001 << mirrorTypeName(theMirrorType) << ", "
3004 if ( theIDsOfElements.length() > 0 )
3006 TIDSortedElemSet elements;
3007 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3008 mirror(elements, theAxis, theMirrorType, theCopy, false);
3013 //=======================================================================
3014 //function : MirrorObject
3016 //=======================================================================
3018 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3019 const SMESH::AxisStruct & theAxis,
3020 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3021 CORBA::Boolean theCopy)
3022 throw (SALOME::SALOME_Exception)
3024 if ( !myIsPreviewMode ) {
3025 TPythonDump() << this << ".MirrorObject( "
3026 << theObject << ", "
3028 << mirrorTypeName(theMirrorType) << ", "
3031 TIDSortedElemSet elements;
3033 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3035 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3036 mirror(elements, theAxis, theMirrorType, theCopy, false);
3039 //=======================================================================
3040 //function : MirrorMakeGroups
3042 //=======================================================================
3044 SMESH::ListOfGroups*
3045 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3046 const SMESH::AxisStruct& theMirror,
3047 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3048 throw (SALOME::SALOME_Exception)
3050 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3052 SMESH::ListOfGroups * aGroups = 0;
3053 if ( theIDsOfElements.length() > 0 )
3055 TIDSortedElemSet elements;
3056 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3057 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3059 if (!myIsPreviewMode) {
3060 dumpGroupsList(aPythonDump, aGroups);
3061 aPythonDump << this << ".MirrorMakeGroups( "
3062 << theIDsOfElements << ", "
3063 << theMirror << ", "
3064 << mirrorTypeName(theMirrorType) << " )";
3069 //=======================================================================
3070 //function : MirrorObjectMakeGroups
3072 //=======================================================================
3074 SMESH::ListOfGroups*
3075 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3076 const SMESH::AxisStruct& theMirror,
3077 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3078 throw (SALOME::SALOME_Exception)
3080 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3082 SMESH::ListOfGroups * aGroups = 0;
3083 TIDSortedElemSet elements;
3084 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3085 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3087 if (!myIsPreviewMode)
3089 dumpGroupsList(aPythonDump,aGroups);
3090 aPythonDump << this << ".MirrorObjectMakeGroups( "
3091 << theObject << ", "
3092 << theMirror << ", "
3093 << mirrorTypeName(theMirrorType) << " )";
3098 //=======================================================================
3099 //function : MirrorMakeMesh
3101 //=======================================================================
3103 SMESH::SMESH_Mesh_ptr
3104 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3105 const SMESH::AxisStruct& theMirror,
3106 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3107 CORBA::Boolean theCopyGroups,
3108 const char* theMeshName)
3109 throw (SALOME::SALOME_Exception)
3111 SMESH_Mesh_i* mesh_i;
3112 SMESH::SMESH_Mesh_var mesh;
3113 { // open new scope to dump "MakeMesh" command
3114 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3116 TPythonDump pydump; // to prevent dump at mesh creation
3118 mesh = makeMesh( theMeshName );
3119 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3120 if (mesh_i && theIDsOfElements.length() > 0 )
3122 TIDSortedElemSet elements;
3123 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3124 mirror(elements, theMirror, theMirrorType,
3125 false, theCopyGroups, & mesh_i->GetImpl());
3126 mesh_i->CreateGroupServants();
3129 if (!myIsPreviewMode) {
3130 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3131 << theIDsOfElements << ", "
3132 << theMirror << ", "
3133 << mirrorTypeName(theMirrorType) << ", "
3134 << theCopyGroups << ", '"
3135 << theMeshName << "' )";
3140 if (!myIsPreviewMode && mesh_i)
3141 mesh_i->GetGroups();
3143 return mesh._retn();
3146 //=======================================================================
3147 //function : MirrorObjectMakeMesh
3149 //=======================================================================
3151 SMESH::SMESH_Mesh_ptr
3152 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3153 const SMESH::AxisStruct& theMirror,
3154 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3155 CORBA::Boolean theCopyGroups,
3156 const char* theMeshName)
3157 throw (SALOME::SALOME_Exception)
3159 SMESH_Mesh_i* mesh_i;
3160 SMESH::SMESH_Mesh_var mesh;
3161 { // open new scope to dump "MakeMesh" command
3162 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3164 TPythonDump pydump; // to prevent dump at mesh creation
3166 mesh = makeMesh( theMeshName );
3167 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3168 TIDSortedElemSet elements;
3170 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3172 mirror(elements, theMirror, theMirrorType,
3173 false, theCopyGroups, & mesh_i->GetImpl());
3174 mesh_i->CreateGroupServants();
3176 if (!myIsPreviewMode) {
3177 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3178 << theObject << ", "
3179 << theMirror << ", "
3180 << mirrorTypeName(theMirrorType) << ", "
3181 << theCopyGroups << ", '"
3182 << theMeshName << "' )";
3187 if (!myIsPreviewMode && mesh_i)
3188 mesh_i->GetGroups();
3190 return mesh._retn();
3193 //=======================================================================
3194 //function : translate
3196 //=======================================================================
3198 SMESH::ListOfGroups*
3199 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3200 const SMESH::DirStruct & theVector,
3201 CORBA::Boolean theCopy,
3203 ::SMESH_Mesh* theTargetMesh)
3204 throw (SALOME::SALOME_Exception)
3209 if ( theTargetMesh )
3213 const SMESH::PointStruct * P = &theVector.PS;
3214 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3216 TIDSortedElemSet copyElements;
3217 TIDSortedElemSet* workElements = &theElements;
3219 if ( myIsPreviewMode )
3221 TPreviewMesh * tmpMesh = getPreviewMesh();
3222 tmpMesh->Copy( theElements, copyElements);
3223 if ( !theCopy && !theTargetMesh )
3225 TIDSortedElemSet elemsAround, elemsAroundCopy;
3226 getElementsAround( theElements, getMeshDS(), elemsAround );
3227 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3229 workElements = & copyElements;
3230 theMakeGroups = false;
3233 ::SMESH_MeshEditor::PGroupIDs groupIds =
3234 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3236 if ( theCopy && !myIsPreviewMode )
3238 if ( theTargetMesh )
3240 theTargetMesh->GetMeshDS()->Modified();
3244 declareMeshModified( /*isReComputeSafe=*/false );
3248 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3250 SMESH_CATCH( SMESH::throwCorbaException );
3254 //=======================================================================
3255 //function : Translate
3257 //=======================================================================
3259 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3260 const SMESH::DirStruct & theVector,
3261 CORBA::Boolean theCopy)
3262 throw (SALOME::SALOME_Exception)
3264 if (!myIsPreviewMode) {
3265 TPythonDump() << this << ".Translate( "
3266 << theIDsOfElements << ", "
3267 << theVector << ", "
3270 if (theIDsOfElements.length()) {
3271 TIDSortedElemSet elements;
3272 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3273 translate(elements, theVector, theCopy, false);
3277 //=======================================================================
3278 //function : TranslateObject
3280 //=======================================================================
3282 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3283 const SMESH::DirStruct & theVector,
3284 CORBA::Boolean theCopy)
3285 throw (SALOME::SALOME_Exception)
3287 if (!myIsPreviewMode) {
3288 TPythonDump() << this << ".TranslateObject( "
3289 << theObject << ", "
3290 << theVector << ", "
3293 TIDSortedElemSet elements;
3295 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3297 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3298 translate(elements, theVector, theCopy, false);
3301 //=======================================================================
3302 //function : TranslateMakeGroups
3304 //=======================================================================
3306 SMESH::ListOfGroups*
3307 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3308 const SMESH::DirStruct& theVector)
3309 throw (SALOME::SALOME_Exception)
3311 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3313 SMESH::ListOfGroups * aGroups = 0;
3314 if (theIDsOfElements.length()) {
3315 TIDSortedElemSet elements;
3316 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3317 aGroups = translate(elements,theVector,true,true);
3319 if (!myIsPreviewMode) {
3320 dumpGroupsList(aPythonDump, aGroups);
3321 aPythonDump << this << ".TranslateMakeGroups( "
3322 << theIDsOfElements << ", "
3323 << theVector << " )";
3328 //=======================================================================
3329 //function : TranslateObjectMakeGroups
3331 //=======================================================================
3333 SMESH::ListOfGroups*
3334 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3335 const SMESH::DirStruct& theVector)
3336 throw (SALOME::SALOME_Exception)
3338 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3340 SMESH::ListOfGroups * aGroups = 0;
3341 TIDSortedElemSet elements;
3342 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3343 aGroups = translate(elements, theVector, true, true);
3345 if (!myIsPreviewMode) {
3346 dumpGroupsList(aPythonDump, aGroups);
3347 aPythonDump << this << ".TranslateObjectMakeGroups( "
3348 << theObject << ", "
3349 << theVector << " )";
3354 //=======================================================================
3355 //function : TranslateMakeMesh
3357 //=======================================================================
3359 SMESH::SMESH_Mesh_ptr
3360 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3361 const SMESH::DirStruct& theVector,
3362 CORBA::Boolean theCopyGroups,
3363 const char* theMeshName)
3364 throw (SALOME::SALOME_Exception)
3366 SMESH_Mesh_i* mesh_i;
3367 SMESH::SMESH_Mesh_var mesh;
3369 { // open new scope to dump "MakeMesh" command
3370 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3372 TPythonDump pydump; // to prevent dump at mesh creation
3374 mesh = makeMesh( theMeshName );
3375 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3377 if ( mesh_i && theIDsOfElements.length() )
3379 TIDSortedElemSet elements;
3380 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3381 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3382 mesh_i->CreateGroupServants();
3385 if ( !myIsPreviewMode ) {
3386 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3387 << theIDsOfElements << ", "
3388 << theVector << ", "
3389 << theCopyGroups << ", '"
3390 << theMeshName << "' )";
3395 if (!myIsPreviewMode && mesh_i)
3396 mesh_i->GetGroups();
3398 return mesh._retn();
3401 //=======================================================================
3402 //function : TranslateObjectMakeMesh
3404 //=======================================================================
3406 SMESH::SMESH_Mesh_ptr
3407 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3408 const SMESH::DirStruct& theVector,
3409 CORBA::Boolean theCopyGroups,
3410 const char* theMeshName)
3411 throw (SALOME::SALOME_Exception)
3414 SMESH_Mesh_i* mesh_i;
3415 SMESH::SMESH_Mesh_var mesh;
3416 { // open new scope to dump "MakeMesh" command
3417 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3419 TPythonDump pydump; // to prevent dump at mesh creation
3420 mesh = makeMesh( theMeshName );
3421 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3423 TIDSortedElemSet elements;
3425 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3427 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3428 mesh_i->CreateGroupServants();
3430 if ( !myIsPreviewMode ) {
3431 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3432 << theObject << ", "
3433 << theVector << ", "
3434 << theCopyGroups << ", '"
3435 << theMeshName << "' )";
3440 if (!myIsPreviewMode && mesh_i)
3441 mesh_i->GetGroups();
3443 return mesh._retn();
3445 SMESH_CATCH( SMESH::throwCorbaException );
3449 //=======================================================================
3452 //=======================================================================
3454 SMESH::ListOfGroups*
3455 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3456 const SMESH::AxisStruct & theAxis,
3457 CORBA::Double theAngle,
3458 CORBA::Boolean theCopy,
3460 ::SMESH_Mesh* theTargetMesh)
3461 throw (SALOME::SALOME_Exception)
3466 if ( theTargetMesh )
3469 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3470 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3473 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3475 TIDSortedElemSet copyElements;
3476 TIDSortedElemSet* workElements = &theElements;
3477 if ( myIsPreviewMode ) {
3478 TPreviewMesh * tmpMesh = getPreviewMesh();
3479 tmpMesh->Copy( theElements, copyElements );
3480 if ( !theCopy && !theTargetMesh )
3482 TIDSortedElemSet elemsAround, elemsAroundCopy;
3483 getElementsAround( theElements, getMeshDS(), elemsAround );
3484 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3486 workElements = ©Elements;
3487 theMakeGroups = false;
3490 ::SMESH_MeshEditor::PGroupIDs groupIds =
3491 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3493 if ( theCopy && !myIsPreviewMode)
3495 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3496 else declareMeshModified( /*isReComputeSafe=*/false );
3499 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3501 SMESH_CATCH( SMESH::throwCorbaException );
3505 //=======================================================================
3508 //=======================================================================
3510 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3511 const SMESH::AxisStruct & theAxis,
3512 CORBA::Double theAngle,
3513 CORBA::Boolean theCopy)
3514 throw (SALOME::SALOME_Exception)
3516 if (!myIsPreviewMode) {
3517 TPythonDump() << this << ".Rotate( "
3518 << theIDsOfElements << ", "
3520 << TVar( theAngle ) << ", "
3523 if (theIDsOfElements.length() > 0)
3525 TIDSortedElemSet elements;
3526 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3527 rotate(elements,theAxis,theAngle,theCopy,false);
3531 //=======================================================================
3532 //function : RotateObject
3534 //=======================================================================
3536 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3537 const SMESH::AxisStruct & theAxis,
3538 CORBA::Double theAngle,
3539 CORBA::Boolean theCopy)
3540 throw (SALOME::SALOME_Exception)
3542 if ( !myIsPreviewMode ) {
3543 TPythonDump() << this << ".RotateObject( "
3544 << theObject << ", "
3546 << TVar( theAngle ) << ", "
3549 TIDSortedElemSet elements;
3550 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3551 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3552 rotate(elements,theAxis,theAngle,theCopy,false);
3555 //=======================================================================
3556 //function : RotateMakeGroups
3558 //=======================================================================
3560 SMESH::ListOfGroups*
3561 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3562 const SMESH::AxisStruct& theAxis,
3563 CORBA::Double theAngle)
3564 throw (SALOME::SALOME_Exception)
3566 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3568 SMESH::ListOfGroups * aGroups = 0;
3569 if (theIDsOfElements.length() > 0)
3571 TIDSortedElemSet elements;
3572 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3573 aGroups = rotate(elements,theAxis,theAngle,true,true);
3575 if (!myIsPreviewMode) {
3576 dumpGroupsList(aPythonDump, aGroups);
3577 aPythonDump << this << ".RotateMakeGroups( "
3578 << theIDsOfElements << ", "
3580 << TVar( theAngle ) << " )";
3585 //=======================================================================
3586 //function : RotateObjectMakeGroups
3588 //=======================================================================
3590 SMESH::ListOfGroups*
3591 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3592 const SMESH::AxisStruct& theAxis,
3593 CORBA::Double theAngle)
3594 throw (SALOME::SALOME_Exception)
3596 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3598 SMESH::ListOfGroups * aGroups = 0;
3599 TIDSortedElemSet elements;
3600 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3601 aGroups = rotate(elements, theAxis, theAngle, true, true);
3603 if (!myIsPreviewMode) {
3604 dumpGroupsList(aPythonDump, aGroups);
3605 aPythonDump << this << ".RotateObjectMakeGroups( "
3606 << theObject << ", "
3608 << TVar( theAngle ) << " )";
3613 //=======================================================================
3614 //function : RotateMakeMesh
3616 //=======================================================================
3618 SMESH::SMESH_Mesh_ptr
3619 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3620 const SMESH::AxisStruct& theAxis,
3621 CORBA::Double theAngleInRadians,
3622 CORBA::Boolean theCopyGroups,
3623 const char* theMeshName)
3624 throw (SALOME::SALOME_Exception)
3627 SMESH::SMESH_Mesh_var mesh;
3628 SMESH_Mesh_i* mesh_i;
3630 { // open new scope to dump "MakeMesh" command
3631 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3633 TPythonDump pydump; // to prevent dump at mesh creation
3635 mesh = makeMesh( theMeshName );
3636 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3638 if ( mesh_i && theIDsOfElements.length() > 0 )
3640 TIDSortedElemSet elements;
3641 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3642 rotate(elements, theAxis, theAngleInRadians,
3643 false, theCopyGroups, & mesh_i->GetImpl());
3644 mesh_i->CreateGroupServants();
3646 if ( !myIsPreviewMode ) {
3647 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3648 << theIDsOfElements << ", "
3650 << TVar( theAngleInRadians ) << ", "
3651 << theCopyGroups << ", '"
3652 << theMeshName << "' )";
3657 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3658 mesh_i->GetGroups();
3660 return mesh._retn();
3662 SMESH_CATCH( SMESH::throwCorbaException );
3666 //=======================================================================
3667 //function : RotateObjectMakeMesh
3669 //=======================================================================
3671 SMESH::SMESH_Mesh_ptr
3672 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3673 const SMESH::AxisStruct& theAxis,
3674 CORBA::Double theAngleInRadians,
3675 CORBA::Boolean theCopyGroups,
3676 const char* theMeshName)
3677 throw (SALOME::SALOME_Exception)
3680 SMESH::SMESH_Mesh_var mesh;
3681 SMESH_Mesh_i* mesh_i;
3683 {// open new scope to dump "MakeMesh" command
3684 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3686 TPythonDump pydump; // to prevent dump at mesh creation
3687 mesh = makeMesh( theMeshName );
3688 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3690 TIDSortedElemSet elements;
3692 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3694 rotate(elements, theAxis, theAngleInRadians,
3695 false, theCopyGroups, & mesh_i->GetImpl());
3696 mesh_i->CreateGroupServants();
3698 if ( !myIsPreviewMode ) {
3699 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3700 << theObject << ", "
3702 << TVar( theAngleInRadians ) << ", "
3703 << theCopyGroups << ", '"
3704 << theMeshName << "' )";
3709 if (!myIsPreviewMode && mesh_i)
3710 mesh_i->GetGroups();
3712 return mesh._retn();
3714 SMESH_CATCH( SMESH::throwCorbaException );
3718 //=======================================================================
3721 //=======================================================================
3723 SMESH::ListOfGroups*
3724 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3725 const SMESH::PointStruct& thePoint,
3726 const SMESH::double_array& theScaleFact,
3727 CORBA::Boolean theCopy,
3729 ::SMESH_Mesh* theTargetMesh)
3730 throw (SALOME::SALOME_Exception)
3734 if ( theScaleFact.length() < 1 )
3735 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3736 if ( theScaleFact.length() == 2 )
3737 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3739 if ( theTargetMesh )
3742 TIDSortedElemSet elements;
3743 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3744 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3749 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3750 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3752 double tol = std::numeric_limits<double>::max();
3755 #if OCC_VERSION_LARGE > 0x06070100
3756 // fight against ortagonalization
3757 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3758 // 0, S[1], 0, thePoint.y * (1-S[1]),
3759 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3760 aTrsf.SetTranslation( gp_Vec( thePoint.x * (1-S[0]),
3761 thePoint.y * (1-S[1]),
3762 thePoint.z * (1-S[2])));
3763 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3764 M.SetDiagonal( S[0], S[1], S[2] );
3767 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3768 0, S[1], 0, thePoint.y * (1-S[1]),
3769 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3772 TIDSortedElemSet copyElements;
3773 TIDSortedElemSet* workElements = &elements;
3774 if ( myIsPreviewMode )
3776 TPreviewMesh * tmpMesh = getPreviewMesh();
3777 tmpMesh->Copy( elements, copyElements);
3778 if ( !theCopy && !theTargetMesh )
3780 TIDSortedElemSet elemsAround, elemsAroundCopy;
3781 getElementsAround( elements, getMeshDS(), elemsAround );
3782 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3784 workElements = & copyElements;
3785 theMakeGroups = false;
3788 ::SMESH_MeshEditor::PGroupIDs groupIds =
3789 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3791 if ( theCopy && !myIsPreviewMode )
3793 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3794 else declareMeshModified( /*isReComputeSafe=*/false );
3796 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3798 SMESH_CATCH( SMESH::throwCorbaException );
3802 //=======================================================================
3805 //=======================================================================
3807 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3808 const SMESH::PointStruct& thePoint,
3809 const SMESH::double_array& theScaleFact,
3810 CORBA::Boolean theCopy)
3811 throw (SALOME::SALOME_Exception)
3813 if ( !myIsPreviewMode ) {
3814 TPythonDump() << this << ".Scale( "
3815 << theObject << ", "
3817 << TVar( theScaleFact ) << ", "
3820 scale(theObject, thePoint, theScaleFact, theCopy, false);
3824 //=======================================================================
3825 //function : ScaleMakeGroups
3827 //=======================================================================
3829 SMESH::ListOfGroups*
3830 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3831 const SMESH::PointStruct& thePoint,
3832 const SMESH::double_array& theScaleFact)
3833 throw (SALOME::SALOME_Exception)
3835 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3837 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3838 if (!myIsPreviewMode) {
3839 dumpGroupsList(aPythonDump, aGroups);
3840 aPythonDump << this << ".Scale("
3843 << TVar( theScaleFact ) << ",True,True)";
3849 //=======================================================================
3850 //function : ScaleMakeMesh
3852 //=======================================================================
3854 SMESH::SMESH_Mesh_ptr
3855 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3856 const SMESH::PointStruct& thePoint,
3857 const SMESH::double_array& theScaleFact,
3858 CORBA::Boolean theCopyGroups,
3859 const char* theMeshName)
3860 throw (SALOME::SALOME_Exception)
3862 SMESH_Mesh_i* mesh_i;
3863 SMESH::SMESH_Mesh_var mesh;
3864 { // open new scope to dump "MakeMesh" command
3865 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3867 TPythonDump pydump; // to prevent dump at mesh creation
3868 mesh = makeMesh( theMeshName );
3869 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3873 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3874 mesh_i->CreateGroupServants();
3876 if ( !myIsPreviewMode )
3877 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3878 << theObject << ", "
3880 << TVar( theScaleFact ) << ", "
3881 << theCopyGroups << ", '"
3882 << theMeshName << "' )";
3886 if (!myIsPreviewMode && mesh_i)
3887 mesh_i->GetGroups();
3889 return mesh._retn();
3893 //=======================================================================
3894 //function : FindCoincidentNodes
3896 //=======================================================================
3898 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tolerance,
3899 SMESH::array_of_long_array_out GroupsOfNodes)
3900 throw (SALOME::SALOME_Exception)
3905 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3906 TIDSortedNodeSet nodes; // no input nodes
3907 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3909 GroupsOfNodes = new SMESH::array_of_long_array;
3910 GroupsOfNodes->length( aListOfListOfNodes.size() );
3911 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3912 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3913 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3914 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3915 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3916 aGroup.length( aListOfNodes.size() );
3917 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3918 aGroup[ j ] = (*lIt)->GetID();
3920 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3921 << Tolerance << " )";
3923 SMESH_CATCH( SMESH::throwCorbaException );
3926 //=======================================================================
3927 //function : FindCoincidentNodesOnPart
3929 //=======================================================================
3931 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
3932 CORBA::Double Tolerance,
3933 SMESH::array_of_long_array_out GroupsOfNodes)
3934 throw (SALOME::SALOME_Exception)
3939 TIDSortedNodeSet nodes;
3940 idSourceToNodeSet( theObject, getMeshDS(), nodes );
3942 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3944 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3946 GroupsOfNodes = new SMESH::array_of_long_array;
3947 GroupsOfNodes->length( aListOfListOfNodes.size() );
3948 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3949 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3951 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3952 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3953 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3954 aGroup.length( aListOfNodes.size() );
3955 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3956 aGroup[ j ] = (*lIt)->GetID();
3958 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
3960 << Tolerance << " )";
3962 SMESH_CATCH( SMESH::throwCorbaException );
3965 //================================================================================
3967 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
3968 * ExceptSubMeshOrGroups
3970 //================================================================================
3972 void SMESH_MeshEditor_i::
3973 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
3974 CORBA::Double theTolerance,
3975 SMESH::array_of_long_array_out theGroupsOfNodes,
3976 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups)
3977 throw (SALOME::SALOME_Exception)
3982 TIDSortedNodeSet nodes;
3983 idSourceToNodeSet( theObject, getMeshDS(), nodes );
3985 for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
3987 TIDSortedNodeSet exceptNodes;
3988 idSourceToNodeSet( theExceptSubMeshOrGroups[i], getMeshDS(), exceptNodes );
3989 TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
3990 for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
3991 nodes.erase( *avoidNode );
3993 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3995 getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
3997 theGroupsOfNodes = new SMESH::array_of_long_array;
3998 theGroupsOfNodes->length( aListOfListOfNodes.size() );
3999 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4000 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4002 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4003 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4004 SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
4005 aGroup.length( aListOfNodes.size() );
4006 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4007 aGroup[ j ] = (*lIt)->GetID();
4009 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4011 << theTolerance << ", "
4012 << theExceptSubMeshOrGroups << " )";
4014 SMESH_CATCH( SMESH::throwCorbaException );
4017 //=======================================================================
4018 //function : MergeNodes
4020 //=======================================================================
4022 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
4023 throw (SALOME::SALOME_Exception)
4028 SMESHDS_Mesh* aMesh = getMeshDS();
4030 TPythonDump aTPythonDump;
4031 aTPythonDump << this << ".MergeNodes([";
4032 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4033 for (int i = 0; i < GroupsOfNodes.length(); i++)
4035 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4036 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4037 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4038 for ( int j = 0; j < aNodeGroup.length(); j++ )
4040 CORBA::Long index = aNodeGroup[ j ];
4041 const SMDS_MeshNode * node = aMesh->FindNode(index);
4043 aListOfNodes.push_back( node );
4045 if ( aListOfNodes.size() < 2 )
4046 aListOfListOfNodes.pop_back();
4048 if ( i > 0 ) aTPythonDump << ", ";
4049 aTPythonDump << aNodeGroup;
4051 getEditor().MergeNodes( aListOfListOfNodes );
4053 aTPythonDump << "])";
4055 declareMeshModified( /*isReComputeSafe=*/false );
4057 SMESH_CATCH( SMESH::throwCorbaException );
4060 //=======================================================================
4061 //function : FindEqualElements
4063 //=======================================================================
4065 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4066 SMESH::array_of_long_array_out GroupsOfElementsID)
4067 throw (SALOME::SALOME_Exception)
4072 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4073 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4075 TIDSortedElemSet elems;
4076 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4078 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4079 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4081 GroupsOfElementsID = new SMESH::array_of_long_array;
4082 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4084 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4085 aListOfListOfElementsID.begin();
4086 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4088 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4089 list<int>& listOfIDs = *arraysIt;
4090 aGroup.length( listOfIDs.size() );
4091 list<int>::iterator idIt = listOfIDs.begin();
4092 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4093 aGroup[ k ] = *idIt;
4096 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4100 SMESH_CATCH( SMESH::throwCorbaException );
4103 //=======================================================================
4104 //function : MergeElements
4106 //=======================================================================
4108 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4109 throw (SALOME::SALOME_Exception)
4114 TPythonDump aTPythonDump;
4115 aTPythonDump << this << ".MergeElements( [";
4117 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4119 for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4120 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4121 aListOfListOfElementsID.push_back( list< int >() );
4122 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4123 for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4124 CORBA::Long id = anElemsIDGroup[ j ];
4125 aListOfElemsID.push_back( id );
4127 if ( aListOfElemsID.size() < 2 )
4128 aListOfListOfElementsID.pop_back();
4129 if ( i > 0 ) aTPythonDump << ", ";
4130 aTPythonDump << anElemsIDGroup;
4133 getEditor().MergeElements(aListOfListOfElementsID);
4135 declareMeshModified( /*isReComputeSafe=*/true );
4137 aTPythonDump << "] )";
4139 SMESH_CATCH( SMESH::throwCorbaException );
4142 //=======================================================================
4143 //function : MergeEqualElements
4145 //=======================================================================
4147 void SMESH_MeshEditor_i::MergeEqualElements()
4148 throw (SALOME::SALOME_Exception)
4153 getEditor().MergeEqualElements();
4155 declareMeshModified( /*isReComputeSafe=*/true );
4157 TPythonDump() << this << ".MergeEqualElements()";
4159 SMESH_CATCH( SMESH::throwCorbaException );
4162 //=============================================================================
4164 * Move the node to a given point
4166 //=============================================================================
4168 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4172 throw (SALOME::SALOME_Exception)
4175 initData(/*deleteSearchers=*/false);
4177 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4181 if ( theNodeSearcher )
4182 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4184 if ( myIsPreviewMode ) // make preview data
4186 // in a preview mesh, make edges linked to a node
4187 TPreviewMesh& tmpMesh = *getPreviewMesh();
4188 TIDSortedElemSet linkedNodes;
4189 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4190 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4191 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4192 for ( ; nIt != linkedNodes.end(); ++nIt )
4194 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4195 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4199 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4200 // fill preview data
4202 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4203 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4205 getMeshDS()->MoveNode(node, x, y, z);
4207 if ( !myIsPreviewMode )
4209 // Update Python script
4210 TPythonDump() << "isDone = " << this << ".MoveNode( "
4211 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4212 declareMeshModified( /*isReComputeSafe=*/false );
4215 SMESH_CATCH( SMESH::throwCorbaException );
4220 //================================================================================
4222 * \brief Return ID of node closest to a given point
4224 //================================================================================
4226 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4229 throw (SALOME::SALOME_Exception)
4232 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4234 if ( !theNodeSearcher ) {
4235 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4238 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4239 return node->GetID();
4241 SMESH_CATCH( SMESH::throwCorbaException );
4245 //================================================================================
4247 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4248 * move the node closest to the point to point's location and return ID of the node
4250 //================================================================================
4252 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4255 CORBA::Long theNodeID)
4256 throw (SALOME::SALOME_Exception)
4259 // We keep theNodeSearcher until any mesh modification:
4260 // 1) initData() deletes theNodeSearcher at any edition,
4261 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4263 initData(/*deleteSearchers=*/false);
4265 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4267 int nodeID = theNodeID;
4268 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4269 if ( !node ) // preview moving node
4271 if ( !theNodeSearcher ) {
4272 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4275 node = theNodeSearcher->FindClosestTo( p );
4278 nodeID = node->GetID();
4279 if ( myIsPreviewMode ) // make preview data
4281 // in a preview mesh, make edges linked to a node
4282 TPreviewMesh tmpMesh = *getPreviewMesh();
4283 TIDSortedElemSet linkedNodes;
4284 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4285 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4286 for ( ; nIt != linkedNodes.end(); ++nIt )
4288 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4289 tmpMesh.Copy( &edge );
4292 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4294 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4295 // fill preview data
4297 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4299 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4303 getMeshDS()->MoveNode(node, x, y, z);
4307 if ( !myIsPreviewMode )
4309 TPythonDump() << "nodeID = " << this
4310 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4311 << ", " << nodeID << " )";
4313 declareMeshModified( /*isReComputeSafe=*/false );
4318 SMESH_CATCH( SMESH::throwCorbaException );
4322 //=======================================================================
4324 * Return elements of given type where the given point is IN or ON.
4326 * 'ALL' type means elements of any type excluding nodes
4328 //=======================================================================
4330 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4333 SMESH::ElementType type)
4334 throw (SALOME::SALOME_Exception)
4337 SMESH::long_array_var res = new SMESH::long_array;
4338 vector< const SMDS_MeshElement* > foundElems;
4340 theSearchersDeleter.Set( myMesh );
4341 if ( !theElementSearcher ) {
4342 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4344 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4345 SMDSAbs_ElementType( type ),
4347 res->length( foundElems.size() );
4348 for ( int i = 0; i < foundElems.size(); ++i )
4349 res[i] = foundElems[i]->GetID();
4353 SMESH_CATCH( SMESH::throwCorbaException );
4357 //=======================================================================
4358 //function : FindAmongElementsByPoint
4359 //purpose : Searching among the given elements, return elements of given type
4360 // where the given point is IN or ON.
4361 // 'ALL' type means elements of any type excluding nodes
4362 //=======================================================================
4365 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4369 SMESH::ElementType type)
4370 throw (SALOME::SALOME_Exception)
4373 SMESH::long_array_var res = new SMESH::long_array;
4375 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4376 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4377 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4378 type != types[0] ) // but search of elements of dim > 0
4381 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4382 return FindElementsByPoint( x,y,z, type );
4384 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4386 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4387 if ( !theElementSearcher )
4389 // create a searcher from elementIDs
4390 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4391 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4393 if ( !idSourceToSet( elementIDs, meshDS, elements,
4394 SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4397 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4398 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4400 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4403 vector< const SMDS_MeshElement* > foundElems;
4405 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4406 SMDSAbs_ElementType( type ),
4408 res->length( foundElems.size() );
4409 for ( int i = 0; i < foundElems.size(); ++i )
4410 res[i] = foundElems[i]->GetID();
4414 SMESH_CATCH( SMESH::throwCorbaException );
4418 //=======================================================================
4419 //function : GetPointState
4420 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4421 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4422 //=======================================================================
4424 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4427 throw (SALOME::SALOME_Exception)
4430 theSearchersDeleter.Set( myMesh );
4431 if ( !theElementSearcher ) {
4432 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4434 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4436 SMESH_CATCH( SMESH::throwCorbaException );
4440 //=======================================================================
4441 //function : convError
4443 //=======================================================================
4445 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4447 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4451 RETCASE( SEW_BORDER1_NOT_FOUND );
4452 RETCASE( SEW_BORDER2_NOT_FOUND );
4453 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4454 RETCASE( SEW_BAD_SIDE_NODES );
4455 RETCASE( SEW_VOLUMES_TO_SPLIT );
4456 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4457 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4458 RETCASE( SEW_BAD_SIDE1_NODES );
4459 RETCASE( SEW_BAD_SIDE2_NODES );
4461 return SMESH::SMESH_MeshEditor::SEW_OK;
4464 //=======================================================================
4465 //function : SewFreeBorders
4467 //=======================================================================
4469 SMESH::SMESH_MeshEditor::Sew_Error
4470 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4471 CORBA::Long SecondNodeID1,
4472 CORBA::Long LastNodeID1,
4473 CORBA::Long FirstNodeID2,
4474 CORBA::Long SecondNodeID2,
4475 CORBA::Long LastNodeID2,
4476 CORBA::Boolean CreatePolygons,
4477 CORBA::Boolean CreatePolyedrs)
4478 throw (SALOME::SALOME_Exception)
4483 SMESHDS_Mesh* aMesh = getMeshDS();
4485 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4486 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4487 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4488 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4489 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4490 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4492 if (!aBorderFirstNode ||
4493 !aBorderSecondNode||
4495 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4496 if (!aSide2FirstNode ||
4497 !aSide2SecondNode ||
4499 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4501 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4502 << FirstNodeID1 << ", "
4503 << SecondNodeID1 << ", "
4504 << LastNodeID1 << ", "
4505 << FirstNodeID2 << ", "
4506 << SecondNodeID2 << ", "
4507 << LastNodeID2 << ", "
4508 << CreatePolygons<< ", "
4509 << CreatePolyedrs<< " )";
4511 SMESH::SMESH_MeshEditor::Sew_Error error =
4512 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4523 declareMeshModified( /*isReComputeSafe=*/false );
4526 SMESH_CATCH( SMESH::throwCorbaException );
4527 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4531 //=======================================================================
4532 //function : SewConformFreeBorders
4534 //=======================================================================
4536 SMESH::SMESH_MeshEditor::Sew_Error
4537 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4538 CORBA::Long SecondNodeID1,
4539 CORBA::Long LastNodeID1,
4540 CORBA::Long FirstNodeID2,
4541 CORBA::Long SecondNodeID2)
4542 throw (SALOME::SALOME_Exception)
4547 SMESHDS_Mesh* aMesh = getMeshDS();
4549 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4550 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4551 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4552 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4553 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4554 const SMDS_MeshNode* aSide2ThirdNode = 0;
4556 if (!aBorderFirstNode ||
4557 !aBorderSecondNode||
4559 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4560 if (!aSide2FirstNode ||
4562 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4564 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4565 << FirstNodeID1 << ", "
4566 << SecondNodeID1 << ", "
4567 << LastNodeID1 << ", "
4568 << FirstNodeID2 << ", "
4569 << SecondNodeID2 << " )";
4571 SMESH::SMESH_MeshEditor::Sew_Error error =
4572 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4581 declareMeshModified( /*isReComputeSafe=*/false );
4584 SMESH_CATCH( SMESH::throwCorbaException );
4585 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4589 //=======================================================================
4590 //function : SewBorderToSide
4592 //=======================================================================
4594 SMESH::SMESH_MeshEditor::Sew_Error
4595 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4596 CORBA::Long SecondNodeIDOnFreeBorder,
4597 CORBA::Long LastNodeIDOnFreeBorder,
4598 CORBA::Long FirstNodeIDOnSide,
4599 CORBA::Long LastNodeIDOnSide,
4600 CORBA::Boolean CreatePolygons,
4601 CORBA::Boolean CreatePolyedrs)
4602 throw (SALOME::SALOME_Exception)
4607 SMESHDS_Mesh* aMesh = getMeshDS();
4609 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4610 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4611 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4612 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4613 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4614 const SMDS_MeshNode* aSide2ThirdNode = 0;
4616 if (!aBorderFirstNode ||
4617 !aBorderSecondNode||
4619 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4620 if (!aSide2FirstNode ||
4622 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4624 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4625 << FirstNodeIDOnFreeBorder << ", "
4626 << SecondNodeIDOnFreeBorder << ", "
4627 << LastNodeIDOnFreeBorder << ", "
4628 << FirstNodeIDOnSide << ", "
4629 << LastNodeIDOnSide << ", "
4630 << CreatePolygons << ", "
4631 << CreatePolyedrs << ") ";
4633 SMESH::SMESH_MeshEditor::Sew_Error error =
4634 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4644 declareMeshModified( /*isReComputeSafe=*/false );
4647 SMESH_CATCH( SMESH::throwCorbaException );
4648 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4652 //=======================================================================
4653 //function : SewSideElements
4655 //=======================================================================
4657 SMESH::SMESH_MeshEditor::Sew_Error
4658 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4659 const SMESH::long_array& IDsOfSide2Elements,
4660 CORBA::Long NodeID1OfSide1ToMerge,
4661 CORBA::Long NodeID1OfSide2ToMerge,
4662 CORBA::Long NodeID2OfSide1ToMerge,
4663 CORBA::Long NodeID2OfSide2ToMerge)
4664 throw (SALOME::SALOME_Exception)
4669 SMESHDS_Mesh* aMesh = getMeshDS();
4671 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
4672 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
4673 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4674 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4676 if (!aFirstNode1ToMerge ||
4677 !aFirstNode2ToMerge )
4678 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4679 if (!aSecondNode1ToMerge||
4680 !aSecondNode2ToMerge)
4681 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4683 TIDSortedElemSet aSide1Elems, aSide2Elems;
4684 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4685 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4687 TPythonDump() << "error = " << this << ".SewSideElements( "
4688 << IDsOfSide1Elements << ", "
4689 << IDsOfSide2Elements << ", "
4690 << NodeID1OfSide1ToMerge << ", "
4691 << NodeID1OfSide2ToMerge << ", "
4692 << NodeID2OfSide1ToMerge << ", "
4693 << NodeID2OfSide2ToMerge << ")";
4695 SMESH::SMESH_MeshEditor::Sew_Error error =
4696 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
4699 aSecondNode1ToMerge,
4700 aSecondNode2ToMerge));
4702 declareMeshModified( /*isReComputeSafe=*/false );
4705 SMESH_CATCH( SMESH::throwCorbaException );
4706 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4709 //================================================================================
4711 * \brief Set new nodes for given element
4712 * \param ide - element id
4713 * \param newIDs - new node ids
4714 * \retval CORBA::Boolean - true if result is OK
4716 //================================================================================
4718 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4719 const SMESH::long_array& newIDs)
4720 throw (SALOME::SALOME_Exception)
4725 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
4726 if(!elem) return false;
4728 int nbn = newIDs.length();
4730 vector<const SMDS_MeshNode*> aNodes(nbn);
4733 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
4736 aNodes[nbn1] = aNode;
4739 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4740 << ide << ", " << newIDs << " )";
4742 MESSAGE("ChangeElementNodes");
4743 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4745 declareMeshModified( /*isReComputeSafe=*/ !res );
4749 SMESH_CATCH( SMESH::throwCorbaException );
4753 //=======================================================================
4755 * \brief Makes a part of the mesh quadratic or bi-quadratic
4757 //=======================================================================
4759 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
4760 CORBA::Boolean theToBiQuad,
4761 SMESH::SMESH_IDSource_ptr theObject)
4762 throw (SALOME::SALOME_Exception)
4765 TIDSortedElemSet elems;
4767 if ( !( elemsOK = CORBA::is_nil( theObject )))
4769 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
4770 SMDSAbs_All, /*emptyIfIsMesh=*/true );
4774 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
4775 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4777 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
4778 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
4780 declareMeshModified( /*isReComputeSafe=*/false );
4783 SMESH_CATCH( SMESH::throwCorbaException );
4786 //=======================================================================
4787 //function : ConvertFromQuadratic
4789 //=======================================================================
4791 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4792 throw (SALOME::SALOME_Exception)
4794 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
4795 TPythonDump() << this << ".ConvertFromQuadratic()";
4796 declareMeshModified( /*isReComputeSafe=*/!isDone );
4800 //=======================================================================
4801 //function : ConvertToQuadratic
4803 //=======================================================================
4805 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4806 throw (SALOME::SALOME_Exception)
4808 convertToQuadratic( theForce3d, false );
4809 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
4812 //================================================================================
4814 * \brief Makes a part of the mesh quadratic
4816 //================================================================================
4818 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
4819 SMESH::SMESH_IDSource_ptr theObject)
4820 throw (SALOME::SALOME_Exception)
4822 convertToQuadratic( theForce3d, false, theObject );
4823 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
4826 //================================================================================
4828 * \brief Makes a part of the mesh bi-quadratic
4830 //================================================================================
4832 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
4833 SMESH::SMESH_IDSource_ptr theObject)
4834 throw (SALOME::SALOME_Exception)
4836 convertToQuadratic( theForce3d, true, theObject );
4837 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
4840 //================================================================================
4842 * \brief Makes a part of the mesh linear
4844 //================================================================================
4846 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
4847 throw (SALOME::SALOME_Exception)
4853 TIDSortedElemSet elems;
4854 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
4856 if ( elems.empty() )
4858 ConvertFromQuadratic();
4860 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
4862 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4866 getEditor().ConvertFromQuadratic(elems);
4869 declareMeshModified( /*isReComputeSafe=*/false );
4871 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
4873 SMESH_CATCH( SMESH::throwCorbaException );
4876 //=======================================================================
4877 //function : makeMesh
4878 //purpose : create a named imported mesh
4879 //=======================================================================
4881 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4883 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4884 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4885 SALOMEDS::Study_var study = gen->GetCurrentStudy();
4886 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
4887 gen->SetName( meshSO, theMeshName, "Mesh" );
4888 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4890 return mesh._retn();
4893 //=======================================================================
4894 //function : dumpGroupsList
4896 //=======================================================================
4898 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
4899 const SMESH::ListOfGroups * theGroupList)
4901 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
4902 if ( isDumpGroupList )
4903 theDumpPython << theGroupList << " = ";
4906 //================================================================================
4908 \brief Generates the unique group name.
4909 \param thePrefix name prefix
4912 //================================================================================
4914 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
4916 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4917 set<string> groupNames;
4919 // Get existing group names
4920 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
4921 SMESH::SMESH_GroupBase_var aGroup = groups[i];
4922 if (CORBA::is_nil(aGroup))
4925 CORBA::String_var name = aGroup->GetName();
4926 groupNames.insert( name.in() );
4930 string name = thePrefix;
4933 while (!groupNames.insert(name).second)
4934 name = SMESH_Comment( thePrefix ) << "_" << index++;
4939 //================================================================================
4941 * \brief Prepare SMESH_IDSource for work
4943 //================================================================================
4945 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
4947 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
4949 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
4950 filter->SetMesh( mesh );
4953 //================================================================================
4955 * \brief Retrieve elements of given type from SMESH_IDSource
4957 //================================================================================
4959 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
4960 const SMESHDS_Mesh* theMeshDS,
4961 TIDSortedElemSet& theElemSet,
4962 const SMDSAbs_ElementType theType,
4963 const bool emptyIfIsMesh,
4964 IDSource_Error* error)
4967 if ( error ) *error = IDSource_OK;
4969 if ( CORBA::is_nil( theIDSource ) )
4971 if ( error ) *error = IDSource_INVALID;
4974 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
4976 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
4977 *error = IDSource_EMPTY;
4980 prepareIdSource( theIDSource );
4981 SMESH::long_array_var anIDs = theIDSource->GetIDs();
4982 if ( anIDs->length() == 0 )
4984 if ( error ) *error = IDSource_EMPTY;
4987 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
4988 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
4990 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
4992 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
4996 if ( error ) *error = IDSource_INVALID;
5002 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5003 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5005 if ( error ) *error = IDSource_INVALID;
5012 //================================================================================
5014 * \brief Duplicates given elements, i.e. creates new elements based on the
5015 * same nodes as the given ones.
5016 * \param theElements - container of elements to duplicate.
5017 * \param theGroupName - a name of group to contain the generated elements.
5018 * If a group with such a name already exists, the new elements
5019 * are added to the existng group, else a new group is created.
5020 * If \a theGroupName is empty, new elements are not added
5022 * \return a group where the new elements are added. NULL if theGroupName == "".
5025 //================================================================================
5027 SMESH::SMESH_Group_ptr
5028 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5029 const char* theGroupName)
5030 throw (SALOME::SALOME_Exception)
5032 SMESH::SMESH_Group_var newGroup;
5039 TIDSortedElemSet elems;
5040 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5042 getEditor().DoubleElements( elems );
5044 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5047 SMESH::ElementType type =
5048 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5049 // find existing group
5050 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5051 for ( size_t i = 0; i < groups->length(); ++i )
5052 if ( groups[i]->GetType() == type )
5054 CORBA::String_var name = groups[i]->GetName();
5055 if ( strcmp( name, theGroupName ) == 0 ) {
5056 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5060 // create a new group
5061 if ( newGroup->_is_nil() )
5062 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5064 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5066 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5067 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5068 for ( int i = 1; i <= aSeq.Length(); i++ )
5069 groupDS->SMDSGroup().Add( aSeq(i) );
5074 if ( !newGroup->_is_nil() )
5075 pyDump << newGroup << " = ";
5076 pyDump << this << ".DoubleElements( "
5077 << theElements << ", " << "'" << theGroupName <<"')";
5079 SMESH_CATCH( SMESH::throwCorbaException );
5081 return newGroup._retn();
5084 //================================================================================
5086 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5087 \param theNodes - identifiers of nodes to be doubled
5088 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5089 nodes. If list of element identifiers is empty then nodes are doubled but
5090 they not assigned to elements
5091 \return TRUE if operation has been completed successfully, FALSE otherwise
5092 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5094 //================================================================================
5096 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5097 const SMESH::long_array& theModifiedElems )
5098 throw (SALOME::SALOME_Exception)
5103 list< int > aListOfNodes;
5105 for ( i = 0, n = theNodes.length(); i < n; i++ )
5106 aListOfNodes.push_back( theNodes[ i ] );
5108 list< int > aListOfElems;
5109 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5110 aListOfElems.push_back( theModifiedElems[ i ] );
5112 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5114 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5116 // Update Python script
5117 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5121 SMESH_CATCH( SMESH::throwCorbaException );
5125 //================================================================================
5127 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5128 This method provided for convenience works as DoubleNodes() described above.
5129 \param theNodeId - identifier of node to be doubled.
5130 \param theModifiedElems - identifiers of elements to be updated.
5131 \return TRUE if operation has been completed successfully, FALSE otherwise
5132 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5134 //================================================================================
5136 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5137 const SMESH::long_array& theModifiedElems )
5138 throw (SALOME::SALOME_Exception)
5141 SMESH::long_array_var aNodes = new SMESH::long_array;
5142 aNodes->length( 1 );
5143 aNodes[ 0 ] = theNodeId;
5145 TPythonDump pyDump; // suppress dump by the next line
5147 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5149 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5153 SMESH_CATCH( SMESH::throwCorbaException );
5157 //================================================================================
5159 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5160 This method provided for convenience works as DoubleNodes() described above.
5161 \param theNodes - group of nodes to be doubled.
5162 \param theModifiedElems - group of elements to be updated.
5163 \return TRUE if operation has been completed successfully, FALSE otherwise
5164 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5166 //================================================================================
5168 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5169 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5170 throw (SALOME::SALOME_Exception)
5173 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5176 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5177 SMESH::long_array_var aModifiedElems;
5178 if ( !CORBA::is_nil( theModifiedElems ) )
5179 aModifiedElems = theModifiedElems->GetListOfID();
5182 aModifiedElems = new SMESH::long_array;
5183 aModifiedElems->length( 0 );
5186 TPythonDump pyDump; // suppress dump by the next line
5188 bool done = DoubleNodes( aNodes, aModifiedElems );
5190 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5194 SMESH_CATCH( SMESH::throwCorbaException );
5198 //================================================================================
5200 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5201 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5202 * \param theNodes - group of nodes to be doubled.
5203 * \param theModifiedElems - group of elements to be updated.
5204 * \return a new group with newly created nodes
5205 * \sa DoubleNodeGroup()
5207 //================================================================================
5209 SMESH::SMESH_Group_ptr
5210 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5211 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5212 throw (SALOME::SALOME_Exception)
5215 SMESH::SMESH_Group_var aNewGroup;
5217 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5218 return aNewGroup._retn();
5221 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5222 SMESH::long_array_var aModifiedElems;
5223 if ( !CORBA::is_nil( theModifiedElems ) )
5224 aModifiedElems = theModifiedElems->GetListOfID();
5226 aModifiedElems = new SMESH::long_array;
5227 aModifiedElems->length( 0 );
5230 TPythonDump pyDump; // suppress dump by the next line
5232 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5235 // Create group with newly created nodes
5236 SMESH::long_array_var anIds = GetLastCreatedNodes();
5237 if (anIds->length() > 0) {
5238 string anUnindexedName (theNodes->GetName());
5239 string aNewName = generateGroupName(anUnindexedName + "_double");
5240 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5241 aNewGroup->Add(anIds);
5242 pyDump << aNewGroup << " = ";
5246 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5247 << theModifiedElems << " )";
5249 return aNewGroup._retn();
5251 SMESH_CATCH( SMESH::throwCorbaException );
5255 //================================================================================
5257 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5258 This method provided for convenience works as DoubleNodes() described above.
5259 \param theNodes - list of groups of nodes to be doubled
5260 \param theModifiedElems - list of groups of elements to be updated.
5261 \return TRUE if operation has been completed successfully, FALSE otherwise
5262 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5264 //================================================================================
5266 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5267 const SMESH::ListOfGroups& theModifiedElems )
5268 throw (SALOME::SALOME_Exception)
5273 std::list< int > aNodes;
5275 for ( i = 0, n = theNodes.length(); i < n; i++ )
5277 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5278 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5280 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5281 for ( j = 0, m = aCurr->length(); j < m; j++ )
5282 aNodes.push_back( aCurr[ j ] );
5286 std::list< int > anElems;
5287 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5289 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5290 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5292 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5293 for ( j = 0, m = aCurr->length(); j < m; j++ )
5294 anElems.push_back( aCurr[ j ] );
5298 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5300 declareMeshModified( /*isReComputeSafe=*/false );
5302 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5306 SMESH_CATCH( SMESH::throwCorbaException );
5310 //================================================================================
5312 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5313 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5314 * \param theNodes - group of nodes to be doubled.
5315 * \param theModifiedElems - group of elements to be updated.
5316 * \return a new group with newly created nodes
5317 * \sa DoubleNodeGroups()
5319 //================================================================================
5321 SMESH::SMESH_Group_ptr
5322 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5323 const SMESH::ListOfGroups& theModifiedElems )
5324 throw (SALOME::SALOME_Exception)
5326 SMESH::SMESH_Group_var aNewGroup;
5328 TPythonDump pyDump; // suppress dump by the next line
5330 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5334 // Create group with newly created nodes
5335 SMESH::long_array_var anIds = GetLastCreatedNodes();
5336 if (anIds->length() > 0) {
5337 string anUnindexedName (theNodes[0]->GetName());
5338 string aNewName = generateGroupName(anUnindexedName + "_double");
5339 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5340 aNewGroup->Add(anIds);
5341 pyDump << aNewGroup << " = ";
5345 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5346 << theModifiedElems << " )";
5348 return aNewGroup._retn();
5352 //================================================================================
5354 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5355 \param theElems - the list of elements (edges or faces) to be replicated
5356 The nodes for duplication could be found from these elements
5357 \param theNodesNot - list of nodes to NOT replicate
5358 \param theAffectedElems - the list of elements (cells and edges) to which the
5359 replicated nodes should be associated to.
5360 \return TRUE if operation has been completed successfully, FALSE otherwise
5361 \sa DoubleNodeGroup(), DoubleNodeGroups()
5363 //================================================================================
5365 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5366 const SMESH::long_array& theNodesNot,
5367 const SMESH::long_array& theAffectedElems )
5368 throw (SALOME::SALOME_Exception)
5373 SMESHDS_Mesh* aMeshDS = getMeshDS();
5374 TIDSortedElemSet anElems, aNodes, anAffected;
5375 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5376 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5377 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5379 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5381 // Update Python script
5382 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5383 << theNodesNot << ", " << theAffectedElems << " )";
5385 declareMeshModified( /*isReComputeSafe=*/false );
5388 SMESH_CATCH( SMESH::throwCorbaException );
5392 //================================================================================
5394 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5395 \param theElems - the list of elements (edges or faces) to be replicated
5396 The nodes for duplication could be found from these elements
5397 \param theNodesNot - list of nodes to NOT replicate
5398 \param theShape - shape to detect affected elements (element which geometric center
5399 located on or inside shape).
5400 The replicated nodes should be associated to affected elements.
5401 \return TRUE if operation has been completed successfully, FALSE otherwise
5402 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5404 //================================================================================
5406 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5407 const SMESH::long_array& theNodesNot,
5408 GEOM::GEOM_Object_ptr theShape )
5409 throw (SALOME::SALOME_Exception)
5415 SMESHDS_Mesh* aMeshDS = getMeshDS();
5416 TIDSortedElemSet anElems, aNodes;
5417 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5418 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5420 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5421 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5423 // Update Python script
5424 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5425 << theNodesNot << ", " << theShape << " )";
5427 declareMeshModified( /*isReComputeSafe=*/false );
5430 SMESH_CATCH( SMESH::throwCorbaException );
5434 //================================================================================
5436 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5437 \param theElems - group of of elements (edges or faces) to be replicated
5438 \param theNodesNot - group of nodes not to replicated
5439 \param theAffectedElems - group of elements to which the replicated nodes
5440 should be associated to.
5441 \return TRUE if operation has been completed successfully, FALSE otherwise
5442 \sa DoubleNodes(), DoubleNodeGroups()
5444 //================================================================================
5447 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5448 SMESH::SMESH_GroupBase_ptr theNodesNot,
5449 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5450 throw (SALOME::SALOME_Exception)
5453 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5459 SMESHDS_Mesh* aMeshDS = getMeshDS();
5460 TIDSortedElemSet anElems, aNodes, anAffected;
5461 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5462 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5463 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5465 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5467 // Update Python script
5468 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5469 << theNodesNot << ", " << theAffectedElems << " )";
5471 declareMeshModified( /*isReComputeSafe=*/false );
5474 SMESH_CATCH( SMESH::throwCorbaException );
5478 //================================================================================
5480 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5481 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5482 * \param theElems - group of of elements (edges or faces) to be replicated
5483 * \param theNodesNot - group of nodes not to replicated
5484 * \param theAffectedElems - group of elements to which the replicated nodes
5485 * should be associated to.
5486 * \return a new group with newly created elements
5487 * \sa DoubleNodeElemGroup()
5489 //================================================================================
5491 SMESH::SMESH_Group_ptr
5492 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5493 SMESH::SMESH_GroupBase_ptr theNodesNot,
5494 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5495 throw (SALOME::SALOME_Exception)
5498 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5502 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5503 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5505 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5507 << theNodesNot << ", "
5508 << theAffectedElems << " )";
5510 return elemGroup._retn();
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::ListOfGroups*
5527 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5528 SMESH::SMESH_GroupBase_ptr theNodesNot,
5529 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5530 CORBA::Boolean theElemGroupNeeded,
5531 CORBA::Boolean theNodeGroupNeeded)
5532 throw (SALOME::SALOME_Exception)
5535 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5536 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5537 aTwoGroups->length( 2 );
5539 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5540 return aTwoGroups._retn();
5545 SMESHDS_Mesh* aMeshDS = getMeshDS();
5546 TIDSortedElemSet anElems, aNodes, anAffected;
5547 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5548 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5549 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5552 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5554 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5560 // Create group with newly created elements
5561 CORBA::String_var elemGroupName = theElems->GetName();
5562 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5563 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5565 SMESH::long_array_var anIds = GetLastCreatedElems();
5566 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5567 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5568 aNewElemGroup->Add(anIds);
5570 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5572 SMESH::long_array_var anIds = GetLastCreatedNodes();
5573 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5574 aNewNodeGroup->Add(anIds);
5578 // Update Python script
5581 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5582 else pyDump << aNewElemGroup << ", ";
5583 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5584 else pyDump << aNewNodeGroup << " ] = ";
5586 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5587 << theNodesNot << ", "
5588 << theAffectedElems << ", "
5589 << theElemGroupNeeded << ", "
5590 << theNodeGroupNeeded <<" )";
5592 aTwoGroups[0] = aNewElemGroup._retn();
5593 aTwoGroups[1] = aNewNodeGroup._retn();
5594 return aTwoGroups._retn();
5596 SMESH_CATCH( SMESH::throwCorbaException );
5600 //================================================================================
5602 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5603 \param theElems - group of of elements (edges or faces) to be replicated
5604 \param theNodesNot - group of nodes not to replicated
5605 \param theShape - shape to detect affected elements (element which geometric center
5606 located on or inside shape).
5607 The replicated nodes should be associated to affected elements.
5608 \return TRUE if operation has been completed successfully, FALSE otherwise
5609 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5611 //================================================================================
5614 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5615 SMESH::SMESH_GroupBase_ptr theNodesNot,
5616 GEOM::GEOM_Object_ptr theShape )
5617 throw (SALOME::SALOME_Exception)
5620 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5626 SMESHDS_Mesh* aMeshDS = getMeshDS();
5627 TIDSortedElemSet anElems, aNodes, anAffected;
5628 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5629 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5631 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5632 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5635 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5637 // Update Python script
5638 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5639 << theNodesNot << ", " << theShape << " )";
5642 SMESH_CATCH( SMESH::throwCorbaException );
5646 //================================================================================
5648 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5649 * \param [in] theGrpList - groups
5650 * \param [in] theMeshDS - mesh
5651 * \param [out] theElemSet - set of elements
5652 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5654 //================================================================================
5656 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5657 SMESHDS_Mesh* theMeshDS,
5658 TIDSortedElemSet& theElemSet,
5659 const bool theIsNodeGrp)
5661 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5663 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5664 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5665 : aGrp->GetType() != SMESH::NODE ) )
5667 SMESH::long_array_var anIDs = aGrp->GetIDs();
5668 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5673 //================================================================================
5675 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5676 This method provided for convenience works as DoubleNodes() described above.
5677 \param theElems - list of groups of elements (edges or faces) to be replicated
5678 \param theNodesNot - list of groups of nodes not to replicated
5679 \param theAffectedElems - group of elements to which the replicated nodes
5680 should be associated to.
5681 \return TRUE if operation has been completed successfully, FALSE otherwise
5682 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5684 //================================================================================
5687 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5688 const SMESH::ListOfGroups& theNodesNot,
5689 const SMESH::ListOfGroups& theAffectedElems)
5690 throw (SALOME::SALOME_Exception)
5696 SMESHDS_Mesh* aMeshDS = getMeshDS();
5697 TIDSortedElemSet anElems, aNodes, anAffected;
5698 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5699 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5700 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5702 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5704 // Update Python script
5705 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5706 << &theNodesNot << ", " << &theAffectedElems << " )";
5708 declareMeshModified( /*isReComputeSafe=*/false );
5711 SMESH_CATCH( SMESH::throwCorbaException );
5715 //================================================================================
5717 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5718 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5719 \param theElems - list of groups of elements (edges or faces) to be replicated
5720 \param theNodesNot - list of groups of nodes not to replicated
5721 \param theAffectedElems - group of elements to which the replicated nodes
5722 should be associated to.
5723 * \return a new group with newly created elements
5724 * \sa DoubleNodeElemGroups()
5726 //================================================================================
5728 SMESH::SMESH_Group_ptr
5729 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5730 const SMESH::ListOfGroups& theNodesNot,
5731 const SMESH::ListOfGroups& theAffectedElems)
5732 throw (SALOME::SALOME_Exception)
5735 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
5739 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5740 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5742 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
5744 << theNodesNot << ", "
5745 << theAffectedElems << " )";
5747 return elemGroup._retn();
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::ListOfGroups*
5764 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
5765 const SMESH::ListOfGroups& theNodesNot,
5766 const SMESH::ListOfGroups& theAffectedElems,
5767 CORBA::Boolean theElemGroupNeeded,
5768 CORBA::Boolean theNodeGroupNeeded)
5769 throw (SALOME::SALOME_Exception)
5772 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5773 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5774 aTwoGroups->length( 2 );
5779 SMESHDS_Mesh* aMeshDS = getMeshDS();
5780 TIDSortedElemSet anElems, aNodes, anAffected;
5781 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5782 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5783 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5785 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5787 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5792 // Create group with newly created elements
5793 CORBA::String_var elemGroupName = theElems[0]->GetName();
5794 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5795 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5797 SMESH::long_array_var anIds = GetLastCreatedElems();
5798 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5799 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5800 aNewElemGroup->Add(anIds);
5802 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5804 SMESH::long_array_var anIds = GetLastCreatedNodes();
5805 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5806 aNewNodeGroup->Add(anIds);
5810 // Update Python script
5813 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5814 else pyDump << aNewElemGroup << ", ";
5815 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5816 else pyDump << aNewNodeGroup << " ] = ";
5818 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
5819 << &theNodesNot << ", "
5820 << &theAffectedElems << ", "
5821 << theElemGroupNeeded << ", "
5822 << theNodeGroupNeeded << " )";
5824 aTwoGroups[0] = aNewElemGroup._retn();
5825 aTwoGroups[1] = aNewNodeGroup._retn();
5826 return aTwoGroups._retn();
5828 SMESH_CATCH( SMESH::throwCorbaException );
5832 //================================================================================
5834 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5835 This method provided for convenience works as DoubleNodes() described above.
5836 \param theElems - list of groups of elements (edges or faces) to be replicated
5837 \param theNodesNot - list of groups of nodes not to replicated
5838 \param theShape - shape to detect affected elements (element which geometric center
5839 located on or inside shape).
5840 The replicated nodes should be associated to affected elements.
5841 \return TRUE if operation has been completed successfully, FALSE otherwise
5842 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5844 //================================================================================
5847 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5848 const SMESH::ListOfGroups& theNodesNot,
5849 GEOM::GEOM_Object_ptr theShape )
5850 throw (SALOME::SALOME_Exception)
5856 SMESHDS_Mesh* aMeshDS = getMeshDS();
5857 TIDSortedElemSet anElems, aNodes;
5858 listOfGroupToSet(theElems, aMeshDS, anElems,false );
5859 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5861 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5862 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5864 // Update Python script
5865 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5866 << &theNodesNot << ", " << theShape << " )";
5868 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5871 SMESH_CATCH( SMESH::throwCorbaException );
5875 //================================================================================
5877 \brief Identify the elements that will be affected by node duplication (actual
5878 duplication is not performed.
5879 This method is the first step of DoubleNodeElemGroupsInRegion.
5880 \param theElems - list of groups of elements (edges or faces) to be replicated
5881 \param theNodesNot - list of groups of nodes not to replicated
5882 \param theShape - shape to detect affected elements (element which geometric center
5883 located on or inside shape).
5884 The replicated nodes should be associated to affected elements.
5885 \return groups of affected elements
5886 \sa DoubleNodeElemGroupsInRegion()
5888 //================================================================================
5889 SMESH::ListOfGroups*
5890 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
5891 const SMESH::ListOfGroups& theNodesNot,
5892 GEOM::GEOM_Object_ptr theShape )
5893 throw (SALOME::SALOME_Exception)
5896 MESSAGE("AffectedElemGroupsInRegion");
5897 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
5898 bool isEdgeGroup = false;
5899 bool isFaceGroup = false;
5900 bool isVolumeGroup = false;
5901 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
5902 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
5903 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
5907 ::SMESH_MeshEditor aMeshEditor(myMesh);
5909 SMESHDS_Mesh* aMeshDS = getMeshDS();
5910 TIDSortedElemSet anElems, aNodes;
5911 listOfGroupToSet(theElems, aMeshDS, anElems, false);
5912 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
5914 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
5915 TIDSortedElemSet anAffected;
5916 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
5919 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5924 int lg = anAffected.size();
5925 MESSAGE("lg="<< lg);
5926 SMESH::long_array_var volumeIds = new SMESH::long_array;
5927 volumeIds->length(lg);
5928 SMESH::long_array_var faceIds = new SMESH::long_array;
5929 faceIds->length(lg);
5930 SMESH::long_array_var edgeIds = new SMESH::long_array;
5931 edgeIds->length(lg);
5936 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
5937 for (; eIt != anAffected.end(); ++eIt)
5939 const SMDS_MeshElement* anElem = *eIt;
5942 int elemId = anElem->GetID();
5943 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
5944 volumeIds[ivol++] = elemId;
5945 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
5946 faceIds[iface++] = elemId;
5947 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
5948 edgeIds[iedge++] = elemId;
5950 volumeIds->length(ivol);
5951 faceIds->length(iface);
5952 edgeIds->length(iedge);
5954 aNewVolumeGroup->Add(volumeIds);
5955 aNewFaceGroup->Add(faceIds);
5956 aNewEdgeGroup->Add(edgeIds);
5957 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
5958 isFaceGroup = (aNewFaceGroup->Size() > 0);
5959 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
5963 if (isEdgeGroup) nbGroups++;
5964 if (isFaceGroup) nbGroups++;
5965 if (isVolumeGroup) nbGroups++;
5966 aListOfGroups->length(nbGroups);
5969 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
5970 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
5971 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
5973 // Update Python script
5976 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
5977 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
5978 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
5980 pyDump << this << ".AffectedElemGroupsInRegion( "
5981 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
5983 return aListOfGroups._retn();
5985 SMESH_CATCH( SMESH::throwCorbaException );
5989 //================================================================================
5991 \brief Generated skin mesh (containing 2D cells) from 3D mesh
5992 The created 2D mesh elements based on nodes of free faces of boundary volumes
5993 \return TRUE if operation has been completed successfully, FALSE otherwise
5995 //================================================================================
5997 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
5998 throw (SALOME::SALOME_Exception)
6003 bool aResult = getEditor().Make2DMeshFrom3D();
6005 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6007 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6010 SMESH_CATCH( SMESH::throwCorbaException );
6014 //================================================================================
6016 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6017 * The list of groups must contain at least two groups. The groups have to be disjoint:
6018 * no common element into two different groups.
6019 * The nodes of the internal faces at the boundaries of the groups are doubled.
6020 * Optionally, the internal faces are replaced by flat elements.
6021 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6022 * The flat elements are stored in groups of volumes.
6023 * These groups are named according to the position of the group in the list:
6024 * 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.
6025 * 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.
6026 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6027 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6028 * \param theDomains - list of groups of volumes
6029 * \param createJointElems - if TRUE, create the elements
6030 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6031 * the boundary between \a theDomains and the rest mesh
6032 * \return TRUE if operation has been completed successfully, FALSE otherwise
6034 //================================================================================
6037 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6038 CORBA::Boolean createJointElems,
6039 CORBA::Boolean onAllBoundaries )
6040 throw (SALOME::SALOME_Exception)
6047 SMESHDS_Mesh* aMeshDS = getMeshDS();
6049 // MESSAGE("theDomains.length = "<<theDomains.length());
6050 if ( theDomains.length() <= 1 && !onAllBoundaries )
6051 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6053 vector<TIDSortedElemSet> domains;
6054 domains.resize( theDomains.length() );
6056 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6058 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6059 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6061 // if ( aGrp->GetType() != SMESH::VOLUME )
6062 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6063 SMESH::long_array_var anIDs = aGrp->GetIDs();
6064 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6068 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6069 // TODO publish the groups of flat elements in study
6071 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6073 // Update Python script
6074 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6075 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6077 SMESH_CATCH( SMESH::throwCorbaException );
6079 myMesh_i->CreateGroupServants(); // publish created groups if any
6084 //================================================================================
6086 * \brief Double nodes on some external faces and create flat elements.
6087 * Flat elements are mainly used by some types of mechanic calculations.
6089 * Each group of the list must be constituted of faces.
6090 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6091 * @param theGroupsOfFaces - list of groups of faces
6092 * @return TRUE if operation has been completed successfully, FALSE otherwise
6094 //================================================================================
6097 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6098 throw (SALOME::SALOME_Exception)
6103 SMESHDS_Mesh* aMeshDS = getMeshDS();
6105 vector<TIDSortedElemSet> faceGroups;
6108 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6110 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6111 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6113 TIDSortedElemSet faceGroup;
6115 faceGroups.push_back(faceGroup);
6116 SMESH::long_array_var anIDs = aGrp->GetIDs();
6117 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6121 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6122 // TODO publish the groups of flat elements in study
6124 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6126 // Update Python script
6127 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6130 SMESH_CATCH( SMESH::throwCorbaException );
6134 //================================================================================
6136 * \brief Identify all the elements around a geom shape, get the faces delimiting
6139 * Build groups of volume to remove, groups of faces to replace on the skin of the
6140 * object, groups of faces to remove inside the object, (idem edges).
6141 * Build ordered list of nodes at the border of each group of faces to replace
6142 * (to be used to build a geom subshape).
6144 //================================================================================
6146 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6147 GEOM::GEOM_Object_ptr theShape,
6148 const char* groupName,
6149 const SMESH::double_array& theNodesCoords,
6150 SMESH::array_of_long_array_out GroupsOfNodes)
6151 throw (SALOME::SALOME_Exception)
6156 std::vector<std::vector<int> > aListOfListOfNodes;
6157 ::SMESH_MeshEditor aMeshEditor( myMesh );
6159 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6160 if ( !theNodeSearcher )
6161 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6163 vector<double> nodesCoords;
6164 for (int i = 0; i < theNodesCoords.length(); i++)
6166 nodesCoords.push_back( theNodesCoords[i] );
6169 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6170 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6171 nodesCoords, aListOfListOfNodes);
6173 GroupsOfNodes = new SMESH::array_of_long_array;
6174 GroupsOfNodes->length( aListOfListOfNodes.size() );
6175 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6176 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6178 vector<int>& aListOfNodes = *llIt;
6179 vector<int>::iterator lIt = aListOfNodes.begin();;
6180 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6181 aGroup.length( aListOfNodes.size() );
6182 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6183 aGroup[ j ] = (*lIt);
6185 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6188 << ", '" << groupName << "', "
6189 << theNodesCoords << " )";
6191 SMESH_CATCH( SMESH::throwCorbaException );
6194 // issue 20749 ===================================================================
6196 * \brief Creates missing boundary elements
6197 * \param elements - elements whose boundary is to be checked
6198 * \param dimension - defines type of boundary elements to create
6199 * \param groupName - a name of group to store created boundary elements in,
6200 * "" means not to create the group
6201 * \param meshName - a name of new mesh to store created boundary elements in,
6202 * "" means not to create the new mesh
6203 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6204 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6205 * boundary elements will be copied into the new mesh
6206 * \param group - returns the create group, if any
6207 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6209 // ================================================================================
6211 SMESH::SMESH_Mesh_ptr
6212 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6213 SMESH::Bnd_Dimension dim,
6214 const char* groupName,
6215 const char* meshName,
6216 CORBA::Boolean toCopyElements,
6217 CORBA::Boolean toCopyExistingBondary,
6218 SMESH::SMESH_Group_out group)
6219 throw (SALOME::SALOME_Exception)
6224 if ( dim > SMESH::BND_1DFROM2D )
6225 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6227 SMESHDS_Mesh* aMeshDS = getMeshDS();
6229 SMESH::SMESH_Mesh_var mesh_var;
6230 SMESH::SMESH_Group_var group_var;
6234 TIDSortedElemSet elements;
6235 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6236 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6240 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6241 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6243 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6245 // group of new boundary elements
6246 SMESH_Group* smesh_group = 0;
6247 if ( strlen(groupName) )
6249 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6250 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6251 smesh_group = group_i->GetSmeshGroup();
6255 getEditor().MakeBoundaryMesh( elements,
6256 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6260 toCopyExistingBondary);
6263 smesh_mesh->GetMeshDS()->Modified();
6266 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6268 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6269 if ( mesh_var->_is_nil() )
6270 pyDump << myMesh_i->_this() << ", ";
6272 pyDump << mesh_var << ", ";
6273 if ( group_var->_is_nil() )
6274 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6276 pyDump << group_var << " = ";
6277 pyDump << this << ".MakeBoundaryMesh( "
6279 << "SMESH." << dimName[int(dim)] << ", "
6280 << "'" << groupName << "', "
6281 << "'" << meshName<< "', "
6282 << toCopyElements << ", "
6283 << toCopyExistingBondary << ")";
6285 group = group_var._retn();
6286 return mesh_var._retn();
6288 SMESH_CATCH( SMESH::throwCorbaException );
6289 return SMESH::SMESH_Mesh::_nil();
6292 //================================================================================
6294 * \brief Creates missing boundary elements
6295 * \param dimension - defines type of boundary elements to create
6296 * \param groupName - a name of group to store all boundary elements in,
6297 * "" means not to create the group
6298 * \param meshName - a name of a new mesh, which is a copy of the initial
6299 * mesh + created boundary elements; "" means not to create the new mesh
6300 * \param toCopyAll - if true, the whole initial mesh will be copied into
6301 * the new mesh else only boundary elements will be copied into the new mesh
6302 * \param groups - optional groups of elements to make boundary around
6303 * \param mesh - returns the mesh where elements were added to
6304 * \param group - returns the created group, if any
6305 * \retval long - number of added boundary elements
6307 //================================================================================
6309 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6310 const char* groupName,
6311 const char* meshName,
6312 CORBA::Boolean toCopyAll,
6313 const SMESH::ListOfIDSources& groups,
6314 SMESH::SMESH_Mesh_out mesh,
6315 SMESH::SMESH_Group_out group)
6316 throw (SALOME::SALOME_Exception)
6321 if ( dim > SMESH::BND_1DFROM2D )
6322 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6324 // separate groups belonging to this and other mesh
6325 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6326 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6327 groupsOfThisMesh->length( groups.length() );
6328 groupsOfOtherMesh->length( groups.length() );
6329 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6330 for ( int i = 0; i < groups.length(); ++i )
6332 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6333 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6334 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6336 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6337 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6338 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6340 groupsOfThisMesh->length( nbGroups );
6341 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6346 if ( nbGroupsOfOtherMesh > 0 )
6348 // process groups belonging to another mesh
6349 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6350 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6351 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6352 groupsOfOtherMesh, mesh, group );
6355 SMESH::SMESH_Mesh_var mesh_var;
6356 SMESH::SMESH_Group_var group_var;
6359 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6360 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6364 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6366 /*toCopyGroups=*/false,
6367 /*toKeepIDs=*/true);
6369 mesh_var = makeMesh(meshName);
6371 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6372 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6375 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6376 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6378 // group of boundary elements
6379 SMESH_Group* smesh_group = 0;
6380 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6381 if ( strlen(groupName) )
6383 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6384 group_var = mesh_i->CreateGroup( groupType, groupName );
6385 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6386 smesh_group = group_i->GetSmeshGroup();
6389 TIDSortedElemSet elements;
6391 if ( groups.length() > 0 )
6393 for ( int i = 0; i < nbGroups; ++i )
6396 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6398 SMESH::Bnd_Dimension bdim =
6399 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6400 nbAdded += getEditor().MakeBoundaryMesh( elements,
6401 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6404 /*toCopyElements=*/false,
6405 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6406 /*toAddExistingBondary=*/true,
6407 /*aroundElements=*/true);
6413 nbAdded += getEditor().MakeBoundaryMesh( elements,
6414 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6417 /*toCopyElements=*/false,
6418 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6419 /*toAddExistingBondary=*/true);
6421 tgtMesh->GetMeshDS()->Modified();
6423 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6425 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6426 pyDump << "nbAdded, ";
6427 if ( mesh_var->_is_nil() )
6428 pyDump << myMesh_i->_this() << ", ";
6430 pyDump << mesh_var << ", ";
6431 if ( group_var->_is_nil() )
6432 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6434 pyDump << group_var << " = ";
6435 pyDump << this << ".MakeBoundaryElements( "
6436 << "SMESH." << dimName[int(dim)] << ", "
6437 << "'" << groupName << "', "
6438 << "'" << meshName<< "', "
6439 << toCopyAll << ", "
6442 mesh = mesh_var._retn();
6443 group = group_var._retn();
6446 SMESH_CATCH( SMESH::throwCorbaException );