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 << ", " << makeGroups
2615 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2617 return aGroups ? aGroups : new SMESH::ListOfGroups;
2619 SMESH_CATCH( SMESH::throwCorbaException );
2623 //=======================================================================
2624 //function : AdvancedExtrusion
2626 //=======================================================================
2628 SMESH::ListOfGroups*
2629 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2630 const SMESH::DirStruct & theStepVector,
2631 CORBA::Long theNbOfSteps,
2632 CORBA::Long theExtrFlags,
2633 CORBA::Double theSewTolerance,
2634 CORBA::Boolean theMakeGroups)
2635 throw (SALOME::SALOME_Exception)
2640 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2642 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2643 theExtrFlags, theSewTolerance );
2645 TIDSortedElemSet elemsNodes[2];
2646 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2648 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2649 ::SMESH_MeshEditor::PGroupIDs groupIds =
2650 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2652 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2654 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2656 if ( !myIsPreviewMode ) {
2657 dumpGroupsList(aPythonDump, aGroups);
2658 aPythonDump << this << ".AdvancedExtrusion( "
2659 << theIDsOfElements << ", "
2660 << theStepVector << ", "
2661 << theNbOfSteps << ", "
2662 << theExtrFlags << ", "
2663 << theSewTolerance << ", "
2664 << theMakeGroups << " )";
2667 return aGroups ? aGroups : new SMESH::ListOfGroups;
2669 SMESH_CATCH( SMESH::throwCorbaException );
2673 //================================================================================
2675 * \brief Convert extrusion error to IDL enum
2677 //================================================================================
2681 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2683 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2687 RETCASE( EXTR_NO_ELEMENTS );
2688 RETCASE( EXTR_PATH_NOT_EDGE );
2689 RETCASE( EXTR_BAD_PATH_SHAPE );
2690 RETCASE( EXTR_BAD_STARTING_NODE );
2691 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2692 RETCASE( EXTR_CANT_GET_TANGENT );
2694 return SMESH::SMESH_MeshEditor::EXTR_OK;
2698 //=======================================================================
2699 //function : extrusionAlongPath
2701 //=======================================================================
2702 SMESH::ListOfGroups*
2703 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2704 const SMESH::ListOfIDSources & theEdges,
2705 const SMESH::ListOfIDSources & theFaces,
2706 SMESH::SMESH_IDSource_ptr thePathMesh,
2707 GEOM::GEOM_Object_ptr thePathShape,
2708 CORBA::Long theNodeStart,
2709 CORBA::Boolean theHasAngles,
2710 const SMESH::double_array & theAngles,
2711 CORBA::Boolean theLinearVariation,
2712 CORBA::Boolean theHasRefPoint,
2713 const SMESH::PointStruct & theRefPoint,
2715 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2716 throw (SALOME::SALOME_Exception)
2721 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2723 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2724 if ( thePathMesh->_is_nil() )
2725 return aGroups._retn();
2728 SMESH_subMesh* aSubMesh = 0;
2729 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2730 if ( thePathShape->_is_nil() )
2732 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2733 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2735 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2736 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2737 if ( !aMeshImp ) return aGroups._retn();
2738 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2739 if ( !aSubMesh ) return aGroups._retn();
2741 else if ( !aMeshImp ||
2742 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2744 return aGroups._retn();
2749 if ( !aMeshImp ) return aGroups._retn();
2750 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2751 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2752 if ( !aSubMesh || !aSubMesh->GetSubMeshDS() )
2753 return aGroups._retn();
2756 SMDS_MeshNode* nodeStart =
2757 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2759 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2760 return aGroups._retn();
2763 TIDSortedElemSet elemsNodes[2];
2764 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2765 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2766 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2768 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2769 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2770 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2771 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2773 list<double> angles;
2774 for (int i = 0; i < theAngles.length(); i++) {
2775 angles.push_back( theAngles[i] );
2778 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2780 int nbOldGroups = myMesh->NbGroup();
2782 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2783 if ( myIsPreviewMode )
2785 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2786 TPreviewMesh * tmpMesh = getPreviewMesh();
2787 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2788 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2789 workElements = & copyElements[0];
2790 theMakeGroups = false;
2793 ::SMESH_MeshEditor::Extrusion_Error error;
2795 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2796 theHasAngles, angles, theLinearVariation,
2797 theHasRefPoint, refPnt, theMakeGroups );
2799 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2800 theHasAngles, angles, theLinearVariation,
2801 theHasRefPoint, refPnt, theMakeGroups );
2803 declareMeshModified( /*isReComputeSafe=*/true );
2804 theError = convExtrError( error );
2806 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2807 if ( theMakeGroups ) {
2808 list<int> groupIDs = myMesh->GetGroupIds();
2809 list<int>::iterator newBegin = groupIDs.begin();
2810 std::advance( newBegin, nbOldGroups ); // skip old groups
2811 groupIDs.erase( groupIDs.begin(), newBegin );
2812 aGroups = getGroups( & groupIDs );
2813 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2816 if ( !myIsPreviewMode ) {
2817 aPythonDump << "(" << aGroups << ", error) = "
2818 << this << ".ExtrusionAlongPathObjects( "
2822 << thePathMesh << ", "
2823 << thePathShape << ", "
2824 << theNodeStart << ", "
2825 << theHasAngles << ", "
2826 << theAngles << ", "
2827 << theLinearVariation << ", "
2828 << theHasRefPoint << ", "
2829 << "SMESH.PointStruct( "
2830 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2831 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2832 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2833 << theMakeGroups << " )";
2836 return aGroups._retn();
2838 SMESH_CATCH( SMESH::throwCorbaException );
2842 //================================================================================
2844 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2845 * of given angles along path steps
2846 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2847 * which proceeds the extrusion
2848 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2849 * is used to define the sub-mesh for the path
2851 //================================================================================
2853 SMESH::double_array*
2854 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2855 GEOM::GEOM_Object_ptr thePathShape,
2856 const SMESH::double_array & theAngles)
2858 SMESH::double_array_var aResult = new SMESH::double_array();
2859 int nbAngles = theAngles.length();
2860 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2862 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2863 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2864 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2865 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2866 return aResult._retn();
2867 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2868 if ( nbSteps == nbAngles )
2870 aResult.inout() = theAngles;
2874 aResult->length( nbSteps );
2875 double rAn2St = double( nbAngles ) / double( nbSteps );
2876 double angPrev = 0, angle;
2877 for ( int iSt = 0; iSt < nbSteps; ++iSt )
2879 double angCur = rAn2St * ( iSt+1 );
2880 double angCurFloor = floor( angCur );
2881 double angPrevFloor = floor( angPrev );
2882 if ( angPrevFloor == angCurFloor )
2883 angle = rAn2St * theAngles[ int( angCurFloor ) ];
2886 int iP = int( angPrevFloor );
2887 double angPrevCeil = ceil(angPrev);
2888 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2890 int iC = int( angCurFloor );
2891 if ( iC < nbAngles )
2892 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2894 iP = int( angPrevCeil );
2896 angle += theAngles[ iC ];
2898 aResult[ iSt ] = angle;
2903 // Update Python script
2904 TPythonDump() << "rotAngles = " << theAngles;
2905 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
2906 << thePathMesh << ", "
2907 << thePathShape << ", "
2910 return aResult._retn();
2913 //=======================================================================
2916 //=======================================================================
2918 SMESH::ListOfGroups*
2919 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
2920 const SMESH::AxisStruct & theAxis,
2921 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2922 CORBA::Boolean theCopy,
2924 ::SMESH_Mesh* theTargetMesh)
2925 throw (SALOME::SALOME_Exception)
2930 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2931 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2933 if ( theTargetMesh )
2937 switch ( theMirrorType ) {
2938 case SMESH::SMESH_MeshEditor::POINT:
2939 aTrsf.SetMirror( P );
2941 case SMESH::SMESH_MeshEditor::AXIS:
2942 aTrsf.SetMirror( gp_Ax1( P, V ));
2945 aTrsf.SetMirror( gp_Ax2( P, V ));
2948 TIDSortedElemSet copyElements;
2949 TIDSortedElemSet* workElements = & theElements;
2951 if ( myIsPreviewMode )
2953 TPreviewMesh * tmpMesh = getPreviewMesh();
2954 tmpMesh->Copy( theElements, copyElements);
2955 if ( !theCopy && !theTargetMesh )
2957 TIDSortedElemSet elemsAround, elemsAroundCopy;
2958 getElementsAround( theElements, getMeshDS(), elemsAround );
2959 tmpMesh->Copy( elemsAround, elemsAroundCopy);
2961 workElements = & copyElements;
2962 theMakeGroups = false;
2965 ::SMESH_MeshEditor::PGroupIDs groupIds =
2966 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2968 if ( theCopy && !myIsPreviewMode)
2970 if ( theTargetMesh )
2972 theTargetMesh->GetMeshDS()->Modified();
2976 declareMeshModified( /*isReComputeSafe=*/false );
2979 return theMakeGroups ? getGroups(groupIds.get()) : 0;
2981 SMESH_CATCH( SMESH::throwCorbaException );
2985 //=======================================================================
2988 //=======================================================================
2990 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
2991 const SMESH::AxisStruct & theAxis,
2992 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2993 CORBA::Boolean theCopy)
2994 throw (SALOME::SALOME_Exception)
2996 if ( !myIsPreviewMode ) {
2997 TPythonDump() << this << ".Mirror( "
2998 << theIDsOfElements << ", "
3000 << mirrorTypeName(theMirrorType) << ", "
3003 if ( theIDsOfElements.length() > 0 )
3005 TIDSortedElemSet elements;
3006 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3007 mirror(elements, theAxis, theMirrorType, theCopy, false);
3012 //=======================================================================
3013 //function : MirrorObject
3015 //=======================================================================
3017 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3018 const SMESH::AxisStruct & theAxis,
3019 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3020 CORBA::Boolean theCopy)
3021 throw (SALOME::SALOME_Exception)
3023 if ( !myIsPreviewMode ) {
3024 TPythonDump() << this << ".MirrorObject( "
3025 << theObject << ", "
3027 << mirrorTypeName(theMirrorType) << ", "
3030 TIDSortedElemSet elements;
3032 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3034 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3035 mirror(elements, theAxis, theMirrorType, theCopy, false);
3038 //=======================================================================
3039 //function : MirrorMakeGroups
3041 //=======================================================================
3043 SMESH::ListOfGroups*
3044 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3045 const SMESH::AxisStruct& theMirror,
3046 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3047 throw (SALOME::SALOME_Exception)
3049 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3051 SMESH::ListOfGroups * aGroups = 0;
3052 if ( theIDsOfElements.length() > 0 )
3054 TIDSortedElemSet elements;
3055 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3056 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3058 if (!myIsPreviewMode) {
3059 dumpGroupsList(aPythonDump, aGroups);
3060 aPythonDump << this << ".MirrorMakeGroups( "
3061 << theIDsOfElements << ", "
3062 << theMirror << ", "
3063 << mirrorTypeName(theMirrorType) << " )";
3068 //=======================================================================
3069 //function : MirrorObjectMakeGroups
3071 //=======================================================================
3073 SMESH::ListOfGroups*
3074 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3075 const SMESH::AxisStruct& theMirror,
3076 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3077 throw (SALOME::SALOME_Exception)
3079 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3081 SMESH::ListOfGroups * aGroups = 0;
3082 TIDSortedElemSet elements;
3083 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3084 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3086 if (!myIsPreviewMode)
3088 dumpGroupsList(aPythonDump,aGroups);
3089 aPythonDump << this << ".MirrorObjectMakeGroups( "
3090 << theObject << ", "
3091 << theMirror << ", "
3092 << mirrorTypeName(theMirrorType) << " )";
3097 //=======================================================================
3098 //function : MirrorMakeMesh
3100 //=======================================================================
3102 SMESH::SMESH_Mesh_ptr
3103 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3104 const SMESH::AxisStruct& theMirror,
3105 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3106 CORBA::Boolean theCopyGroups,
3107 const char* theMeshName)
3108 throw (SALOME::SALOME_Exception)
3110 SMESH_Mesh_i* mesh_i;
3111 SMESH::SMESH_Mesh_var mesh;
3112 { // open new scope to dump "MakeMesh" command
3113 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3115 TPythonDump pydump; // to prevent dump at mesh creation
3117 mesh = makeMesh( theMeshName );
3118 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3119 if (mesh_i && theIDsOfElements.length() > 0 )
3121 TIDSortedElemSet elements;
3122 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3123 mirror(elements, theMirror, theMirrorType,
3124 false, theCopyGroups, & mesh_i->GetImpl());
3125 mesh_i->CreateGroupServants();
3128 if (!myIsPreviewMode) {
3129 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3130 << theIDsOfElements << ", "
3131 << theMirror << ", "
3132 << mirrorTypeName(theMirrorType) << ", "
3133 << theCopyGroups << ", '"
3134 << theMeshName << "' )";
3139 if (!myIsPreviewMode && mesh_i)
3140 mesh_i->GetGroups();
3142 return mesh._retn();
3145 //=======================================================================
3146 //function : MirrorObjectMakeMesh
3148 //=======================================================================
3150 SMESH::SMESH_Mesh_ptr
3151 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3152 const SMESH::AxisStruct& theMirror,
3153 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3154 CORBA::Boolean theCopyGroups,
3155 const char* theMeshName)
3156 throw (SALOME::SALOME_Exception)
3158 SMESH_Mesh_i* mesh_i;
3159 SMESH::SMESH_Mesh_var mesh;
3160 { // open new scope to dump "MakeMesh" command
3161 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3163 TPythonDump pydump; // to prevent dump at mesh creation
3165 mesh = makeMesh( theMeshName );
3166 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3167 TIDSortedElemSet elements;
3169 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3171 mirror(elements, theMirror, theMirrorType,
3172 false, theCopyGroups, & mesh_i->GetImpl());
3173 mesh_i->CreateGroupServants();
3175 if (!myIsPreviewMode) {
3176 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3177 << theObject << ", "
3178 << theMirror << ", "
3179 << mirrorTypeName(theMirrorType) << ", "
3180 << theCopyGroups << ", '"
3181 << theMeshName << "' )";
3186 if (!myIsPreviewMode && mesh_i)
3187 mesh_i->GetGroups();
3189 return mesh._retn();
3192 //=======================================================================
3193 //function : translate
3195 //=======================================================================
3197 SMESH::ListOfGroups*
3198 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3199 const SMESH::DirStruct & theVector,
3200 CORBA::Boolean theCopy,
3202 ::SMESH_Mesh* theTargetMesh)
3203 throw (SALOME::SALOME_Exception)
3208 if ( theTargetMesh )
3212 const SMESH::PointStruct * P = &theVector.PS;
3213 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3215 TIDSortedElemSet copyElements;
3216 TIDSortedElemSet* workElements = &theElements;
3218 if ( myIsPreviewMode )
3220 TPreviewMesh * tmpMesh = getPreviewMesh();
3221 tmpMesh->Copy( theElements, copyElements);
3222 if ( !theCopy && !theTargetMesh )
3224 TIDSortedElemSet elemsAround, elemsAroundCopy;
3225 getElementsAround( theElements, getMeshDS(), elemsAround );
3226 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3228 workElements = & copyElements;
3229 theMakeGroups = false;
3232 ::SMESH_MeshEditor::PGroupIDs groupIds =
3233 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3235 if ( theCopy && !myIsPreviewMode )
3237 if ( theTargetMesh )
3239 theTargetMesh->GetMeshDS()->Modified();
3243 declareMeshModified( /*isReComputeSafe=*/false );
3247 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3249 SMESH_CATCH( SMESH::throwCorbaException );
3253 //=======================================================================
3254 //function : Translate
3256 //=======================================================================
3258 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3259 const SMESH::DirStruct & theVector,
3260 CORBA::Boolean theCopy)
3261 throw (SALOME::SALOME_Exception)
3263 if (!myIsPreviewMode) {
3264 TPythonDump() << this << ".Translate( "
3265 << theIDsOfElements << ", "
3266 << theVector << ", "
3269 if (theIDsOfElements.length()) {
3270 TIDSortedElemSet elements;
3271 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3272 translate(elements, theVector, theCopy, false);
3276 //=======================================================================
3277 //function : TranslateObject
3279 //=======================================================================
3281 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3282 const SMESH::DirStruct & theVector,
3283 CORBA::Boolean theCopy)
3284 throw (SALOME::SALOME_Exception)
3286 if (!myIsPreviewMode) {
3287 TPythonDump() << this << ".TranslateObject( "
3288 << theObject << ", "
3289 << theVector << ", "
3292 TIDSortedElemSet elements;
3294 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3296 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3297 translate(elements, theVector, theCopy, false);
3300 //=======================================================================
3301 //function : TranslateMakeGroups
3303 //=======================================================================
3305 SMESH::ListOfGroups*
3306 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3307 const SMESH::DirStruct& theVector)
3308 throw (SALOME::SALOME_Exception)
3310 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3312 SMESH::ListOfGroups * aGroups = 0;
3313 if (theIDsOfElements.length()) {
3314 TIDSortedElemSet elements;
3315 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3316 aGroups = translate(elements,theVector,true,true);
3318 if (!myIsPreviewMode) {
3319 dumpGroupsList(aPythonDump, aGroups);
3320 aPythonDump << this << ".TranslateMakeGroups( "
3321 << theIDsOfElements << ", "
3322 << theVector << " )";
3327 //=======================================================================
3328 //function : TranslateObjectMakeGroups
3330 //=======================================================================
3332 SMESH::ListOfGroups*
3333 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3334 const SMESH::DirStruct& theVector)
3335 throw (SALOME::SALOME_Exception)
3337 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3339 SMESH::ListOfGroups * aGroups = 0;
3340 TIDSortedElemSet elements;
3341 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3342 aGroups = translate(elements, theVector, true, true);
3344 if (!myIsPreviewMode) {
3345 dumpGroupsList(aPythonDump, aGroups);
3346 aPythonDump << this << ".TranslateObjectMakeGroups( "
3347 << theObject << ", "
3348 << theVector << " )";
3353 //=======================================================================
3354 //function : TranslateMakeMesh
3356 //=======================================================================
3358 SMESH::SMESH_Mesh_ptr
3359 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3360 const SMESH::DirStruct& theVector,
3361 CORBA::Boolean theCopyGroups,
3362 const char* theMeshName)
3363 throw (SALOME::SALOME_Exception)
3365 SMESH_Mesh_i* mesh_i;
3366 SMESH::SMESH_Mesh_var mesh;
3368 { // open new scope to dump "MakeMesh" command
3369 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3371 TPythonDump pydump; // to prevent dump at mesh creation
3373 mesh = makeMesh( theMeshName );
3374 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3376 if ( mesh_i && theIDsOfElements.length() )
3378 TIDSortedElemSet elements;
3379 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3380 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3381 mesh_i->CreateGroupServants();
3384 if ( !myIsPreviewMode ) {
3385 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3386 << theIDsOfElements << ", "
3387 << theVector << ", "
3388 << theCopyGroups << ", '"
3389 << theMeshName << "' )";
3394 if (!myIsPreviewMode && mesh_i)
3395 mesh_i->GetGroups();
3397 return mesh._retn();
3400 //=======================================================================
3401 //function : TranslateObjectMakeMesh
3403 //=======================================================================
3405 SMESH::SMESH_Mesh_ptr
3406 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3407 const SMESH::DirStruct& theVector,
3408 CORBA::Boolean theCopyGroups,
3409 const char* theMeshName)
3410 throw (SALOME::SALOME_Exception)
3413 SMESH_Mesh_i* mesh_i;
3414 SMESH::SMESH_Mesh_var mesh;
3415 { // open new scope to dump "MakeMesh" command
3416 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3418 TPythonDump pydump; // to prevent dump at mesh creation
3419 mesh = makeMesh( theMeshName );
3420 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3422 TIDSortedElemSet elements;
3424 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3426 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3427 mesh_i->CreateGroupServants();
3429 if ( !myIsPreviewMode ) {
3430 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3431 << theObject << ", "
3432 << theVector << ", "
3433 << theCopyGroups << ", '"
3434 << theMeshName << "' )";
3439 if (!myIsPreviewMode && mesh_i)
3440 mesh_i->GetGroups();
3442 return mesh._retn();
3444 SMESH_CATCH( SMESH::throwCorbaException );
3448 //=======================================================================
3451 //=======================================================================
3453 SMESH::ListOfGroups*
3454 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3455 const SMESH::AxisStruct & theAxis,
3456 CORBA::Double theAngle,
3457 CORBA::Boolean theCopy,
3459 ::SMESH_Mesh* theTargetMesh)
3460 throw (SALOME::SALOME_Exception)
3465 if ( theTargetMesh )
3468 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3469 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3472 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3474 TIDSortedElemSet copyElements;
3475 TIDSortedElemSet* workElements = &theElements;
3476 if ( myIsPreviewMode ) {
3477 TPreviewMesh * tmpMesh = getPreviewMesh();
3478 tmpMesh->Copy( theElements, copyElements );
3479 if ( !theCopy && !theTargetMesh )
3481 TIDSortedElemSet elemsAround, elemsAroundCopy;
3482 getElementsAround( theElements, getMeshDS(), elemsAround );
3483 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3485 workElements = ©Elements;
3486 theMakeGroups = false;
3489 ::SMESH_MeshEditor::PGroupIDs groupIds =
3490 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3492 if ( theCopy && !myIsPreviewMode)
3494 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3495 else declareMeshModified( /*isReComputeSafe=*/false );
3498 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3500 SMESH_CATCH( SMESH::throwCorbaException );
3504 //=======================================================================
3507 //=======================================================================
3509 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3510 const SMESH::AxisStruct & theAxis,
3511 CORBA::Double theAngle,
3512 CORBA::Boolean theCopy)
3513 throw (SALOME::SALOME_Exception)
3515 if (!myIsPreviewMode) {
3516 TPythonDump() << this << ".Rotate( "
3517 << theIDsOfElements << ", "
3519 << TVar( theAngle ) << ", "
3522 if (theIDsOfElements.length() > 0)
3524 TIDSortedElemSet elements;
3525 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3526 rotate(elements,theAxis,theAngle,theCopy,false);
3530 //=======================================================================
3531 //function : RotateObject
3533 //=======================================================================
3535 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3536 const SMESH::AxisStruct & theAxis,
3537 CORBA::Double theAngle,
3538 CORBA::Boolean theCopy)
3539 throw (SALOME::SALOME_Exception)
3541 if ( !myIsPreviewMode ) {
3542 TPythonDump() << this << ".RotateObject( "
3543 << theObject << ", "
3545 << TVar( theAngle ) << ", "
3548 TIDSortedElemSet elements;
3549 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3550 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3551 rotate(elements,theAxis,theAngle,theCopy,false);
3554 //=======================================================================
3555 //function : RotateMakeGroups
3557 //=======================================================================
3559 SMESH::ListOfGroups*
3560 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3561 const SMESH::AxisStruct& theAxis,
3562 CORBA::Double theAngle)
3563 throw (SALOME::SALOME_Exception)
3565 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3567 SMESH::ListOfGroups * aGroups = 0;
3568 if (theIDsOfElements.length() > 0)
3570 TIDSortedElemSet elements;
3571 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3572 aGroups = rotate(elements,theAxis,theAngle,true,true);
3574 if (!myIsPreviewMode) {
3575 dumpGroupsList(aPythonDump, aGroups);
3576 aPythonDump << this << ".RotateMakeGroups( "
3577 << theIDsOfElements << ", "
3579 << TVar( theAngle ) << " )";
3584 //=======================================================================
3585 //function : RotateObjectMakeGroups
3587 //=======================================================================
3589 SMESH::ListOfGroups*
3590 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3591 const SMESH::AxisStruct& theAxis,
3592 CORBA::Double theAngle)
3593 throw (SALOME::SALOME_Exception)
3595 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3597 SMESH::ListOfGroups * aGroups = 0;
3598 TIDSortedElemSet elements;
3599 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3600 aGroups = rotate(elements, theAxis, theAngle, true, true);
3602 if (!myIsPreviewMode) {
3603 dumpGroupsList(aPythonDump, aGroups);
3604 aPythonDump << this << ".RotateObjectMakeGroups( "
3605 << theObject << ", "
3607 << TVar( theAngle ) << " )";
3612 //=======================================================================
3613 //function : RotateMakeMesh
3615 //=======================================================================
3617 SMESH::SMESH_Mesh_ptr
3618 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3619 const SMESH::AxisStruct& theAxis,
3620 CORBA::Double theAngleInRadians,
3621 CORBA::Boolean theCopyGroups,
3622 const char* theMeshName)
3623 throw (SALOME::SALOME_Exception)
3626 SMESH::SMESH_Mesh_var mesh;
3627 SMESH_Mesh_i* mesh_i;
3629 { // open new scope to dump "MakeMesh" command
3630 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3632 TPythonDump pydump; // to prevent dump at mesh creation
3634 mesh = makeMesh( theMeshName );
3635 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3637 if ( mesh_i && theIDsOfElements.length() > 0 )
3639 TIDSortedElemSet elements;
3640 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3641 rotate(elements, theAxis, theAngleInRadians,
3642 false, theCopyGroups, & mesh_i->GetImpl());
3643 mesh_i->CreateGroupServants();
3645 if ( !myIsPreviewMode ) {
3646 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3647 << theIDsOfElements << ", "
3649 << TVar( theAngleInRadians ) << ", "
3650 << theCopyGroups << ", '"
3651 << theMeshName << "' )";
3656 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3657 mesh_i->GetGroups();
3659 return mesh._retn();
3661 SMESH_CATCH( SMESH::throwCorbaException );
3665 //=======================================================================
3666 //function : RotateObjectMakeMesh
3668 //=======================================================================
3670 SMESH::SMESH_Mesh_ptr
3671 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3672 const SMESH::AxisStruct& theAxis,
3673 CORBA::Double theAngleInRadians,
3674 CORBA::Boolean theCopyGroups,
3675 const char* theMeshName)
3676 throw (SALOME::SALOME_Exception)
3679 SMESH::SMESH_Mesh_var mesh;
3680 SMESH_Mesh_i* mesh_i;
3682 {// open new scope to dump "MakeMesh" command
3683 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3685 TPythonDump pydump; // to prevent dump at mesh creation
3686 mesh = makeMesh( theMeshName );
3687 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3689 TIDSortedElemSet elements;
3691 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3693 rotate(elements, theAxis, theAngleInRadians,
3694 false, theCopyGroups, & mesh_i->GetImpl());
3695 mesh_i->CreateGroupServants();
3697 if ( !myIsPreviewMode ) {
3698 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3699 << theObject << ", "
3701 << TVar( theAngleInRadians ) << ", "
3702 << theCopyGroups << ", '"
3703 << theMeshName << "' )";
3708 if (!myIsPreviewMode && mesh_i)
3709 mesh_i->GetGroups();
3711 return mesh._retn();
3713 SMESH_CATCH( SMESH::throwCorbaException );
3717 //=======================================================================
3720 //=======================================================================
3722 SMESH::ListOfGroups*
3723 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3724 const SMESH::PointStruct& thePoint,
3725 const SMESH::double_array& theScaleFact,
3726 CORBA::Boolean theCopy,
3728 ::SMESH_Mesh* theTargetMesh)
3729 throw (SALOME::SALOME_Exception)
3733 if ( theScaleFact.length() < 1 )
3734 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3735 if ( theScaleFact.length() == 2 )
3736 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3738 if ( theTargetMesh )
3741 TIDSortedElemSet elements;
3742 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3743 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3748 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3749 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3751 double tol = std::numeric_limits<double>::max();
3754 #if OCC_VERSION_LARGE > 0x06070100
3755 // fight against ortagonalization
3756 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3757 // 0, S[1], 0, thePoint.y * (1-S[1]),
3758 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3759 aTrsf.SetTranslation( gp_Vec( thePoint.x * (1-S[0]),
3760 thePoint.y * (1-S[1]),
3761 thePoint.z * (1-S[2])));
3762 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3763 M.SetDiagonal( S[0], S[1], S[2] );
3766 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3767 0, S[1], 0, thePoint.y * (1-S[1]),
3768 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3771 TIDSortedElemSet copyElements;
3772 TIDSortedElemSet* workElements = &elements;
3773 if ( myIsPreviewMode )
3775 TPreviewMesh * tmpMesh = getPreviewMesh();
3776 tmpMesh->Copy( elements, copyElements);
3777 if ( !theCopy && !theTargetMesh )
3779 TIDSortedElemSet elemsAround, elemsAroundCopy;
3780 getElementsAround( elements, getMeshDS(), elemsAround );
3781 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3783 workElements = & copyElements;
3784 theMakeGroups = false;
3787 ::SMESH_MeshEditor::PGroupIDs groupIds =
3788 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3790 if ( theCopy && !myIsPreviewMode )
3792 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3793 else declareMeshModified( /*isReComputeSafe=*/false );
3795 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3797 SMESH_CATCH( SMESH::throwCorbaException );
3801 //=======================================================================
3804 //=======================================================================
3806 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3807 const SMESH::PointStruct& thePoint,
3808 const SMESH::double_array& theScaleFact,
3809 CORBA::Boolean theCopy)
3810 throw (SALOME::SALOME_Exception)
3812 if ( !myIsPreviewMode ) {
3813 TPythonDump() << this << ".Scale( "
3814 << theObject << ", "
3816 << TVar( theScaleFact ) << ", "
3819 scale(theObject, thePoint, theScaleFact, theCopy, false);
3823 //=======================================================================
3824 //function : ScaleMakeGroups
3826 //=======================================================================
3828 SMESH::ListOfGroups*
3829 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3830 const SMESH::PointStruct& thePoint,
3831 const SMESH::double_array& theScaleFact)
3832 throw (SALOME::SALOME_Exception)
3834 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3836 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3837 if (!myIsPreviewMode) {
3838 dumpGroupsList(aPythonDump, aGroups);
3839 aPythonDump << this << ".Scale("
3842 << TVar( theScaleFact ) << ",True,True)";
3848 //=======================================================================
3849 //function : ScaleMakeMesh
3851 //=======================================================================
3853 SMESH::SMESH_Mesh_ptr
3854 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3855 const SMESH::PointStruct& thePoint,
3856 const SMESH::double_array& theScaleFact,
3857 CORBA::Boolean theCopyGroups,
3858 const char* theMeshName)
3859 throw (SALOME::SALOME_Exception)
3861 SMESH_Mesh_i* mesh_i;
3862 SMESH::SMESH_Mesh_var mesh;
3863 { // open new scope to dump "MakeMesh" command
3864 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3866 TPythonDump pydump; // to prevent dump at mesh creation
3867 mesh = makeMesh( theMeshName );
3868 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3872 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3873 mesh_i->CreateGroupServants();
3875 if ( !myIsPreviewMode )
3876 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3877 << theObject << ", "
3879 << TVar( theScaleFact ) << ", "
3880 << theCopyGroups << ", '"
3881 << theMeshName << "' )";
3885 if (!myIsPreviewMode && mesh_i)
3886 mesh_i->GetGroups();
3888 return mesh._retn();
3892 //=======================================================================
3893 //function : FindCoincidentNodes
3895 //=======================================================================
3897 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tolerance,
3898 SMESH::array_of_long_array_out GroupsOfNodes)
3899 throw (SALOME::SALOME_Exception)
3904 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3905 TIDSortedNodeSet nodes; // no input nodes
3906 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3908 GroupsOfNodes = new SMESH::array_of_long_array;
3909 GroupsOfNodes->length( aListOfListOfNodes.size() );
3910 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3911 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3912 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3913 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3914 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3915 aGroup.length( aListOfNodes.size() );
3916 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3917 aGroup[ j ] = (*lIt)->GetID();
3919 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3920 << Tolerance << " )";
3922 SMESH_CATCH( SMESH::throwCorbaException );
3925 //=======================================================================
3926 //function : FindCoincidentNodesOnPart
3928 //=======================================================================
3930 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
3931 CORBA::Double Tolerance,
3932 SMESH::array_of_long_array_out GroupsOfNodes)
3933 throw (SALOME::SALOME_Exception)
3938 TIDSortedNodeSet nodes;
3939 idSourceToNodeSet( theObject, getMeshDS(), nodes );
3941 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3943 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3945 GroupsOfNodes = new SMESH::array_of_long_array;
3946 GroupsOfNodes->length( aListOfListOfNodes.size() );
3947 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3948 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3950 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3951 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3952 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3953 aGroup.length( aListOfNodes.size() );
3954 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3955 aGroup[ j ] = (*lIt)->GetID();
3957 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
3959 << Tolerance << " )";
3961 SMESH_CATCH( SMESH::throwCorbaException );
3964 //================================================================================
3966 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
3967 * ExceptSubMeshOrGroups
3969 //================================================================================
3971 void SMESH_MeshEditor_i::
3972 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
3973 CORBA::Double theTolerance,
3974 SMESH::array_of_long_array_out theGroupsOfNodes,
3975 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups)
3976 throw (SALOME::SALOME_Exception)
3981 TIDSortedNodeSet nodes;
3982 idSourceToNodeSet( theObject, getMeshDS(), nodes );
3984 for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
3986 TIDSortedNodeSet exceptNodes;
3987 idSourceToNodeSet( theExceptSubMeshOrGroups[i], getMeshDS(), exceptNodes );
3988 TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
3989 for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
3990 nodes.erase( *avoidNode );
3992 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3994 getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
3996 theGroupsOfNodes = new SMESH::array_of_long_array;
3997 theGroupsOfNodes->length( aListOfListOfNodes.size() );
3998 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3999 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4001 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4002 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4003 SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
4004 aGroup.length( aListOfNodes.size() );
4005 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4006 aGroup[ j ] = (*lIt)->GetID();
4008 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4010 << theTolerance << ", "
4011 << theExceptSubMeshOrGroups << " )";
4013 SMESH_CATCH( SMESH::throwCorbaException );
4016 //=======================================================================
4017 //function : MergeNodes
4019 //=======================================================================
4021 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
4022 throw (SALOME::SALOME_Exception)
4027 SMESHDS_Mesh* aMesh = getMeshDS();
4029 TPythonDump aTPythonDump;
4030 aTPythonDump << this << ".MergeNodes([";
4031 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4032 for (int i = 0; i < GroupsOfNodes.length(); i++)
4034 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4035 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4036 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4037 for ( int j = 0; j < aNodeGroup.length(); j++ )
4039 CORBA::Long index = aNodeGroup[ j ];
4040 const SMDS_MeshNode * node = aMesh->FindNode(index);
4042 aListOfNodes.push_back( node );
4044 if ( aListOfNodes.size() < 2 )
4045 aListOfListOfNodes.pop_back();
4047 if ( i > 0 ) aTPythonDump << ", ";
4048 aTPythonDump << aNodeGroup;
4050 getEditor().MergeNodes( aListOfListOfNodes );
4052 aTPythonDump << "])";
4054 declareMeshModified( /*isReComputeSafe=*/false );
4056 SMESH_CATCH( SMESH::throwCorbaException );
4059 //=======================================================================
4060 //function : FindEqualElements
4062 //=======================================================================
4064 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4065 SMESH::array_of_long_array_out GroupsOfElementsID)
4066 throw (SALOME::SALOME_Exception)
4071 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4072 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4074 TIDSortedElemSet elems;
4075 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4077 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4078 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4080 GroupsOfElementsID = new SMESH::array_of_long_array;
4081 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4083 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4084 aListOfListOfElementsID.begin();
4085 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4087 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4088 list<int>& listOfIDs = *arraysIt;
4089 aGroup.length( listOfIDs.size() );
4090 list<int>::iterator idIt = listOfIDs.begin();
4091 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4092 aGroup[ k ] = *idIt;
4095 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4099 SMESH_CATCH( SMESH::throwCorbaException );
4102 //=======================================================================
4103 //function : MergeElements
4105 //=======================================================================
4107 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4108 throw (SALOME::SALOME_Exception)
4113 TPythonDump aTPythonDump;
4114 aTPythonDump << this << ".MergeElements( [";
4116 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4118 for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4119 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4120 aListOfListOfElementsID.push_back( list< int >() );
4121 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4122 for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4123 CORBA::Long id = anElemsIDGroup[ j ];
4124 aListOfElemsID.push_back( id );
4126 if ( aListOfElemsID.size() < 2 )
4127 aListOfListOfElementsID.pop_back();
4128 if ( i > 0 ) aTPythonDump << ", ";
4129 aTPythonDump << anElemsIDGroup;
4132 getEditor().MergeElements(aListOfListOfElementsID);
4134 declareMeshModified( /*isReComputeSafe=*/true );
4136 aTPythonDump << "] )";
4138 SMESH_CATCH( SMESH::throwCorbaException );
4141 //=======================================================================
4142 //function : MergeEqualElements
4144 //=======================================================================
4146 void SMESH_MeshEditor_i::MergeEqualElements()
4147 throw (SALOME::SALOME_Exception)
4152 getEditor().MergeEqualElements();
4154 declareMeshModified( /*isReComputeSafe=*/true );
4156 TPythonDump() << this << ".MergeEqualElements()";
4158 SMESH_CATCH( SMESH::throwCorbaException );
4161 //=============================================================================
4163 * Move the node to a given point
4165 //=============================================================================
4167 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4171 throw (SALOME::SALOME_Exception)
4174 initData(/*deleteSearchers=*/false);
4176 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4180 if ( theNodeSearcher )
4181 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4183 if ( myIsPreviewMode ) // make preview data
4185 // in a preview mesh, make edges linked to a node
4186 TPreviewMesh& tmpMesh = *getPreviewMesh();
4187 TIDSortedElemSet linkedNodes;
4188 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4189 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4190 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4191 for ( ; nIt != linkedNodes.end(); ++nIt )
4193 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4194 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4198 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4199 // fill preview data
4201 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4202 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4204 getMeshDS()->MoveNode(node, x, y, z);
4206 if ( !myIsPreviewMode )
4208 // Update Python script
4209 TPythonDump() << "isDone = " << this << ".MoveNode( "
4210 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4211 declareMeshModified( /*isReComputeSafe=*/false );
4214 SMESH_CATCH( SMESH::throwCorbaException );
4219 //================================================================================
4221 * \brief Return ID of node closest to a given point
4223 //================================================================================
4225 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4228 throw (SALOME::SALOME_Exception)
4231 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4233 if ( !theNodeSearcher ) {
4234 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4237 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4238 return node->GetID();
4240 SMESH_CATCH( SMESH::throwCorbaException );
4244 //================================================================================
4246 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4247 * move the node closest to the point to point's location and return ID of the node
4249 //================================================================================
4251 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4254 CORBA::Long theNodeID)
4255 throw (SALOME::SALOME_Exception)
4258 // We keep theNodeSearcher until any mesh modification:
4259 // 1) initData() deletes theNodeSearcher at any edition,
4260 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4262 initData(/*deleteSearchers=*/false);
4264 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4266 int nodeID = theNodeID;
4267 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4268 if ( !node ) // preview moving node
4270 if ( !theNodeSearcher ) {
4271 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4274 node = theNodeSearcher->FindClosestTo( p );
4277 nodeID = node->GetID();
4278 if ( myIsPreviewMode ) // make preview data
4280 // in a preview mesh, make edges linked to a node
4281 TPreviewMesh tmpMesh = *getPreviewMesh();
4282 TIDSortedElemSet linkedNodes;
4283 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4284 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4285 for ( ; nIt != linkedNodes.end(); ++nIt )
4287 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4288 tmpMesh.Copy( &edge );
4291 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4293 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4294 // fill preview data
4296 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4298 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4302 getMeshDS()->MoveNode(node, x, y, z);
4306 if ( !myIsPreviewMode )
4308 TPythonDump() << "nodeID = " << this
4309 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4310 << ", " << nodeID << " )";
4312 declareMeshModified( /*isReComputeSafe=*/false );
4317 SMESH_CATCH( SMESH::throwCorbaException );
4321 //=======================================================================
4323 * Return elements of given type where the given point is IN or ON.
4325 * 'ALL' type means elements of any type excluding nodes
4327 //=======================================================================
4329 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4332 SMESH::ElementType type)
4333 throw (SALOME::SALOME_Exception)
4336 SMESH::long_array_var res = new SMESH::long_array;
4337 vector< const SMDS_MeshElement* > foundElems;
4339 theSearchersDeleter.Set( myMesh );
4340 if ( !theElementSearcher ) {
4341 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4343 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4344 SMDSAbs_ElementType( type ),
4346 res->length( foundElems.size() );
4347 for ( int i = 0; i < foundElems.size(); ++i )
4348 res[i] = foundElems[i]->GetID();
4352 SMESH_CATCH( SMESH::throwCorbaException );
4356 //=======================================================================
4357 //function : FindAmongElementsByPoint
4358 //purpose : Searching among the given elements, return elements of given type
4359 // where the given point is IN or ON.
4360 // 'ALL' type means elements of any type excluding nodes
4361 //=======================================================================
4364 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4368 SMESH::ElementType type)
4369 throw (SALOME::SALOME_Exception)
4372 SMESH::long_array_var res = new SMESH::long_array;
4374 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4375 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4376 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4377 type != types[0] ) // but search of elements of dim > 0
4380 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4381 return FindElementsByPoint( x,y,z, type );
4383 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4385 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4386 if ( !theElementSearcher )
4388 // create a searcher from elementIDs
4389 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4390 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4392 if ( !idSourceToSet( elementIDs, meshDS, elements,
4393 SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4396 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4397 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4399 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4402 vector< const SMDS_MeshElement* > foundElems;
4404 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4405 SMDSAbs_ElementType( type ),
4407 res->length( foundElems.size() );
4408 for ( int i = 0; i < foundElems.size(); ++i )
4409 res[i] = foundElems[i]->GetID();
4413 SMESH_CATCH( SMESH::throwCorbaException );
4417 //=======================================================================
4418 //function : GetPointState
4419 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4420 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4421 //=======================================================================
4423 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4426 throw (SALOME::SALOME_Exception)
4429 theSearchersDeleter.Set( myMesh );
4430 if ( !theElementSearcher ) {
4431 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4433 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4435 SMESH_CATCH( SMESH::throwCorbaException );
4439 //=======================================================================
4440 //function : convError
4442 //=======================================================================
4444 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4446 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4450 RETCASE( SEW_BORDER1_NOT_FOUND );
4451 RETCASE( SEW_BORDER2_NOT_FOUND );
4452 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4453 RETCASE( SEW_BAD_SIDE_NODES );
4454 RETCASE( SEW_VOLUMES_TO_SPLIT );
4455 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4456 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4457 RETCASE( SEW_BAD_SIDE1_NODES );
4458 RETCASE( SEW_BAD_SIDE2_NODES );
4460 return SMESH::SMESH_MeshEditor::SEW_OK;
4463 //=======================================================================
4464 //function : SewFreeBorders
4466 //=======================================================================
4468 SMESH::SMESH_MeshEditor::Sew_Error
4469 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4470 CORBA::Long SecondNodeID1,
4471 CORBA::Long LastNodeID1,
4472 CORBA::Long FirstNodeID2,
4473 CORBA::Long SecondNodeID2,
4474 CORBA::Long LastNodeID2,
4475 CORBA::Boolean CreatePolygons,
4476 CORBA::Boolean CreatePolyedrs)
4477 throw (SALOME::SALOME_Exception)
4482 SMESHDS_Mesh* aMesh = getMeshDS();
4484 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4485 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4486 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4487 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4488 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4489 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4491 if (!aBorderFirstNode ||
4492 !aBorderSecondNode||
4494 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4495 if (!aSide2FirstNode ||
4496 !aSide2SecondNode ||
4498 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4500 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4501 << FirstNodeID1 << ", "
4502 << SecondNodeID1 << ", "
4503 << LastNodeID1 << ", "
4504 << FirstNodeID2 << ", "
4505 << SecondNodeID2 << ", "
4506 << LastNodeID2 << ", "
4507 << CreatePolygons<< ", "
4508 << CreatePolyedrs<< " )";
4510 SMESH::SMESH_MeshEditor::Sew_Error error =
4511 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4522 declareMeshModified( /*isReComputeSafe=*/false );
4525 SMESH_CATCH( SMESH::throwCorbaException );
4526 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4530 //=======================================================================
4531 //function : SewConformFreeBorders
4533 //=======================================================================
4535 SMESH::SMESH_MeshEditor::Sew_Error
4536 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4537 CORBA::Long SecondNodeID1,
4538 CORBA::Long LastNodeID1,
4539 CORBA::Long FirstNodeID2,
4540 CORBA::Long SecondNodeID2)
4541 throw (SALOME::SALOME_Exception)
4546 SMESHDS_Mesh* aMesh = getMeshDS();
4548 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4549 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4550 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4551 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4552 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4553 const SMDS_MeshNode* aSide2ThirdNode = 0;
4555 if (!aBorderFirstNode ||
4556 !aBorderSecondNode||
4558 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4559 if (!aSide2FirstNode ||
4561 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4563 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4564 << FirstNodeID1 << ", "
4565 << SecondNodeID1 << ", "
4566 << LastNodeID1 << ", "
4567 << FirstNodeID2 << ", "
4568 << SecondNodeID2 << " )";
4570 SMESH::SMESH_MeshEditor::Sew_Error error =
4571 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4580 declareMeshModified( /*isReComputeSafe=*/false );
4583 SMESH_CATCH( SMESH::throwCorbaException );
4584 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4588 //=======================================================================
4589 //function : SewBorderToSide
4591 //=======================================================================
4593 SMESH::SMESH_MeshEditor::Sew_Error
4594 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4595 CORBA::Long SecondNodeIDOnFreeBorder,
4596 CORBA::Long LastNodeIDOnFreeBorder,
4597 CORBA::Long FirstNodeIDOnSide,
4598 CORBA::Long LastNodeIDOnSide,
4599 CORBA::Boolean CreatePolygons,
4600 CORBA::Boolean CreatePolyedrs)
4601 throw (SALOME::SALOME_Exception)
4606 SMESHDS_Mesh* aMesh = getMeshDS();
4608 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4609 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4610 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4611 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4612 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4613 const SMDS_MeshNode* aSide2ThirdNode = 0;
4615 if (!aBorderFirstNode ||
4616 !aBorderSecondNode||
4618 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4619 if (!aSide2FirstNode ||
4621 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4623 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4624 << FirstNodeIDOnFreeBorder << ", "
4625 << SecondNodeIDOnFreeBorder << ", "
4626 << LastNodeIDOnFreeBorder << ", "
4627 << FirstNodeIDOnSide << ", "
4628 << LastNodeIDOnSide << ", "
4629 << CreatePolygons << ", "
4630 << CreatePolyedrs << ") ";
4632 SMESH::SMESH_MeshEditor::Sew_Error error =
4633 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4643 declareMeshModified( /*isReComputeSafe=*/false );
4646 SMESH_CATCH( SMESH::throwCorbaException );
4647 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4651 //=======================================================================
4652 //function : SewSideElements
4654 //=======================================================================
4656 SMESH::SMESH_MeshEditor::Sew_Error
4657 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4658 const SMESH::long_array& IDsOfSide2Elements,
4659 CORBA::Long NodeID1OfSide1ToMerge,
4660 CORBA::Long NodeID1OfSide2ToMerge,
4661 CORBA::Long NodeID2OfSide1ToMerge,
4662 CORBA::Long NodeID2OfSide2ToMerge)
4663 throw (SALOME::SALOME_Exception)
4668 SMESHDS_Mesh* aMesh = getMeshDS();
4670 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
4671 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
4672 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4673 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4675 if (!aFirstNode1ToMerge ||
4676 !aFirstNode2ToMerge )
4677 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4678 if (!aSecondNode1ToMerge||
4679 !aSecondNode2ToMerge)
4680 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4682 TIDSortedElemSet aSide1Elems, aSide2Elems;
4683 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4684 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4686 TPythonDump() << "error = " << this << ".SewSideElements( "
4687 << IDsOfSide1Elements << ", "
4688 << IDsOfSide2Elements << ", "
4689 << NodeID1OfSide1ToMerge << ", "
4690 << NodeID1OfSide2ToMerge << ", "
4691 << NodeID2OfSide1ToMerge << ", "
4692 << NodeID2OfSide2ToMerge << ")";
4694 SMESH::SMESH_MeshEditor::Sew_Error error =
4695 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
4698 aSecondNode1ToMerge,
4699 aSecondNode2ToMerge));
4701 declareMeshModified( /*isReComputeSafe=*/false );
4704 SMESH_CATCH( SMESH::throwCorbaException );
4705 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4708 //================================================================================
4710 * \brief Set new nodes for given element
4711 * \param ide - element id
4712 * \param newIDs - new node ids
4713 * \retval CORBA::Boolean - true if result is OK
4715 //================================================================================
4717 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4718 const SMESH::long_array& newIDs)
4719 throw (SALOME::SALOME_Exception)
4724 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
4725 if(!elem) return false;
4727 int nbn = newIDs.length();
4729 vector<const SMDS_MeshNode*> aNodes(nbn);
4732 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
4735 aNodes[nbn1] = aNode;
4738 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4739 << ide << ", " << newIDs << " )";
4741 MESSAGE("ChangeElementNodes");
4742 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4744 declareMeshModified( /*isReComputeSafe=*/ !res );
4748 SMESH_CATCH( SMESH::throwCorbaException );
4752 //=======================================================================
4754 * \brief Makes a part of the mesh quadratic or bi-quadratic
4756 //=======================================================================
4758 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
4759 CORBA::Boolean theToBiQuad,
4760 SMESH::SMESH_IDSource_ptr theObject)
4761 throw (SALOME::SALOME_Exception)
4764 TIDSortedElemSet elems;
4766 if ( !( elemsOK = CORBA::is_nil( theObject )))
4768 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
4769 SMDSAbs_All, /*emptyIfIsMesh=*/true );
4773 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
4774 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4776 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
4777 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
4779 declareMeshModified( /*isReComputeSafe=*/false );
4782 SMESH_CATCH( SMESH::throwCorbaException );
4785 //=======================================================================
4786 //function : ConvertFromQuadratic
4788 //=======================================================================
4790 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4791 throw (SALOME::SALOME_Exception)
4793 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
4794 TPythonDump() << this << ".ConvertFromQuadratic()";
4795 declareMeshModified( /*isReComputeSafe=*/!isDone );
4799 //=======================================================================
4800 //function : ConvertToQuadratic
4802 //=======================================================================
4804 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4805 throw (SALOME::SALOME_Exception)
4807 convertToQuadratic( theForce3d, false );
4808 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
4811 //================================================================================
4813 * \brief Makes a part of the mesh quadratic
4815 //================================================================================
4817 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
4818 SMESH::SMESH_IDSource_ptr theObject)
4819 throw (SALOME::SALOME_Exception)
4821 convertToQuadratic( theForce3d, false, theObject );
4822 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
4825 //================================================================================
4827 * \brief Makes a part of the mesh bi-quadratic
4829 //================================================================================
4831 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
4832 SMESH::SMESH_IDSource_ptr theObject)
4833 throw (SALOME::SALOME_Exception)
4835 convertToQuadratic( theForce3d, true, theObject );
4836 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
4839 //================================================================================
4841 * \brief Makes a part of the mesh linear
4843 //================================================================================
4845 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
4846 throw (SALOME::SALOME_Exception)
4852 TIDSortedElemSet elems;
4853 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
4855 if ( elems.empty() )
4857 ConvertFromQuadratic();
4859 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
4861 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4865 getEditor().ConvertFromQuadratic(elems);
4868 declareMeshModified( /*isReComputeSafe=*/false );
4870 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
4872 SMESH_CATCH( SMESH::throwCorbaException );
4875 //=======================================================================
4876 //function : makeMesh
4877 //purpose : create a named imported mesh
4878 //=======================================================================
4880 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4882 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4883 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4884 SALOMEDS::Study_var study = gen->GetCurrentStudy();
4885 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
4886 gen->SetName( meshSO, theMeshName, "Mesh" );
4887 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4889 return mesh._retn();
4892 //=======================================================================
4893 //function : dumpGroupsList
4895 //=======================================================================
4897 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
4898 const SMESH::ListOfGroups * theGroupList)
4900 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
4901 if ( isDumpGroupList )
4902 theDumpPython << theGroupList << " = ";
4905 //================================================================================
4907 \brief Generates the unique group name.
4908 \param thePrefix name prefix
4911 //================================================================================
4913 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
4915 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4916 set<string> groupNames;
4918 // Get existing group names
4919 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
4920 SMESH::SMESH_GroupBase_var aGroup = groups[i];
4921 if (CORBA::is_nil(aGroup))
4924 CORBA::String_var name = aGroup->GetName();
4925 groupNames.insert( name.in() );
4929 string name = thePrefix;
4932 while (!groupNames.insert(name).second)
4933 name = SMESH_Comment( thePrefix ) << "_" << index++;
4938 //================================================================================
4940 * \brief Prepare SMESH_IDSource for work
4942 //================================================================================
4944 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
4946 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
4948 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
4949 filter->SetMesh( mesh );
4952 //================================================================================
4954 * \brief Retrieve elements of given type from SMESH_IDSource
4956 //================================================================================
4958 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
4959 const SMESHDS_Mesh* theMeshDS,
4960 TIDSortedElemSet& theElemSet,
4961 const SMDSAbs_ElementType theType,
4962 const bool emptyIfIsMesh,
4963 IDSource_Error* error)
4966 if ( error ) *error = IDSource_OK;
4968 if ( CORBA::is_nil( theIDSource ) )
4970 if ( error ) *error = IDSource_INVALID;
4973 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
4975 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
4976 *error = IDSource_EMPTY;
4979 prepareIdSource( theIDSource );
4980 SMESH::long_array_var anIDs = theIDSource->GetIDs();
4981 if ( anIDs->length() == 0 )
4983 if ( error ) *error = IDSource_EMPTY;
4986 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
4987 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
4989 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
4991 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
4995 if ( error ) *error = IDSource_INVALID;
5001 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5002 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5004 if ( error ) *error = IDSource_INVALID;
5011 //================================================================================
5013 * \brief Duplicates given elements, i.e. creates new elements based on the
5014 * same nodes as the given ones.
5015 * \param theElements - container of elements to duplicate.
5016 * \param theGroupName - a name of group to contain the generated elements.
5017 * If a group with such a name already exists, the new elements
5018 * are added to the existng group, else a new group is created.
5019 * If \a theGroupName is empty, new elements are not added
5021 * \return a group where the new elements are added. NULL if theGroupName == "".
5024 //================================================================================
5026 SMESH::SMESH_Group_ptr
5027 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5028 const char* theGroupName)
5029 throw (SALOME::SALOME_Exception)
5031 SMESH::SMESH_Group_var newGroup;
5038 TIDSortedElemSet elems;
5039 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5041 getEditor().DoubleElements( elems );
5043 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5046 SMESH::ElementType type =
5047 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5048 // find existing group
5049 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5050 for ( size_t i = 0; i < groups->length(); ++i )
5051 if ( groups[i]->GetType() == type )
5053 CORBA::String_var name = groups[i]->GetName();
5054 if ( strcmp( name, theGroupName ) == 0 ) {
5055 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5059 // create a new group
5060 if ( newGroup->_is_nil() )
5061 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5063 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5065 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5066 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5067 for ( int i = 1; i <= aSeq.Length(); i++ )
5068 groupDS->SMDSGroup().Add( aSeq(i) );
5073 if ( !newGroup->_is_nil() )
5074 pyDump << newGroup << " = ";
5075 pyDump << this << ".DoubleElements( "
5076 << theElements << ", " << "'" << theGroupName <<"')";
5078 SMESH_CATCH( SMESH::throwCorbaException );
5080 return newGroup._retn();
5083 //================================================================================
5085 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5086 \param theNodes - identifiers of nodes to be doubled
5087 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5088 nodes. If list of element identifiers is empty then nodes are doubled but
5089 they not assigned to elements
5090 \return TRUE if operation has been completed successfully, FALSE otherwise
5091 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5093 //================================================================================
5095 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5096 const SMESH::long_array& theModifiedElems )
5097 throw (SALOME::SALOME_Exception)
5102 list< int > aListOfNodes;
5104 for ( i = 0, n = theNodes.length(); i < n; i++ )
5105 aListOfNodes.push_back( theNodes[ i ] );
5107 list< int > aListOfElems;
5108 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5109 aListOfElems.push_back( theModifiedElems[ i ] );
5111 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5113 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5115 // Update Python script
5116 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5120 SMESH_CATCH( SMESH::throwCorbaException );
5124 //================================================================================
5126 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5127 This method provided for convenience works as DoubleNodes() described above.
5128 \param theNodeId - identifier of node to be doubled.
5129 \param theModifiedElems - identifiers of elements to be updated.
5130 \return TRUE if operation has been completed successfully, FALSE otherwise
5131 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5133 //================================================================================
5135 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5136 const SMESH::long_array& theModifiedElems )
5137 throw (SALOME::SALOME_Exception)
5140 SMESH::long_array_var aNodes = new SMESH::long_array;
5141 aNodes->length( 1 );
5142 aNodes[ 0 ] = theNodeId;
5144 TPythonDump pyDump; // suppress dump by the next line
5146 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5148 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5152 SMESH_CATCH( SMESH::throwCorbaException );
5156 //================================================================================
5158 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5159 This method provided for convenience works as DoubleNodes() described above.
5160 \param theNodes - group of nodes to be doubled.
5161 \param theModifiedElems - group of elements to be updated.
5162 \return TRUE if operation has been completed successfully, FALSE otherwise
5163 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5165 //================================================================================
5167 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5168 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5169 throw (SALOME::SALOME_Exception)
5172 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5175 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5176 SMESH::long_array_var aModifiedElems;
5177 if ( !CORBA::is_nil( theModifiedElems ) )
5178 aModifiedElems = theModifiedElems->GetListOfID();
5181 aModifiedElems = new SMESH::long_array;
5182 aModifiedElems->length( 0 );
5185 TPythonDump pyDump; // suppress dump by the next line
5187 bool done = DoubleNodes( aNodes, aModifiedElems );
5189 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5193 SMESH_CATCH( SMESH::throwCorbaException );
5197 //================================================================================
5199 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5200 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5201 * \param theNodes - group of nodes to be doubled.
5202 * \param theModifiedElems - group of elements to be updated.
5203 * \return a new group with newly created nodes
5204 * \sa DoubleNodeGroup()
5206 //================================================================================
5208 SMESH::SMESH_Group_ptr
5209 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5210 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5211 throw (SALOME::SALOME_Exception)
5214 SMESH::SMESH_Group_var aNewGroup;
5216 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5217 return aNewGroup._retn();
5220 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5221 SMESH::long_array_var aModifiedElems;
5222 if ( !CORBA::is_nil( theModifiedElems ) )
5223 aModifiedElems = theModifiedElems->GetListOfID();
5225 aModifiedElems = new SMESH::long_array;
5226 aModifiedElems->length( 0 );
5229 TPythonDump pyDump; // suppress dump by the next line
5231 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5234 // Create group with newly created nodes
5235 SMESH::long_array_var anIds = GetLastCreatedNodes();
5236 if (anIds->length() > 0) {
5237 string anUnindexedName (theNodes->GetName());
5238 string aNewName = generateGroupName(anUnindexedName + "_double");
5239 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5240 aNewGroup->Add(anIds);
5241 pyDump << aNewGroup << " = ";
5245 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5246 << theModifiedElems << " )";
5248 return aNewGroup._retn();
5250 SMESH_CATCH( SMESH::throwCorbaException );
5254 //================================================================================
5256 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5257 This method provided for convenience works as DoubleNodes() described above.
5258 \param theNodes - list of groups of nodes to be doubled
5259 \param theModifiedElems - list of groups of elements to be updated.
5260 \return TRUE if operation has been completed successfully, FALSE otherwise
5261 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5263 //================================================================================
5265 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5266 const SMESH::ListOfGroups& theModifiedElems )
5267 throw (SALOME::SALOME_Exception)
5272 std::list< int > aNodes;
5274 for ( i = 0, n = theNodes.length(); i < n; i++ )
5276 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5277 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5279 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5280 for ( j = 0, m = aCurr->length(); j < m; j++ )
5281 aNodes.push_back( aCurr[ j ] );
5285 std::list< int > anElems;
5286 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5288 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5289 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5291 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5292 for ( j = 0, m = aCurr->length(); j < m; j++ )
5293 anElems.push_back( aCurr[ j ] );
5297 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5299 declareMeshModified( /*isReComputeSafe=*/false );
5301 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5305 SMESH_CATCH( SMESH::throwCorbaException );
5309 //================================================================================
5311 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5312 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5313 * \param theNodes - group of nodes to be doubled.
5314 * \param theModifiedElems - group of elements to be updated.
5315 * \return a new group with newly created nodes
5316 * \sa DoubleNodeGroups()
5318 //================================================================================
5320 SMESH::SMESH_Group_ptr
5321 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5322 const SMESH::ListOfGroups& theModifiedElems )
5323 throw (SALOME::SALOME_Exception)
5325 SMESH::SMESH_Group_var aNewGroup;
5327 TPythonDump pyDump; // suppress dump by the next line
5329 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5333 // Create group with newly created nodes
5334 SMESH::long_array_var anIds = GetLastCreatedNodes();
5335 if (anIds->length() > 0) {
5336 string anUnindexedName (theNodes[0]->GetName());
5337 string aNewName = generateGroupName(anUnindexedName + "_double");
5338 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5339 aNewGroup->Add(anIds);
5340 pyDump << aNewGroup << " = ";
5344 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5345 << theModifiedElems << " )";
5347 return aNewGroup._retn();
5351 //================================================================================
5353 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5354 \param theElems - the list of elements (edges or faces) to be replicated
5355 The nodes for duplication could be found from these elements
5356 \param theNodesNot - list of nodes to NOT replicate
5357 \param theAffectedElems - the list of elements (cells and edges) to which the
5358 replicated nodes should be associated to.
5359 \return TRUE if operation has been completed successfully, FALSE otherwise
5360 \sa DoubleNodeGroup(), DoubleNodeGroups()
5362 //================================================================================
5364 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5365 const SMESH::long_array& theNodesNot,
5366 const SMESH::long_array& theAffectedElems )
5367 throw (SALOME::SALOME_Exception)
5372 SMESHDS_Mesh* aMeshDS = getMeshDS();
5373 TIDSortedElemSet anElems, aNodes, anAffected;
5374 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5375 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5376 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5378 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5380 // Update Python script
5381 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5382 << theNodesNot << ", " << theAffectedElems << " )";
5384 declareMeshModified( /*isReComputeSafe=*/false );
5387 SMESH_CATCH( SMESH::throwCorbaException );
5391 //================================================================================
5393 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5394 \param theElems - the list of elements (edges or faces) to be replicated
5395 The nodes for duplication could be found from these elements
5396 \param theNodesNot - list of nodes to NOT replicate
5397 \param theShape - shape to detect affected elements (element which geometric center
5398 located on or inside shape).
5399 The replicated nodes should be associated to affected elements.
5400 \return TRUE if operation has been completed successfully, FALSE otherwise
5401 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5403 //================================================================================
5405 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5406 const SMESH::long_array& theNodesNot,
5407 GEOM::GEOM_Object_ptr theShape )
5408 throw (SALOME::SALOME_Exception)
5414 SMESHDS_Mesh* aMeshDS = getMeshDS();
5415 TIDSortedElemSet anElems, aNodes;
5416 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5417 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5419 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5420 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5422 // Update Python script
5423 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5424 << theNodesNot << ", " << theShape << " )";
5426 declareMeshModified( /*isReComputeSafe=*/false );
5429 SMESH_CATCH( SMESH::throwCorbaException );
5433 //================================================================================
5435 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5436 \param theElems - group of of elements (edges or faces) to be replicated
5437 \param theNodesNot - group of nodes not to replicated
5438 \param theAffectedElems - group of elements to which the replicated nodes
5439 should be associated to.
5440 \return TRUE if operation has been completed successfully, FALSE otherwise
5441 \sa DoubleNodes(), DoubleNodeGroups()
5443 //================================================================================
5446 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5447 SMESH::SMESH_GroupBase_ptr theNodesNot,
5448 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5449 throw (SALOME::SALOME_Exception)
5452 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5458 SMESHDS_Mesh* aMeshDS = getMeshDS();
5459 TIDSortedElemSet anElems, aNodes, anAffected;
5460 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5461 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5462 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5464 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5466 // Update Python script
5467 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5468 << theNodesNot << ", " << theAffectedElems << " )";
5470 declareMeshModified( /*isReComputeSafe=*/false );
5473 SMESH_CATCH( SMESH::throwCorbaException );
5477 //================================================================================
5479 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5480 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5481 * \param theElems - group of of elements (edges or faces) to be replicated
5482 * \param theNodesNot - group of nodes not to replicated
5483 * \param theAffectedElems - group of elements to which the replicated nodes
5484 * should be associated to.
5485 * \return a new group with newly created elements
5486 * \sa DoubleNodeElemGroup()
5488 //================================================================================
5490 SMESH::SMESH_Group_ptr
5491 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5492 SMESH::SMESH_GroupBase_ptr theNodesNot,
5493 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5494 throw (SALOME::SALOME_Exception)
5497 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5501 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5502 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5504 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5506 << theNodesNot << ", "
5507 << theAffectedElems << " )";
5509 return elemGroup._retn();
5512 //================================================================================
5514 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5515 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5516 * \param theElems - group of of elements (edges or faces) to be replicated
5517 * \param theNodesNot - group of nodes not to replicated
5518 * \param theAffectedElems - group of elements to which the replicated nodes
5519 * should be associated to.
5520 * \return a new group with newly created elements
5521 * \sa DoubleNodeElemGroup()
5523 //================================================================================
5525 SMESH::ListOfGroups*
5526 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5527 SMESH::SMESH_GroupBase_ptr theNodesNot,
5528 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5529 CORBA::Boolean theElemGroupNeeded,
5530 CORBA::Boolean theNodeGroupNeeded)
5531 throw (SALOME::SALOME_Exception)
5534 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5535 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5536 aTwoGroups->length( 2 );
5538 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5539 return aTwoGroups._retn();
5544 SMESHDS_Mesh* aMeshDS = getMeshDS();
5545 TIDSortedElemSet anElems, aNodes, anAffected;
5546 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5547 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5548 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5551 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5553 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5559 // Create group with newly created elements
5560 CORBA::String_var elemGroupName = theElems->GetName();
5561 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5562 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5564 SMESH::long_array_var anIds = GetLastCreatedElems();
5565 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5566 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5567 aNewElemGroup->Add(anIds);
5569 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5571 SMESH::long_array_var anIds = GetLastCreatedNodes();
5572 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5573 aNewNodeGroup->Add(anIds);
5577 // Update Python script
5580 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5581 else pyDump << aNewElemGroup << ", ";
5582 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5583 else pyDump << aNewNodeGroup << " ] = ";
5585 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5586 << theNodesNot << ", "
5587 << theAffectedElems << ", "
5588 << theElemGroupNeeded << ", "
5589 << theNodeGroupNeeded <<" )";
5591 aTwoGroups[0] = aNewElemGroup._retn();
5592 aTwoGroups[1] = aNewNodeGroup._retn();
5593 return aTwoGroups._retn();
5595 SMESH_CATCH( SMESH::throwCorbaException );
5599 //================================================================================
5601 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5602 \param theElems - group of of elements (edges or faces) to be replicated
5603 \param theNodesNot - group of nodes not to replicated
5604 \param theShape - shape to detect affected elements (element which geometric center
5605 located on or inside shape).
5606 The replicated nodes should be associated to affected elements.
5607 \return TRUE if operation has been completed successfully, FALSE otherwise
5608 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5610 //================================================================================
5613 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5614 SMESH::SMESH_GroupBase_ptr theNodesNot,
5615 GEOM::GEOM_Object_ptr theShape )
5616 throw (SALOME::SALOME_Exception)
5619 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5625 SMESHDS_Mesh* aMeshDS = getMeshDS();
5626 TIDSortedElemSet anElems, aNodes, anAffected;
5627 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5628 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5630 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5631 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5634 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5636 // Update Python script
5637 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5638 << theNodesNot << ", " << theShape << " )";
5641 SMESH_CATCH( SMESH::throwCorbaException );
5645 //================================================================================
5647 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5648 * \param [in] theGrpList - groups
5649 * \param [in] theMeshDS - mesh
5650 * \param [out] theElemSet - set of elements
5651 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5653 //================================================================================
5655 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5656 SMESHDS_Mesh* theMeshDS,
5657 TIDSortedElemSet& theElemSet,
5658 const bool theIsNodeGrp)
5660 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5662 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5663 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5664 : aGrp->GetType() != SMESH::NODE ) )
5666 SMESH::long_array_var anIDs = aGrp->GetIDs();
5667 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5672 //================================================================================
5674 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5675 This method provided for convenience works as DoubleNodes() described above.
5676 \param theElems - list of groups of elements (edges or faces) to be replicated
5677 \param theNodesNot - list of groups of nodes not to replicated
5678 \param theAffectedElems - group of elements to which the replicated nodes
5679 should be associated to.
5680 \return TRUE if operation has been completed successfully, FALSE otherwise
5681 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5683 //================================================================================
5686 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5687 const SMESH::ListOfGroups& theNodesNot,
5688 const SMESH::ListOfGroups& theAffectedElems)
5689 throw (SALOME::SALOME_Exception)
5695 SMESHDS_Mesh* aMeshDS = getMeshDS();
5696 TIDSortedElemSet anElems, aNodes, anAffected;
5697 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5698 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5699 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5701 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5703 // Update Python script
5704 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5705 << &theNodesNot << ", " << &theAffectedElems << " )";
5707 declareMeshModified( /*isReComputeSafe=*/false );
5710 SMESH_CATCH( SMESH::throwCorbaException );
5714 //================================================================================
5716 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5717 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5718 \param theElems - list of groups of elements (edges or faces) to be replicated
5719 \param theNodesNot - list of groups of nodes not to replicated
5720 \param theAffectedElems - group of elements to which the replicated nodes
5721 should be associated to.
5722 * \return a new group with newly created elements
5723 * \sa DoubleNodeElemGroups()
5725 //================================================================================
5727 SMESH::SMESH_Group_ptr
5728 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5729 const SMESH::ListOfGroups& theNodesNot,
5730 const SMESH::ListOfGroups& theAffectedElems)
5731 throw (SALOME::SALOME_Exception)
5734 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
5738 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5739 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5741 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
5743 << theNodesNot << ", "
5744 << theAffectedElems << " )";
5746 return elemGroup._retn();
5749 //================================================================================
5751 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5752 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5753 \param theElems - list of groups of elements (edges or faces) to be replicated
5754 \param theNodesNot - list of groups of nodes not to replicated
5755 \param theAffectedElems - group of elements to which the replicated nodes
5756 should be associated to.
5757 * \return a new group with newly created elements
5758 * \sa DoubleNodeElemGroups()
5760 //================================================================================
5762 SMESH::ListOfGroups*
5763 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
5764 const SMESH::ListOfGroups& theNodesNot,
5765 const SMESH::ListOfGroups& theAffectedElems,
5766 CORBA::Boolean theElemGroupNeeded,
5767 CORBA::Boolean theNodeGroupNeeded)
5768 throw (SALOME::SALOME_Exception)
5771 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5772 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5773 aTwoGroups->length( 2 );
5778 SMESHDS_Mesh* aMeshDS = getMeshDS();
5779 TIDSortedElemSet anElems, aNodes, anAffected;
5780 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5781 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5782 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5784 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5786 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5791 // Create group with newly created elements
5792 CORBA::String_var elemGroupName = theElems[0]->GetName();
5793 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5794 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5796 SMESH::long_array_var anIds = GetLastCreatedElems();
5797 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5798 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5799 aNewElemGroup->Add(anIds);
5801 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5803 SMESH::long_array_var anIds = GetLastCreatedNodes();
5804 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5805 aNewNodeGroup->Add(anIds);
5809 // Update Python script
5812 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5813 else pyDump << aNewElemGroup << ", ";
5814 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5815 else pyDump << aNewNodeGroup << " ] = ";
5817 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
5818 << &theNodesNot << ", "
5819 << &theAffectedElems << ", "
5820 << theElemGroupNeeded << ", "
5821 << theNodeGroupNeeded << " )";
5823 aTwoGroups[0] = aNewElemGroup._retn();
5824 aTwoGroups[1] = aNewNodeGroup._retn();
5825 return aTwoGroups._retn();
5827 SMESH_CATCH( SMESH::throwCorbaException );
5831 //================================================================================
5833 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5834 This method provided for convenience works as DoubleNodes() described above.
5835 \param theElems - list of groups of elements (edges or faces) to be replicated
5836 \param theNodesNot - list of groups of nodes not to replicated
5837 \param theShape - shape to detect affected elements (element which geometric center
5838 located on or inside shape).
5839 The replicated nodes should be associated to affected elements.
5840 \return TRUE if operation has been completed successfully, FALSE otherwise
5841 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5843 //================================================================================
5846 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5847 const SMESH::ListOfGroups& theNodesNot,
5848 GEOM::GEOM_Object_ptr theShape )
5849 throw (SALOME::SALOME_Exception)
5855 SMESHDS_Mesh* aMeshDS = getMeshDS();
5856 TIDSortedElemSet anElems, aNodes;
5857 listOfGroupToSet(theElems, aMeshDS, anElems,false );
5858 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5860 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5861 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5863 // Update Python script
5864 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5865 << &theNodesNot << ", " << theShape << " )";
5867 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5870 SMESH_CATCH( SMESH::throwCorbaException );
5874 //================================================================================
5876 \brief Identify the elements that will be affected by node duplication (actual
5877 duplication is not performed.
5878 This method is the first step of DoubleNodeElemGroupsInRegion.
5879 \param theElems - list of groups of elements (edges or faces) to be replicated
5880 \param theNodesNot - list of groups of nodes not to replicated
5881 \param theShape - shape to detect affected elements (element which geometric center
5882 located on or inside shape).
5883 The replicated nodes should be associated to affected elements.
5884 \return groups of affected elements
5885 \sa DoubleNodeElemGroupsInRegion()
5887 //================================================================================
5888 SMESH::ListOfGroups*
5889 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
5890 const SMESH::ListOfGroups& theNodesNot,
5891 GEOM::GEOM_Object_ptr theShape )
5892 throw (SALOME::SALOME_Exception)
5895 MESSAGE("AffectedElemGroupsInRegion");
5896 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
5897 bool isEdgeGroup = false;
5898 bool isFaceGroup = false;
5899 bool isVolumeGroup = false;
5900 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
5901 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
5902 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
5906 ::SMESH_MeshEditor aMeshEditor(myMesh);
5908 SMESHDS_Mesh* aMeshDS = getMeshDS();
5909 TIDSortedElemSet anElems, aNodes;
5910 listOfGroupToSet(theElems, aMeshDS, anElems, false);
5911 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
5913 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
5914 TIDSortedElemSet anAffected;
5915 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
5918 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5923 int lg = anAffected.size();
5924 MESSAGE("lg="<< lg);
5925 SMESH::long_array_var volumeIds = new SMESH::long_array;
5926 volumeIds->length(lg);
5927 SMESH::long_array_var faceIds = new SMESH::long_array;
5928 faceIds->length(lg);
5929 SMESH::long_array_var edgeIds = new SMESH::long_array;
5930 edgeIds->length(lg);
5935 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
5936 for (; eIt != anAffected.end(); ++eIt)
5938 const SMDS_MeshElement* anElem = *eIt;
5941 int elemId = anElem->GetID();
5942 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
5943 volumeIds[ivol++] = elemId;
5944 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
5945 faceIds[iface++] = elemId;
5946 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
5947 edgeIds[iedge++] = elemId;
5949 volumeIds->length(ivol);
5950 faceIds->length(iface);
5951 edgeIds->length(iedge);
5953 aNewVolumeGroup->Add(volumeIds);
5954 aNewFaceGroup->Add(faceIds);
5955 aNewEdgeGroup->Add(edgeIds);
5956 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
5957 isFaceGroup = (aNewFaceGroup->Size() > 0);
5958 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
5962 if (isEdgeGroup) nbGroups++;
5963 if (isFaceGroup) nbGroups++;
5964 if (isVolumeGroup) nbGroups++;
5965 aListOfGroups->length(nbGroups);
5968 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
5969 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
5970 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
5972 // Update Python script
5975 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
5976 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
5977 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
5979 pyDump << this << ".AffectedElemGroupsInRegion( "
5980 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
5982 return aListOfGroups._retn();
5984 SMESH_CATCH( SMESH::throwCorbaException );
5988 //================================================================================
5990 \brief Generated skin mesh (containing 2D cells) from 3D mesh
5991 The created 2D mesh elements based on nodes of free faces of boundary volumes
5992 \return TRUE if operation has been completed successfully, FALSE otherwise
5994 //================================================================================
5996 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
5997 throw (SALOME::SALOME_Exception)
6002 bool aResult = getEditor().Make2DMeshFrom3D();
6004 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6006 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6009 SMESH_CATCH( SMESH::throwCorbaException );
6013 //================================================================================
6015 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6016 * The list of groups must contain at least two groups. The groups have to be disjoint:
6017 * no common element into two different groups.
6018 * The nodes of the internal faces at the boundaries of the groups are doubled.
6019 * Optionally, the internal faces are replaced by flat elements.
6020 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6021 * The flat elements are stored in groups of volumes.
6022 * These groups are named according to the position of the group in the list:
6023 * 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.
6024 * 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.
6025 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6026 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6027 * \param theDomains - list of groups of volumes
6028 * \param createJointElems - if TRUE, create the elements
6029 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6030 * the boundary between \a theDomains and the rest mesh
6031 * \return TRUE if operation has been completed successfully, FALSE otherwise
6033 //================================================================================
6036 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6037 CORBA::Boolean createJointElems,
6038 CORBA::Boolean onAllBoundaries )
6039 throw (SALOME::SALOME_Exception)
6046 SMESHDS_Mesh* aMeshDS = getMeshDS();
6048 // MESSAGE("theDomains.length = "<<theDomains.length());
6049 if ( theDomains.length() <= 1 && !onAllBoundaries )
6050 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6052 vector<TIDSortedElemSet> domains;
6053 domains.resize( theDomains.length() );
6055 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6057 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6058 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6060 // if ( aGrp->GetType() != SMESH::VOLUME )
6061 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6062 SMESH::long_array_var anIDs = aGrp->GetIDs();
6063 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6067 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6068 // TODO publish the groups of flat elements in study
6070 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6072 // Update Python script
6073 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6074 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6076 SMESH_CATCH( SMESH::throwCorbaException );
6078 myMesh_i->CreateGroupServants(); // publish created groups if any
6083 //================================================================================
6085 * \brief Double nodes on some external faces and create flat elements.
6086 * Flat elements are mainly used by some types of mechanic calculations.
6088 * Each group of the list must be constituted of faces.
6089 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6090 * @param theGroupsOfFaces - list of groups of faces
6091 * @return TRUE if operation has been completed successfully, FALSE otherwise
6093 //================================================================================
6096 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6097 throw (SALOME::SALOME_Exception)
6102 SMESHDS_Mesh* aMeshDS = getMeshDS();
6104 vector<TIDSortedElemSet> faceGroups;
6107 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6109 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6110 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6112 TIDSortedElemSet faceGroup;
6114 faceGroups.push_back(faceGroup);
6115 SMESH::long_array_var anIDs = aGrp->GetIDs();
6116 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6120 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6121 // TODO publish the groups of flat elements in study
6123 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6125 // Update Python script
6126 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6129 SMESH_CATCH( SMESH::throwCorbaException );
6133 //================================================================================
6135 * \brief Identify all the elements around a geom shape, get the faces delimiting
6138 * Build groups of volume to remove, groups of faces to replace on the skin of the
6139 * object, groups of faces to remove inside the object, (idem edges).
6140 * Build ordered list of nodes at the border of each group of faces to replace
6141 * (to be used to build a geom subshape).
6143 //================================================================================
6145 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6146 GEOM::GEOM_Object_ptr theShape,
6147 const char* groupName,
6148 const SMESH::double_array& theNodesCoords,
6149 SMESH::array_of_long_array_out GroupsOfNodes)
6150 throw (SALOME::SALOME_Exception)
6155 std::vector<std::vector<int> > aListOfListOfNodes;
6156 ::SMESH_MeshEditor aMeshEditor( myMesh );
6158 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6159 if ( !theNodeSearcher )
6160 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6162 vector<double> nodesCoords;
6163 for (int i = 0; i < theNodesCoords.length(); i++)
6165 nodesCoords.push_back( theNodesCoords[i] );
6168 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6169 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6170 nodesCoords, aListOfListOfNodes);
6172 GroupsOfNodes = new SMESH::array_of_long_array;
6173 GroupsOfNodes->length( aListOfListOfNodes.size() );
6174 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6175 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6177 vector<int>& aListOfNodes = *llIt;
6178 vector<int>::iterator lIt = aListOfNodes.begin();;
6179 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6180 aGroup.length( aListOfNodes.size() );
6181 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6182 aGroup[ j ] = (*lIt);
6184 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6187 << ", '" << groupName << "', "
6188 << theNodesCoords << " )";
6190 SMESH_CATCH( SMESH::throwCorbaException );
6193 // issue 20749 ===================================================================
6195 * \brief Creates missing boundary elements
6196 * \param elements - elements whose boundary is to be checked
6197 * \param dimension - defines type of boundary elements to create
6198 * \param groupName - a name of group to store created boundary elements in,
6199 * "" means not to create the group
6200 * \param meshName - a name of new mesh to store created boundary elements in,
6201 * "" means not to create the new mesh
6202 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6203 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6204 * boundary elements will be copied into the new mesh
6205 * \param group - returns the create group, if any
6206 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6208 // ================================================================================
6210 SMESH::SMESH_Mesh_ptr
6211 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6212 SMESH::Bnd_Dimension dim,
6213 const char* groupName,
6214 const char* meshName,
6215 CORBA::Boolean toCopyElements,
6216 CORBA::Boolean toCopyExistingBondary,
6217 SMESH::SMESH_Group_out group)
6218 throw (SALOME::SALOME_Exception)
6223 if ( dim > SMESH::BND_1DFROM2D )
6224 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6226 SMESHDS_Mesh* aMeshDS = getMeshDS();
6228 SMESH::SMESH_Mesh_var mesh_var;
6229 SMESH::SMESH_Group_var group_var;
6233 TIDSortedElemSet elements;
6234 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6235 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6239 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6240 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6242 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6244 // group of new boundary elements
6245 SMESH_Group* smesh_group = 0;
6246 if ( strlen(groupName) )
6248 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6249 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6250 smesh_group = group_i->GetSmeshGroup();
6254 getEditor().MakeBoundaryMesh( elements,
6255 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6259 toCopyExistingBondary);
6262 smesh_mesh->GetMeshDS()->Modified();
6265 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6267 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6268 if ( mesh_var->_is_nil() )
6269 pyDump << myMesh_i->_this() << ", ";
6271 pyDump << mesh_var << ", ";
6272 if ( group_var->_is_nil() )
6273 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6275 pyDump << group_var << " = ";
6276 pyDump << this << ".MakeBoundaryMesh( "
6278 << "SMESH." << dimName[int(dim)] << ", "
6279 << "'" << groupName << "', "
6280 << "'" << meshName<< "', "
6281 << toCopyElements << ", "
6282 << toCopyExistingBondary << ")";
6284 group = group_var._retn();
6285 return mesh_var._retn();
6287 SMESH_CATCH( SMESH::throwCorbaException );
6288 return SMESH::SMESH_Mesh::_nil();
6291 //================================================================================
6293 * \brief Creates missing boundary elements
6294 * \param dimension - defines type of boundary elements to create
6295 * \param groupName - a name of group to store all boundary elements in,
6296 * "" means not to create the group
6297 * \param meshName - a name of a new mesh, which is a copy of the initial
6298 * mesh + created boundary elements; "" means not to create the new mesh
6299 * \param toCopyAll - if true, the whole initial mesh will be copied into
6300 * the new mesh else only boundary elements will be copied into the new mesh
6301 * \param groups - optional groups of elements to make boundary around
6302 * \param mesh - returns the mesh where elements were added to
6303 * \param group - returns the created group, if any
6304 * \retval long - number of added boundary elements
6306 //================================================================================
6308 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6309 const char* groupName,
6310 const char* meshName,
6311 CORBA::Boolean toCopyAll,
6312 const SMESH::ListOfIDSources& groups,
6313 SMESH::SMESH_Mesh_out mesh,
6314 SMESH::SMESH_Group_out group)
6315 throw (SALOME::SALOME_Exception)
6320 if ( dim > SMESH::BND_1DFROM2D )
6321 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6323 // separate groups belonging to this and other mesh
6324 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6325 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6326 groupsOfThisMesh->length( groups.length() );
6327 groupsOfOtherMesh->length( groups.length() );
6328 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6329 for ( int i = 0; i < groups.length(); ++i )
6331 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6332 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6333 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6335 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6336 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6337 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6339 groupsOfThisMesh->length( nbGroups );
6340 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6345 if ( nbGroupsOfOtherMesh > 0 )
6347 // process groups belonging to another mesh
6348 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6349 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6350 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6351 groupsOfOtherMesh, mesh, group );
6354 SMESH::SMESH_Mesh_var mesh_var;
6355 SMESH::SMESH_Group_var group_var;
6358 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6359 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6363 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6365 /*toCopyGroups=*/false,
6366 /*toKeepIDs=*/true);
6368 mesh_var = makeMesh(meshName);
6370 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6371 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6374 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6375 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6377 // group of boundary elements
6378 SMESH_Group* smesh_group = 0;
6379 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6380 if ( strlen(groupName) )
6382 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6383 group_var = mesh_i->CreateGroup( groupType, groupName );
6384 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6385 smesh_group = group_i->GetSmeshGroup();
6388 TIDSortedElemSet elements;
6390 if ( groups.length() > 0 )
6392 for ( int i = 0; i < nbGroups; ++i )
6395 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6397 SMESH::Bnd_Dimension bdim =
6398 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6399 nbAdded += getEditor().MakeBoundaryMesh( elements,
6400 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6403 /*toCopyElements=*/false,
6404 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6405 /*toAddExistingBondary=*/true,
6406 /*aroundElements=*/true);
6412 nbAdded += getEditor().MakeBoundaryMesh( elements,
6413 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6416 /*toCopyElements=*/false,
6417 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6418 /*toAddExistingBondary=*/true);
6420 tgtMesh->GetMeshDS()->Modified();
6422 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6424 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6425 pyDump << "nbAdded, ";
6426 if ( mesh_var->_is_nil() )
6427 pyDump << myMesh_i->_this() << ", ";
6429 pyDump << mesh_var << ", ";
6430 if ( group_var->_is_nil() )
6431 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6433 pyDump << group_var << " = ";
6434 pyDump << this << ".MakeBoundaryElements( "
6435 << "SMESH." << dimName[int(dim)] << ", "
6436 << "'" << groupName << "', "
6437 << "'" << meshName<< "', "
6438 << toCopyAll << ", "
6441 mesh = mesh_var._retn();
6442 group = group_var._retn();
6445 SMESH_CATCH( SMESH::throwCorbaException );