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 ) << " ))";
2835 return aGroups._retn();
2837 SMESH_CATCH( SMESH::throwCorbaException );
2841 //================================================================================
2843 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2844 * of given angles along path steps
2845 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2846 * which proceeds the extrusion
2847 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2848 * is used to define the sub-mesh for the path
2850 //================================================================================
2852 SMESH::double_array*
2853 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2854 GEOM::GEOM_Object_ptr thePathShape,
2855 const SMESH::double_array & theAngles)
2857 SMESH::double_array_var aResult = new SMESH::double_array();
2858 int nbAngles = theAngles.length();
2859 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2861 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2862 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2863 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2864 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2865 return aResult._retn();
2866 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2867 if ( nbSteps == nbAngles )
2869 aResult.inout() = theAngles;
2873 aResult->length( nbSteps );
2874 double rAn2St = double( nbAngles ) / double( nbSteps );
2875 double angPrev = 0, angle;
2876 for ( int iSt = 0; iSt < nbSteps; ++iSt )
2878 double angCur = rAn2St * ( iSt+1 );
2879 double angCurFloor = floor( angCur );
2880 double angPrevFloor = floor( angPrev );
2881 if ( angPrevFloor == angCurFloor )
2882 angle = rAn2St * theAngles[ int( angCurFloor ) ];
2885 int iP = int( angPrevFloor );
2886 double angPrevCeil = ceil(angPrev);
2887 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2889 int iC = int( angCurFloor );
2890 if ( iC < nbAngles )
2891 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2893 iP = int( angPrevCeil );
2895 angle += theAngles[ iC ];
2897 aResult[ iSt ] = angle;
2902 // Update Python script
2903 TPythonDump() << "rotAngles = " << theAngles;
2904 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
2905 << thePathMesh << ", "
2906 << thePathShape << ", "
2909 return aResult._retn();
2912 //=======================================================================
2915 //=======================================================================
2917 SMESH::ListOfGroups*
2918 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
2919 const SMESH::AxisStruct & theAxis,
2920 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2921 CORBA::Boolean theCopy,
2923 ::SMESH_Mesh* theTargetMesh)
2924 throw (SALOME::SALOME_Exception)
2929 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2930 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2932 if ( theTargetMesh )
2936 switch ( theMirrorType ) {
2937 case SMESH::SMESH_MeshEditor::POINT:
2938 aTrsf.SetMirror( P );
2940 case SMESH::SMESH_MeshEditor::AXIS:
2941 aTrsf.SetMirror( gp_Ax1( P, V ));
2944 aTrsf.SetMirror( gp_Ax2( P, V ));
2947 TIDSortedElemSet copyElements;
2948 TIDSortedElemSet* workElements = & theElements;
2950 if ( myIsPreviewMode )
2952 TPreviewMesh * tmpMesh = getPreviewMesh();
2953 tmpMesh->Copy( theElements, copyElements);
2954 if ( !theCopy && !theTargetMesh )
2956 TIDSortedElemSet elemsAround, elemsAroundCopy;
2957 getElementsAround( theElements, getMeshDS(), elemsAround );
2958 tmpMesh->Copy( elemsAround, elemsAroundCopy);
2960 workElements = & copyElements;
2961 theMakeGroups = false;
2964 ::SMESH_MeshEditor::PGroupIDs groupIds =
2965 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2967 if ( theCopy && !myIsPreviewMode)
2969 if ( theTargetMesh )
2971 theTargetMesh->GetMeshDS()->Modified();
2975 declareMeshModified( /*isReComputeSafe=*/false );
2978 return theMakeGroups ? getGroups(groupIds.get()) : 0;
2980 SMESH_CATCH( SMESH::throwCorbaException );
2984 //=======================================================================
2987 //=======================================================================
2989 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
2990 const SMESH::AxisStruct & theAxis,
2991 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2992 CORBA::Boolean theCopy)
2993 throw (SALOME::SALOME_Exception)
2995 if ( !myIsPreviewMode ) {
2996 TPythonDump() << this << ".Mirror( "
2997 << theIDsOfElements << ", "
2999 << mirrorTypeName(theMirrorType) << ", "
3002 if ( theIDsOfElements.length() > 0 )
3004 TIDSortedElemSet elements;
3005 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3006 mirror(elements, theAxis, theMirrorType, theCopy, false);
3011 //=======================================================================
3012 //function : MirrorObject
3014 //=======================================================================
3016 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3017 const SMESH::AxisStruct & theAxis,
3018 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3019 CORBA::Boolean theCopy)
3020 throw (SALOME::SALOME_Exception)
3022 if ( !myIsPreviewMode ) {
3023 TPythonDump() << this << ".MirrorObject( "
3024 << theObject << ", "
3026 << mirrorTypeName(theMirrorType) << ", "
3029 TIDSortedElemSet elements;
3031 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3033 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3034 mirror(elements, theAxis, theMirrorType, theCopy, false);
3037 //=======================================================================
3038 //function : MirrorMakeGroups
3040 //=======================================================================
3042 SMESH::ListOfGroups*
3043 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3044 const SMESH::AxisStruct& theMirror,
3045 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3046 throw (SALOME::SALOME_Exception)
3048 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3050 SMESH::ListOfGroups * aGroups = 0;
3051 if ( theIDsOfElements.length() > 0 )
3053 TIDSortedElemSet elements;
3054 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3055 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3057 if (!myIsPreviewMode) {
3058 dumpGroupsList(aPythonDump, aGroups);
3059 aPythonDump << this << ".MirrorMakeGroups( "
3060 << theIDsOfElements << ", "
3061 << theMirror << ", "
3062 << mirrorTypeName(theMirrorType) << " )";
3067 //=======================================================================
3068 //function : MirrorObjectMakeGroups
3070 //=======================================================================
3072 SMESH::ListOfGroups*
3073 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3074 const SMESH::AxisStruct& theMirror,
3075 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3076 throw (SALOME::SALOME_Exception)
3078 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3080 SMESH::ListOfGroups * aGroups = 0;
3081 TIDSortedElemSet elements;
3082 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3083 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3085 if (!myIsPreviewMode)
3087 dumpGroupsList(aPythonDump,aGroups);
3088 aPythonDump << this << ".MirrorObjectMakeGroups( "
3089 << theObject << ", "
3090 << theMirror << ", "
3091 << mirrorTypeName(theMirrorType) << " )";
3096 //=======================================================================
3097 //function : MirrorMakeMesh
3099 //=======================================================================
3101 SMESH::SMESH_Mesh_ptr
3102 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3103 const SMESH::AxisStruct& theMirror,
3104 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3105 CORBA::Boolean theCopyGroups,
3106 const char* theMeshName)
3107 throw (SALOME::SALOME_Exception)
3109 SMESH_Mesh_i* mesh_i;
3110 SMESH::SMESH_Mesh_var mesh;
3111 { // open new scope to dump "MakeMesh" command
3112 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3114 TPythonDump pydump; // to prevent dump at mesh creation
3116 mesh = makeMesh( theMeshName );
3117 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3118 if (mesh_i && theIDsOfElements.length() > 0 )
3120 TIDSortedElemSet elements;
3121 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3122 mirror(elements, theMirror, theMirrorType,
3123 false, theCopyGroups, & mesh_i->GetImpl());
3124 mesh_i->CreateGroupServants();
3127 if (!myIsPreviewMode) {
3128 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3129 << theIDsOfElements << ", "
3130 << theMirror << ", "
3131 << mirrorTypeName(theMirrorType) << ", "
3132 << theCopyGroups << ", '"
3133 << theMeshName << "' )";
3138 if (!myIsPreviewMode && mesh_i)
3139 mesh_i->GetGroups();
3141 return mesh._retn();
3144 //=======================================================================
3145 //function : MirrorObjectMakeMesh
3147 //=======================================================================
3149 SMESH::SMESH_Mesh_ptr
3150 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3151 const SMESH::AxisStruct& theMirror,
3152 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3153 CORBA::Boolean theCopyGroups,
3154 const char* theMeshName)
3155 throw (SALOME::SALOME_Exception)
3157 SMESH_Mesh_i* mesh_i;
3158 SMESH::SMESH_Mesh_var mesh;
3159 { // open new scope to dump "MakeMesh" command
3160 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3162 TPythonDump pydump; // to prevent dump at mesh creation
3164 mesh = makeMesh( theMeshName );
3165 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3166 TIDSortedElemSet elements;
3168 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3170 mirror(elements, theMirror, theMirrorType,
3171 false, theCopyGroups, & mesh_i->GetImpl());
3172 mesh_i->CreateGroupServants();
3174 if (!myIsPreviewMode) {
3175 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3176 << theObject << ", "
3177 << theMirror << ", "
3178 << mirrorTypeName(theMirrorType) << ", "
3179 << theCopyGroups << ", '"
3180 << theMeshName << "' )";
3185 if (!myIsPreviewMode && mesh_i)
3186 mesh_i->GetGroups();
3188 return mesh._retn();
3191 //=======================================================================
3192 //function : translate
3194 //=======================================================================
3196 SMESH::ListOfGroups*
3197 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3198 const SMESH::DirStruct & theVector,
3199 CORBA::Boolean theCopy,
3201 ::SMESH_Mesh* theTargetMesh)
3202 throw (SALOME::SALOME_Exception)
3207 if ( theTargetMesh )
3211 const SMESH::PointStruct * P = &theVector.PS;
3212 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3214 TIDSortedElemSet copyElements;
3215 TIDSortedElemSet* workElements = &theElements;
3217 if ( myIsPreviewMode )
3219 TPreviewMesh * tmpMesh = getPreviewMesh();
3220 tmpMesh->Copy( theElements, copyElements);
3221 if ( !theCopy && !theTargetMesh )
3223 TIDSortedElemSet elemsAround, elemsAroundCopy;
3224 getElementsAround( theElements, getMeshDS(), elemsAround );
3225 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3227 workElements = & copyElements;
3228 theMakeGroups = false;
3231 ::SMESH_MeshEditor::PGroupIDs groupIds =
3232 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3234 if ( theCopy && !myIsPreviewMode )
3236 if ( theTargetMesh )
3238 theTargetMesh->GetMeshDS()->Modified();
3242 declareMeshModified( /*isReComputeSafe=*/false );
3246 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3248 SMESH_CATCH( SMESH::throwCorbaException );
3252 //=======================================================================
3253 //function : Translate
3255 //=======================================================================
3257 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3258 const SMESH::DirStruct & theVector,
3259 CORBA::Boolean theCopy)
3260 throw (SALOME::SALOME_Exception)
3262 if (!myIsPreviewMode) {
3263 TPythonDump() << this << ".Translate( "
3264 << theIDsOfElements << ", "
3265 << theVector << ", "
3268 if (theIDsOfElements.length()) {
3269 TIDSortedElemSet elements;
3270 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3271 translate(elements, theVector, theCopy, false);
3275 //=======================================================================
3276 //function : TranslateObject
3278 //=======================================================================
3280 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3281 const SMESH::DirStruct & theVector,
3282 CORBA::Boolean theCopy)
3283 throw (SALOME::SALOME_Exception)
3285 if (!myIsPreviewMode) {
3286 TPythonDump() << this << ".TranslateObject( "
3287 << theObject << ", "
3288 << theVector << ", "
3291 TIDSortedElemSet elements;
3293 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3295 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3296 translate(elements, theVector, theCopy, false);
3299 //=======================================================================
3300 //function : TranslateMakeGroups
3302 //=======================================================================
3304 SMESH::ListOfGroups*
3305 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3306 const SMESH::DirStruct& theVector)
3307 throw (SALOME::SALOME_Exception)
3309 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3311 SMESH::ListOfGroups * aGroups = 0;
3312 if (theIDsOfElements.length()) {
3313 TIDSortedElemSet elements;
3314 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3315 aGroups = translate(elements,theVector,true,true);
3317 if (!myIsPreviewMode) {
3318 dumpGroupsList(aPythonDump, aGroups);
3319 aPythonDump << this << ".TranslateMakeGroups( "
3320 << theIDsOfElements << ", "
3321 << theVector << " )";
3326 //=======================================================================
3327 //function : TranslateObjectMakeGroups
3329 //=======================================================================
3331 SMESH::ListOfGroups*
3332 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3333 const SMESH::DirStruct& theVector)
3334 throw (SALOME::SALOME_Exception)
3336 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3338 SMESH::ListOfGroups * aGroups = 0;
3339 TIDSortedElemSet elements;
3340 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3341 aGroups = translate(elements, theVector, true, true);
3343 if (!myIsPreviewMode) {
3344 dumpGroupsList(aPythonDump, aGroups);
3345 aPythonDump << this << ".TranslateObjectMakeGroups( "
3346 << theObject << ", "
3347 << theVector << " )";
3352 //=======================================================================
3353 //function : TranslateMakeMesh
3355 //=======================================================================
3357 SMESH::SMESH_Mesh_ptr
3358 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3359 const SMESH::DirStruct& theVector,
3360 CORBA::Boolean theCopyGroups,
3361 const char* theMeshName)
3362 throw (SALOME::SALOME_Exception)
3364 SMESH_Mesh_i* mesh_i;
3365 SMESH::SMESH_Mesh_var mesh;
3367 { // open new scope to dump "MakeMesh" command
3368 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3370 TPythonDump pydump; // to prevent dump at mesh creation
3372 mesh = makeMesh( theMeshName );
3373 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3375 if ( mesh_i && theIDsOfElements.length() )
3377 TIDSortedElemSet elements;
3378 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3379 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3380 mesh_i->CreateGroupServants();
3383 if ( !myIsPreviewMode ) {
3384 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3385 << theIDsOfElements << ", "
3386 << theVector << ", "
3387 << theCopyGroups << ", '"
3388 << theMeshName << "' )";
3393 if (!myIsPreviewMode && mesh_i)
3394 mesh_i->GetGroups();
3396 return mesh._retn();
3399 //=======================================================================
3400 //function : TranslateObjectMakeMesh
3402 //=======================================================================
3404 SMESH::SMESH_Mesh_ptr
3405 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3406 const SMESH::DirStruct& theVector,
3407 CORBA::Boolean theCopyGroups,
3408 const char* theMeshName)
3409 throw (SALOME::SALOME_Exception)
3412 SMESH_Mesh_i* mesh_i;
3413 SMESH::SMESH_Mesh_var mesh;
3414 { // open new scope to dump "MakeMesh" command
3415 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3417 TPythonDump pydump; // to prevent dump at mesh creation
3418 mesh = makeMesh( theMeshName );
3419 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3421 TIDSortedElemSet elements;
3423 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3425 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3426 mesh_i->CreateGroupServants();
3428 if ( !myIsPreviewMode ) {
3429 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3430 << theObject << ", "
3431 << theVector << ", "
3432 << theCopyGroups << ", '"
3433 << theMeshName << "' )";
3438 if (!myIsPreviewMode && mesh_i)
3439 mesh_i->GetGroups();
3441 return mesh._retn();
3443 SMESH_CATCH( SMESH::throwCorbaException );
3447 //=======================================================================
3450 //=======================================================================
3452 SMESH::ListOfGroups*
3453 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3454 const SMESH::AxisStruct & theAxis,
3455 CORBA::Double theAngle,
3456 CORBA::Boolean theCopy,
3458 ::SMESH_Mesh* theTargetMesh)
3459 throw (SALOME::SALOME_Exception)
3464 if ( theTargetMesh )
3467 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3468 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3471 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3473 TIDSortedElemSet copyElements;
3474 TIDSortedElemSet* workElements = &theElements;
3475 if ( myIsPreviewMode ) {
3476 TPreviewMesh * tmpMesh = getPreviewMesh();
3477 tmpMesh->Copy( theElements, copyElements );
3478 if ( !theCopy && !theTargetMesh )
3480 TIDSortedElemSet elemsAround, elemsAroundCopy;
3481 getElementsAround( theElements, getMeshDS(), elemsAround );
3482 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3484 workElements = ©Elements;
3485 theMakeGroups = false;
3488 ::SMESH_MeshEditor::PGroupIDs groupIds =
3489 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3491 if ( theCopy && !myIsPreviewMode)
3493 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3494 else declareMeshModified( /*isReComputeSafe=*/false );
3497 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3499 SMESH_CATCH( SMESH::throwCorbaException );
3503 //=======================================================================
3506 //=======================================================================
3508 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3509 const SMESH::AxisStruct & theAxis,
3510 CORBA::Double theAngle,
3511 CORBA::Boolean theCopy)
3512 throw (SALOME::SALOME_Exception)
3514 if (!myIsPreviewMode) {
3515 TPythonDump() << this << ".Rotate( "
3516 << theIDsOfElements << ", "
3518 << TVar( theAngle ) << ", "
3521 if (theIDsOfElements.length() > 0)
3523 TIDSortedElemSet elements;
3524 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3525 rotate(elements,theAxis,theAngle,theCopy,false);
3529 //=======================================================================
3530 //function : RotateObject
3532 //=======================================================================
3534 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3535 const SMESH::AxisStruct & theAxis,
3536 CORBA::Double theAngle,
3537 CORBA::Boolean theCopy)
3538 throw (SALOME::SALOME_Exception)
3540 if ( !myIsPreviewMode ) {
3541 TPythonDump() << this << ".RotateObject( "
3542 << theObject << ", "
3544 << TVar( theAngle ) << ", "
3547 TIDSortedElemSet elements;
3548 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3549 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3550 rotate(elements,theAxis,theAngle,theCopy,false);
3553 //=======================================================================
3554 //function : RotateMakeGroups
3556 //=======================================================================
3558 SMESH::ListOfGroups*
3559 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3560 const SMESH::AxisStruct& theAxis,
3561 CORBA::Double theAngle)
3562 throw (SALOME::SALOME_Exception)
3564 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3566 SMESH::ListOfGroups * aGroups = 0;
3567 if (theIDsOfElements.length() > 0)
3569 TIDSortedElemSet elements;
3570 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3571 aGroups = rotate(elements,theAxis,theAngle,true,true);
3573 if (!myIsPreviewMode) {
3574 dumpGroupsList(aPythonDump, aGroups);
3575 aPythonDump << this << ".RotateMakeGroups( "
3576 << theIDsOfElements << ", "
3578 << TVar( theAngle ) << " )";
3583 //=======================================================================
3584 //function : RotateObjectMakeGroups
3586 //=======================================================================
3588 SMESH::ListOfGroups*
3589 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3590 const SMESH::AxisStruct& theAxis,
3591 CORBA::Double theAngle)
3592 throw (SALOME::SALOME_Exception)
3594 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3596 SMESH::ListOfGroups * aGroups = 0;
3597 TIDSortedElemSet elements;
3598 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3599 aGroups = rotate(elements, theAxis, theAngle, true, true);
3601 if (!myIsPreviewMode) {
3602 dumpGroupsList(aPythonDump, aGroups);
3603 aPythonDump << this << ".RotateObjectMakeGroups( "
3604 << theObject << ", "
3606 << TVar( theAngle ) << " )";
3611 //=======================================================================
3612 //function : RotateMakeMesh
3614 //=======================================================================
3616 SMESH::SMESH_Mesh_ptr
3617 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3618 const SMESH::AxisStruct& theAxis,
3619 CORBA::Double theAngleInRadians,
3620 CORBA::Boolean theCopyGroups,
3621 const char* theMeshName)
3622 throw (SALOME::SALOME_Exception)
3625 SMESH::SMESH_Mesh_var mesh;
3626 SMESH_Mesh_i* mesh_i;
3628 { // open new scope to dump "MakeMesh" command
3629 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3631 TPythonDump pydump; // to prevent dump at mesh creation
3633 mesh = makeMesh( theMeshName );
3634 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3636 if ( mesh_i && theIDsOfElements.length() > 0 )
3638 TIDSortedElemSet elements;
3639 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3640 rotate(elements, theAxis, theAngleInRadians,
3641 false, theCopyGroups, & mesh_i->GetImpl());
3642 mesh_i->CreateGroupServants();
3644 if ( !myIsPreviewMode ) {
3645 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3646 << theIDsOfElements << ", "
3648 << TVar( theAngleInRadians ) << ", "
3649 << theCopyGroups << ", '"
3650 << theMeshName << "' )";
3655 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3656 mesh_i->GetGroups();
3658 return mesh._retn();
3660 SMESH_CATCH( SMESH::throwCorbaException );
3664 //=======================================================================
3665 //function : RotateObjectMakeMesh
3667 //=======================================================================
3669 SMESH::SMESH_Mesh_ptr
3670 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3671 const SMESH::AxisStruct& theAxis,
3672 CORBA::Double theAngleInRadians,
3673 CORBA::Boolean theCopyGroups,
3674 const char* theMeshName)
3675 throw (SALOME::SALOME_Exception)
3678 SMESH::SMESH_Mesh_var mesh;
3679 SMESH_Mesh_i* mesh_i;
3681 {// open new scope to dump "MakeMesh" command
3682 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3684 TPythonDump pydump; // to prevent dump at mesh creation
3685 mesh = makeMesh( theMeshName );
3686 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3688 TIDSortedElemSet elements;
3690 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3692 rotate(elements, theAxis, theAngleInRadians,
3693 false, theCopyGroups, & mesh_i->GetImpl());
3694 mesh_i->CreateGroupServants();
3696 if ( !myIsPreviewMode ) {
3697 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3698 << theObject << ", "
3700 << TVar( theAngleInRadians ) << ", "
3701 << theCopyGroups << ", '"
3702 << theMeshName << "' )";
3707 if (!myIsPreviewMode && mesh_i)
3708 mesh_i->GetGroups();
3710 return mesh._retn();
3712 SMESH_CATCH( SMESH::throwCorbaException );
3716 //=======================================================================
3719 //=======================================================================
3721 SMESH::ListOfGroups*
3722 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3723 const SMESH::PointStruct& thePoint,
3724 const SMESH::double_array& theScaleFact,
3725 CORBA::Boolean theCopy,
3727 ::SMESH_Mesh* theTargetMesh)
3728 throw (SALOME::SALOME_Exception)
3732 if ( theScaleFact.length() < 1 )
3733 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3734 if ( theScaleFact.length() == 2 )
3735 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3737 if ( theTargetMesh )
3740 TIDSortedElemSet elements;
3741 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3742 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3747 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3748 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3750 double tol = std::numeric_limits<double>::max();
3753 #if OCC_VERSION_LARGE > 0x06070100
3754 // fight against ortagonalization
3755 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3756 // 0, S[1], 0, thePoint.y * (1-S[1]),
3757 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3758 aTrsf.SetTranslation( gp_Vec( thePoint.x * (1-S[0]),
3759 thePoint.y * (1-S[1]),
3760 thePoint.z * (1-S[2])));
3761 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3762 M.SetDiagonal( S[0], S[1], S[2] );
3765 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3766 0, S[1], 0, thePoint.y * (1-S[1]),
3767 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3770 TIDSortedElemSet copyElements;
3771 TIDSortedElemSet* workElements = &elements;
3772 if ( myIsPreviewMode )
3774 TPreviewMesh * tmpMesh = getPreviewMesh();
3775 tmpMesh->Copy( elements, copyElements);
3776 if ( !theCopy && !theTargetMesh )
3778 TIDSortedElemSet elemsAround, elemsAroundCopy;
3779 getElementsAround( elements, getMeshDS(), elemsAround );
3780 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3782 workElements = & copyElements;
3783 theMakeGroups = false;
3786 ::SMESH_MeshEditor::PGroupIDs groupIds =
3787 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3789 if ( theCopy && !myIsPreviewMode )
3791 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3792 else declareMeshModified( /*isReComputeSafe=*/false );
3794 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3796 SMESH_CATCH( SMESH::throwCorbaException );
3800 //=======================================================================
3803 //=======================================================================
3805 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3806 const SMESH::PointStruct& thePoint,
3807 const SMESH::double_array& theScaleFact,
3808 CORBA::Boolean theCopy)
3809 throw (SALOME::SALOME_Exception)
3811 if ( !myIsPreviewMode ) {
3812 TPythonDump() << this << ".Scale( "
3813 << theObject << ", "
3815 << TVar( theScaleFact ) << ", "
3818 scale(theObject, thePoint, theScaleFact, theCopy, false);
3822 //=======================================================================
3823 //function : ScaleMakeGroups
3825 //=======================================================================
3827 SMESH::ListOfGroups*
3828 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3829 const SMESH::PointStruct& thePoint,
3830 const SMESH::double_array& theScaleFact)
3831 throw (SALOME::SALOME_Exception)
3833 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3835 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3836 if (!myIsPreviewMode) {
3837 dumpGroupsList(aPythonDump, aGroups);
3838 aPythonDump << this << ".Scale("
3841 << TVar( theScaleFact ) << ",True,True)";
3847 //=======================================================================
3848 //function : ScaleMakeMesh
3850 //=======================================================================
3852 SMESH::SMESH_Mesh_ptr
3853 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3854 const SMESH::PointStruct& thePoint,
3855 const SMESH::double_array& theScaleFact,
3856 CORBA::Boolean theCopyGroups,
3857 const char* theMeshName)
3858 throw (SALOME::SALOME_Exception)
3860 SMESH_Mesh_i* mesh_i;
3861 SMESH::SMESH_Mesh_var mesh;
3862 { // open new scope to dump "MakeMesh" command
3863 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3865 TPythonDump pydump; // to prevent dump at mesh creation
3866 mesh = makeMesh( theMeshName );
3867 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3871 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3872 mesh_i->CreateGroupServants();
3874 if ( !myIsPreviewMode )
3875 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3876 << theObject << ", "
3878 << TVar( theScaleFact ) << ", "
3879 << theCopyGroups << ", '"
3880 << theMeshName << "' )";
3884 if (!myIsPreviewMode && mesh_i)
3885 mesh_i->GetGroups();
3887 return mesh._retn();
3891 //=======================================================================
3892 //function : FindCoincidentNodes
3894 //=======================================================================
3896 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tolerance,
3897 SMESH::array_of_long_array_out GroupsOfNodes)
3898 throw (SALOME::SALOME_Exception)
3903 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3904 TIDSortedNodeSet nodes; // no input nodes
3905 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3907 GroupsOfNodes = new SMESH::array_of_long_array;
3908 GroupsOfNodes->length( aListOfListOfNodes.size() );
3909 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3910 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3911 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3912 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3913 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3914 aGroup.length( aListOfNodes.size() );
3915 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3916 aGroup[ j ] = (*lIt)->GetID();
3918 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3919 << Tolerance << " )";
3921 SMESH_CATCH( SMESH::throwCorbaException );
3924 //=======================================================================
3925 //function : FindCoincidentNodesOnPart
3927 //=======================================================================
3929 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
3930 CORBA::Double Tolerance,
3931 SMESH::array_of_long_array_out GroupsOfNodes)
3932 throw (SALOME::SALOME_Exception)
3937 TIDSortedNodeSet nodes;
3938 idSourceToNodeSet( theObject, getMeshDS(), nodes );
3940 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3942 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3944 GroupsOfNodes = new SMESH::array_of_long_array;
3945 GroupsOfNodes->length( aListOfListOfNodes.size() );
3946 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3947 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3949 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3950 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3951 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3952 aGroup.length( aListOfNodes.size() );
3953 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3954 aGroup[ j ] = (*lIt)->GetID();
3956 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
3958 << Tolerance << " )";
3960 SMESH_CATCH( SMESH::throwCorbaException );
3963 //================================================================================
3965 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
3966 * ExceptSubMeshOrGroups
3968 //================================================================================
3970 void SMESH_MeshEditor_i::
3971 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
3972 CORBA::Double theTolerance,
3973 SMESH::array_of_long_array_out theGroupsOfNodes,
3974 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups)
3975 throw (SALOME::SALOME_Exception)
3980 TIDSortedNodeSet nodes;
3981 idSourceToNodeSet( theObject, getMeshDS(), nodes );
3983 for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
3985 TIDSortedNodeSet exceptNodes;
3986 idSourceToNodeSet( theExceptSubMeshOrGroups[i], getMeshDS(), exceptNodes );
3987 TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
3988 for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
3989 nodes.erase( *avoidNode );
3991 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3993 getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
3995 theGroupsOfNodes = new SMESH::array_of_long_array;
3996 theGroupsOfNodes->length( aListOfListOfNodes.size() );
3997 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3998 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4000 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4001 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4002 SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
4003 aGroup.length( aListOfNodes.size() );
4004 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4005 aGroup[ j ] = (*lIt)->GetID();
4007 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4009 << theTolerance << ", "
4010 << theExceptSubMeshOrGroups << " )";
4012 SMESH_CATCH( SMESH::throwCorbaException );
4015 //=======================================================================
4016 //function : MergeNodes
4018 //=======================================================================
4020 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
4021 throw (SALOME::SALOME_Exception)
4026 SMESHDS_Mesh* aMesh = getMeshDS();
4028 TPythonDump aTPythonDump;
4029 aTPythonDump << this << ".MergeNodes([";
4030 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4031 for (int i = 0; i < GroupsOfNodes.length(); i++)
4033 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4034 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4035 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4036 for ( int j = 0; j < aNodeGroup.length(); j++ )
4038 CORBA::Long index = aNodeGroup[ j ];
4039 const SMDS_MeshNode * node = aMesh->FindNode(index);
4041 aListOfNodes.push_back( node );
4043 if ( aListOfNodes.size() < 2 )
4044 aListOfListOfNodes.pop_back();
4046 if ( i > 0 ) aTPythonDump << ", ";
4047 aTPythonDump << aNodeGroup;
4049 getEditor().MergeNodes( aListOfListOfNodes );
4051 aTPythonDump << "])";
4053 declareMeshModified( /*isReComputeSafe=*/false );
4055 SMESH_CATCH( SMESH::throwCorbaException );
4058 //=======================================================================
4059 //function : FindEqualElements
4061 //=======================================================================
4063 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4064 SMESH::array_of_long_array_out GroupsOfElementsID)
4065 throw (SALOME::SALOME_Exception)
4070 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4071 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4073 TIDSortedElemSet elems;
4074 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4076 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4077 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4079 GroupsOfElementsID = new SMESH::array_of_long_array;
4080 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4082 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4083 aListOfListOfElementsID.begin();
4084 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4086 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4087 list<int>& listOfIDs = *arraysIt;
4088 aGroup.length( listOfIDs.size() );
4089 list<int>::iterator idIt = listOfIDs.begin();
4090 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4091 aGroup[ k ] = *idIt;
4094 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4098 SMESH_CATCH( SMESH::throwCorbaException );
4101 //=======================================================================
4102 //function : MergeElements
4104 //=======================================================================
4106 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4107 throw (SALOME::SALOME_Exception)
4112 TPythonDump aTPythonDump;
4113 aTPythonDump << this << ".MergeElements( [";
4115 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4117 for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4118 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4119 aListOfListOfElementsID.push_back( list< int >() );
4120 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4121 for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4122 CORBA::Long id = anElemsIDGroup[ j ];
4123 aListOfElemsID.push_back( id );
4125 if ( aListOfElemsID.size() < 2 )
4126 aListOfListOfElementsID.pop_back();
4127 if ( i > 0 ) aTPythonDump << ", ";
4128 aTPythonDump << anElemsIDGroup;
4131 getEditor().MergeElements(aListOfListOfElementsID);
4133 declareMeshModified( /*isReComputeSafe=*/true );
4135 aTPythonDump << "] )";
4137 SMESH_CATCH( SMESH::throwCorbaException );
4140 //=======================================================================
4141 //function : MergeEqualElements
4143 //=======================================================================
4145 void SMESH_MeshEditor_i::MergeEqualElements()
4146 throw (SALOME::SALOME_Exception)
4151 getEditor().MergeEqualElements();
4153 declareMeshModified( /*isReComputeSafe=*/true );
4155 TPythonDump() << this << ".MergeEqualElements()";
4157 SMESH_CATCH( SMESH::throwCorbaException );
4160 //=============================================================================
4162 * Move the node to a given point
4164 //=============================================================================
4166 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4170 throw (SALOME::SALOME_Exception)
4173 initData(/*deleteSearchers=*/false);
4175 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4179 if ( theNodeSearcher )
4180 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4182 if ( myIsPreviewMode ) // make preview data
4184 // in a preview mesh, make edges linked to a node
4185 TPreviewMesh& tmpMesh = *getPreviewMesh();
4186 TIDSortedElemSet linkedNodes;
4187 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4188 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4189 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4190 for ( ; nIt != linkedNodes.end(); ++nIt )
4192 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4193 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4197 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4198 // fill preview data
4200 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4201 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4203 getMeshDS()->MoveNode(node, x, y, z);
4205 if ( !myIsPreviewMode )
4207 // Update Python script
4208 TPythonDump() << "isDone = " << this << ".MoveNode( "
4209 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4210 declareMeshModified( /*isReComputeSafe=*/false );
4213 SMESH_CATCH( SMESH::throwCorbaException );
4218 //================================================================================
4220 * \brief Return ID of node closest to a given point
4222 //================================================================================
4224 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4227 throw (SALOME::SALOME_Exception)
4230 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4232 if ( !theNodeSearcher ) {
4233 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4236 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4237 return node->GetID();
4239 SMESH_CATCH( SMESH::throwCorbaException );
4243 //================================================================================
4245 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4246 * move the node closest to the point to point's location and return ID of the node
4248 //================================================================================
4250 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4253 CORBA::Long theNodeID)
4254 throw (SALOME::SALOME_Exception)
4257 // We keep theNodeSearcher until any mesh modification:
4258 // 1) initData() deletes theNodeSearcher at any edition,
4259 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4261 initData(/*deleteSearchers=*/false);
4263 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4265 int nodeID = theNodeID;
4266 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4267 if ( !node ) // preview moving node
4269 if ( !theNodeSearcher ) {
4270 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4273 node = theNodeSearcher->FindClosestTo( p );
4276 nodeID = node->GetID();
4277 if ( myIsPreviewMode ) // make preview data
4279 // in a preview mesh, make edges linked to a node
4280 TPreviewMesh tmpMesh = *getPreviewMesh();
4281 TIDSortedElemSet linkedNodes;
4282 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4283 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4284 for ( ; nIt != linkedNodes.end(); ++nIt )
4286 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4287 tmpMesh.Copy( &edge );
4290 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4292 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4293 // fill preview data
4295 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4297 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4301 getMeshDS()->MoveNode(node, x, y, z);
4305 if ( !myIsPreviewMode )
4307 TPythonDump() << "nodeID = " << this
4308 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4309 << ", " << nodeID << " )";
4311 declareMeshModified( /*isReComputeSafe=*/false );
4316 SMESH_CATCH( SMESH::throwCorbaException );
4320 //=======================================================================
4322 * Return elements of given type where the given point is IN or ON.
4324 * 'ALL' type means elements of any type excluding nodes
4326 //=======================================================================
4328 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4331 SMESH::ElementType type)
4332 throw (SALOME::SALOME_Exception)
4335 SMESH::long_array_var res = new SMESH::long_array;
4336 vector< const SMDS_MeshElement* > foundElems;
4338 theSearchersDeleter.Set( myMesh );
4339 if ( !theElementSearcher ) {
4340 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4342 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4343 SMDSAbs_ElementType( type ),
4345 res->length( foundElems.size() );
4346 for ( int i = 0; i < foundElems.size(); ++i )
4347 res[i] = foundElems[i]->GetID();
4351 SMESH_CATCH( SMESH::throwCorbaException );
4355 //=======================================================================
4356 //function : FindAmongElementsByPoint
4357 //purpose : Searching among the given elements, return elements of given type
4358 // where the given point is IN or ON.
4359 // 'ALL' type means elements of any type excluding nodes
4360 //=======================================================================
4363 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4367 SMESH::ElementType type)
4368 throw (SALOME::SALOME_Exception)
4371 SMESH::long_array_var res = new SMESH::long_array;
4373 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4374 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4375 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4376 type != types[0] ) // but search of elements of dim > 0
4379 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4380 return FindElementsByPoint( x,y,z, type );
4382 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4384 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4385 if ( !theElementSearcher )
4387 // create a searcher from elementIDs
4388 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4389 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4391 if ( !idSourceToSet( elementIDs, meshDS, elements,
4392 SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4395 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4396 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4398 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4401 vector< const SMDS_MeshElement* > foundElems;
4403 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4404 SMDSAbs_ElementType( type ),
4406 res->length( foundElems.size() );
4407 for ( int i = 0; i < foundElems.size(); ++i )
4408 res[i] = foundElems[i]->GetID();
4412 SMESH_CATCH( SMESH::throwCorbaException );
4416 //=======================================================================
4417 //function : GetPointState
4418 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4419 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4420 //=======================================================================
4422 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4425 throw (SALOME::SALOME_Exception)
4428 theSearchersDeleter.Set( myMesh );
4429 if ( !theElementSearcher ) {
4430 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4432 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4434 SMESH_CATCH( SMESH::throwCorbaException );
4438 //=======================================================================
4439 //function : convError
4441 //=======================================================================
4443 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4445 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4449 RETCASE( SEW_BORDER1_NOT_FOUND );
4450 RETCASE( SEW_BORDER2_NOT_FOUND );
4451 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4452 RETCASE( SEW_BAD_SIDE_NODES );
4453 RETCASE( SEW_VOLUMES_TO_SPLIT );
4454 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4455 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4456 RETCASE( SEW_BAD_SIDE1_NODES );
4457 RETCASE( SEW_BAD_SIDE2_NODES );
4459 return SMESH::SMESH_MeshEditor::SEW_OK;
4462 //=======================================================================
4463 //function : SewFreeBorders
4465 //=======================================================================
4467 SMESH::SMESH_MeshEditor::Sew_Error
4468 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4469 CORBA::Long SecondNodeID1,
4470 CORBA::Long LastNodeID1,
4471 CORBA::Long FirstNodeID2,
4472 CORBA::Long SecondNodeID2,
4473 CORBA::Long LastNodeID2,
4474 CORBA::Boolean CreatePolygons,
4475 CORBA::Boolean CreatePolyedrs)
4476 throw (SALOME::SALOME_Exception)
4481 SMESHDS_Mesh* aMesh = getMeshDS();
4483 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4484 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4485 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4486 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4487 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4488 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4490 if (!aBorderFirstNode ||
4491 !aBorderSecondNode||
4493 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4494 if (!aSide2FirstNode ||
4495 !aSide2SecondNode ||
4497 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4499 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4500 << FirstNodeID1 << ", "
4501 << SecondNodeID1 << ", "
4502 << LastNodeID1 << ", "
4503 << FirstNodeID2 << ", "
4504 << SecondNodeID2 << ", "
4505 << LastNodeID2 << ", "
4506 << CreatePolygons<< ", "
4507 << CreatePolyedrs<< " )";
4509 SMESH::SMESH_MeshEditor::Sew_Error error =
4510 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4521 declareMeshModified( /*isReComputeSafe=*/false );
4524 SMESH_CATCH( SMESH::throwCorbaException );
4525 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4529 //=======================================================================
4530 //function : SewConformFreeBorders
4532 //=======================================================================
4534 SMESH::SMESH_MeshEditor::Sew_Error
4535 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4536 CORBA::Long SecondNodeID1,
4537 CORBA::Long LastNodeID1,
4538 CORBA::Long FirstNodeID2,
4539 CORBA::Long SecondNodeID2)
4540 throw (SALOME::SALOME_Exception)
4545 SMESHDS_Mesh* aMesh = getMeshDS();
4547 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4548 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4549 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4550 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4551 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4552 const SMDS_MeshNode* aSide2ThirdNode = 0;
4554 if (!aBorderFirstNode ||
4555 !aBorderSecondNode||
4557 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4558 if (!aSide2FirstNode ||
4560 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4562 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4563 << FirstNodeID1 << ", "
4564 << SecondNodeID1 << ", "
4565 << LastNodeID1 << ", "
4566 << FirstNodeID2 << ", "
4567 << SecondNodeID2 << " )";
4569 SMESH::SMESH_MeshEditor::Sew_Error error =
4570 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4579 declareMeshModified( /*isReComputeSafe=*/false );
4582 SMESH_CATCH( SMESH::throwCorbaException );
4583 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4587 //=======================================================================
4588 //function : SewBorderToSide
4590 //=======================================================================
4592 SMESH::SMESH_MeshEditor::Sew_Error
4593 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4594 CORBA::Long SecondNodeIDOnFreeBorder,
4595 CORBA::Long LastNodeIDOnFreeBorder,
4596 CORBA::Long FirstNodeIDOnSide,
4597 CORBA::Long LastNodeIDOnSide,
4598 CORBA::Boolean CreatePolygons,
4599 CORBA::Boolean CreatePolyedrs)
4600 throw (SALOME::SALOME_Exception)
4605 SMESHDS_Mesh* aMesh = getMeshDS();
4607 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4608 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4609 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4610 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4611 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4612 const SMDS_MeshNode* aSide2ThirdNode = 0;
4614 if (!aBorderFirstNode ||
4615 !aBorderSecondNode||
4617 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4618 if (!aSide2FirstNode ||
4620 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4622 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4623 << FirstNodeIDOnFreeBorder << ", "
4624 << SecondNodeIDOnFreeBorder << ", "
4625 << LastNodeIDOnFreeBorder << ", "
4626 << FirstNodeIDOnSide << ", "
4627 << LastNodeIDOnSide << ", "
4628 << CreatePolygons << ", "
4629 << CreatePolyedrs << ") ";
4631 SMESH::SMESH_MeshEditor::Sew_Error error =
4632 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4642 declareMeshModified( /*isReComputeSafe=*/false );
4645 SMESH_CATCH( SMESH::throwCorbaException );
4646 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4650 //=======================================================================
4651 //function : SewSideElements
4653 //=======================================================================
4655 SMESH::SMESH_MeshEditor::Sew_Error
4656 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4657 const SMESH::long_array& IDsOfSide2Elements,
4658 CORBA::Long NodeID1OfSide1ToMerge,
4659 CORBA::Long NodeID1OfSide2ToMerge,
4660 CORBA::Long NodeID2OfSide1ToMerge,
4661 CORBA::Long NodeID2OfSide2ToMerge)
4662 throw (SALOME::SALOME_Exception)
4667 SMESHDS_Mesh* aMesh = getMeshDS();
4669 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
4670 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
4671 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4672 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4674 if (!aFirstNode1ToMerge ||
4675 !aFirstNode2ToMerge )
4676 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4677 if (!aSecondNode1ToMerge||
4678 !aSecondNode2ToMerge)
4679 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4681 TIDSortedElemSet aSide1Elems, aSide2Elems;
4682 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4683 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4685 TPythonDump() << "error = " << this << ".SewSideElements( "
4686 << IDsOfSide1Elements << ", "
4687 << IDsOfSide2Elements << ", "
4688 << NodeID1OfSide1ToMerge << ", "
4689 << NodeID1OfSide2ToMerge << ", "
4690 << NodeID2OfSide1ToMerge << ", "
4691 << NodeID2OfSide2ToMerge << ")";
4693 SMESH::SMESH_MeshEditor::Sew_Error error =
4694 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
4697 aSecondNode1ToMerge,
4698 aSecondNode2ToMerge));
4700 declareMeshModified( /*isReComputeSafe=*/false );
4703 SMESH_CATCH( SMESH::throwCorbaException );
4704 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4707 //================================================================================
4709 * \brief Set new nodes for given element
4710 * \param ide - element id
4711 * \param newIDs - new node ids
4712 * \retval CORBA::Boolean - true if result is OK
4714 //================================================================================
4716 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4717 const SMESH::long_array& newIDs)
4718 throw (SALOME::SALOME_Exception)
4723 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
4724 if(!elem) return false;
4726 int nbn = newIDs.length();
4728 vector<const SMDS_MeshNode*> aNodes(nbn);
4731 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
4734 aNodes[nbn1] = aNode;
4737 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4738 << ide << ", " << newIDs << " )";
4740 MESSAGE("ChangeElementNodes");
4741 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4743 declareMeshModified( /*isReComputeSafe=*/ !res );
4747 SMESH_CATCH( SMESH::throwCorbaException );
4751 //=======================================================================
4753 * \brief Makes a part of the mesh quadratic or bi-quadratic
4755 //=======================================================================
4757 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
4758 CORBA::Boolean theToBiQuad,
4759 SMESH::SMESH_IDSource_ptr theObject)
4760 throw (SALOME::SALOME_Exception)
4763 TIDSortedElemSet elems;
4765 if ( !( elemsOK = CORBA::is_nil( theObject )))
4767 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
4768 SMDSAbs_All, /*emptyIfIsMesh=*/true );
4772 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
4773 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4775 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
4776 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
4778 declareMeshModified( /*isReComputeSafe=*/false );
4781 SMESH_CATCH( SMESH::throwCorbaException );
4784 //=======================================================================
4785 //function : ConvertFromQuadratic
4787 //=======================================================================
4789 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4790 throw (SALOME::SALOME_Exception)
4792 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
4793 TPythonDump() << this << ".ConvertFromQuadratic()";
4794 declareMeshModified( /*isReComputeSafe=*/!isDone );
4798 //=======================================================================
4799 //function : ConvertToQuadratic
4801 //=======================================================================
4803 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4804 throw (SALOME::SALOME_Exception)
4806 convertToQuadratic( theForce3d, false );
4807 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
4810 //================================================================================
4812 * \brief Makes a part of the mesh quadratic
4814 //================================================================================
4816 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
4817 SMESH::SMESH_IDSource_ptr theObject)
4818 throw (SALOME::SALOME_Exception)
4820 convertToQuadratic( theForce3d, false, theObject );
4821 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
4824 //================================================================================
4826 * \brief Makes a part of the mesh bi-quadratic
4828 //================================================================================
4830 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
4831 SMESH::SMESH_IDSource_ptr theObject)
4832 throw (SALOME::SALOME_Exception)
4834 convertToQuadratic( theForce3d, true, theObject );
4835 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
4838 //================================================================================
4840 * \brief Makes a part of the mesh linear
4842 //================================================================================
4844 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
4845 throw (SALOME::SALOME_Exception)
4851 TIDSortedElemSet elems;
4852 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
4854 if ( elems.empty() )
4856 ConvertFromQuadratic();
4858 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
4860 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4864 getEditor().ConvertFromQuadratic(elems);
4867 declareMeshModified( /*isReComputeSafe=*/false );
4869 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
4871 SMESH_CATCH( SMESH::throwCorbaException );
4874 //=======================================================================
4875 //function : makeMesh
4876 //purpose : create a named imported mesh
4877 //=======================================================================
4879 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4881 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4882 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4883 SALOMEDS::Study_var study = gen->GetCurrentStudy();
4884 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
4885 gen->SetName( meshSO, theMeshName, "Mesh" );
4886 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4888 return mesh._retn();
4891 //=======================================================================
4892 //function : dumpGroupsList
4894 //=======================================================================
4896 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
4897 const SMESH::ListOfGroups * theGroupList)
4899 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
4900 if ( isDumpGroupList )
4901 theDumpPython << theGroupList << " = ";
4904 //================================================================================
4906 \brief Generates the unique group name.
4907 \param thePrefix name prefix
4910 //================================================================================
4912 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
4914 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4915 set<string> groupNames;
4917 // Get existing group names
4918 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
4919 SMESH::SMESH_GroupBase_var aGroup = groups[i];
4920 if (CORBA::is_nil(aGroup))
4923 CORBA::String_var name = aGroup->GetName();
4924 groupNames.insert( name.in() );
4928 string name = thePrefix;
4931 while (!groupNames.insert(name).second)
4932 name = SMESH_Comment( thePrefix ) << "_" << index++;
4937 //================================================================================
4939 * \brief Prepare SMESH_IDSource for work
4941 //================================================================================
4943 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
4945 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
4947 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
4948 filter->SetMesh( mesh );
4951 //================================================================================
4953 * \brief Retrieve elements of given type from SMESH_IDSource
4955 //================================================================================
4957 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
4958 const SMESHDS_Mesh* theMeshDS,
4959 TIDSortedElemSet& theElemSet,
4960 const SMDSAbs_ElementType theType,
4961 const bool emptyIfIsMesh,
4962 IDSource_Error* error)
4965 if ( error ) *error = IDSource_OK;
4967 if ( CORBA::is_nil( theIDSource ) )
4969 if ( error ) *error = IDSource_INVALID;
4972 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
4974 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
4975 *error = IDSource_EMPTY;
4978 prepareIdSource( theIDSource );
4979 SMESH::long_array_var anIDs = theIDSource->GetIDs();
4980 if ( anIDs->length() == 0 )
4982 if ( error ) *error = IDSource_EMPTY;
4985 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
4986 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
4988 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
4990 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
4994 if ( error ) *error = IDSource_INVALID;
5000 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5001 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5003 if ( error ) *error = IDSource_INVALID;
5010 //================================================================================
5012 * \brief Duplicates given elements, i.e. creates new elements based on the
5013 * same nodes as the given ones.
5014 * \param theElements - container of elements to duplicate.
5015 * \param theGroupName - a name of group to contain the generated elements.
5016 * If a group with such a name already exists, the new elements
5017 * are added to the existng group, else a new group is created.
5018 * If \a theGroupName is empty, new elements are not added
5020 * \return a group where the new elements are added. NULL if theGroupName == "".
5023 //================================================================================
5025 SMESH::SMESH_Group_ptr
5026 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5027 const char* theGroupName)
5028 throw (SALOME::SALOME_Exception)
5030 SMESH::SMESH_Group_var newGroup;
5037 TIDSortedElemSet elems;
5038 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5040 getEditor().DoubleElements( elems );
5042 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5045 SMESH::ElementType type =
5046 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5047 // find existing group
5048 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5049 for ( size_t i = 0; i < groups->length(); ++i )
5050 if ( groups[i]->GetType() == type )
5052 CORBA::String_var name = groups[i]->GetName();
5053 if ( strcmp( name, theGroupName ) == 0 ) {
5054 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5058 // create a new group
5059 if ( newGroup->_is_nil() )
5060 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5062 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5064 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5065 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5066 for ( int i = 1; i <= aSeq.Length(); i++ )
5067 groupDS->SMDSGroup().Add( aSeq(i) );
5072 if ( !newGroup->_is_nil() )
5073 pyDump << newGroup << " = ";
5074 pyDump << this << ".DoubleElements( "
5075 << theElements << ", " << "'" << theGroupName <<"')";
5077 SMESH_CATCH( SMESH::throwCorbaException );
5079 return newGroup._retn();
5082 //================================================================================
5084 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5085 \param theNodes - identifiers of nodes to be doubled
5086 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5087 nodes. If list of element identifiers is empty then nodes are doubled but
5088 they not assigned to elements
5089 \return TRUE if operation has been completed successfully, FALSE otherwise
5090 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5092 //================================================================================
5094 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5095 const SMESH::long_array& theModifiedElems )
5096 throw (SALOME::SALOME_Exception)
5101 list< int > aListOfNodes;
5103 for ( i = 0, n = theNodes.length(); i < n; i++ )
5104 aListOfNodes.push_back( theNodes[ i ] );
5106 list< int > aListOfElems;
5107 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5108 aListOfElems.push_back( theModifiedElems[ i ] );
5110 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5112 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5114 // Update Python script
5115 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5119 SMESH_CATCH( SMESH::throwCorbaException );
5123 //================================================================================
5125 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5126 This method provided for convenience works as DoubleNodes() described above.
5127 \param theNodeId - identifier of node to be doubled.
5128 \param theModifiedElems - identifiers of elements to be updated.
5129 \return TRUE if operation has been completed successfully, FALSE otherwise
5130 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5132 //================================================================================
5134 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5135 const SMESH::long_array& theModifiedElems )
5136 throw (SALOME::SALOME_Exception)
5139 SMESH::long_array_var aNodes = new SMESH::long_array;
5140 aNodes->length( 1 );
5141 aNodes[ 0 ] = theNodeId;
5143 TPythonDump pyDump; // suppress dump by the next line
5145 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5147 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5151 SMESH_CATCH( SMESH::throwCorbaException );
5155 //================================================================================
5157 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5158 This method provided for convenience works as DoubleNodes() described above.
5159 \param theNodes - group of nodes to be doubled.
5160 \param theModifiedElems - group of elements to be updated.
5161 \return TRUE if operation has been completed successfully, FALSE otherwise
5162 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5164 //================================================================================
5166 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5167 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5168 throw (SALOME::SALOME_Exception)
5171 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5174 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5175 SMESH::long_array_var aModifiedElems;
5176 if ( !CORBA::is_nil( theModifiedElems ) )
5177 aModifiedElems = theModifiedElems->GetListOfID();
5180 aModifiedElems = new SMESH::long_array;
5181 aModifiedElems->length( 0 );
5184 TPythonDump pyDump; // suppress dump by the next line
5186 bool done = DoubleNodes( aNodes, aModifiedElems );
5188 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5192 SMESH_CATCH( SMESH::throwCorbaException );
5196 //================================================================================
5198 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5199 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5200 * \param theNodes - group of nodes to be doubled.
5201 * \param theModifiedElems - group of elements to be updated.
5202 * \return a new group with newly created nodes
5203 * \sa DoubleNodeGroup()
5205 //================================================================================
5207 SMESH::SMESH_Group_ptr
5208 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5209 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5210 throw (SALOME::SALOME_Exception)
5213 SMESH::SMESH_Group_var aNewGroup;
5215 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5216 return aNewGroup._retn();
5219 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5220 SMESH::long_array_var aModifiedElems;
5221 if ( !CORBA::is_nil( theModifiedElems ) )
5222 aModifiedElems = theModifiedElems->GetListOfID();
5224 aModifiedElems = new SMESH::long_array;
5225 aModifiedElems->length( 0 );
5228 TPythonDump pyDump; // suppress dump by the next line
5230 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5233 // Create group with newly created nodes
5234 SMESH::long_array_var anIds = GetLastCreatedNodes();
5235 if (anIds->length() > 0) {
5236 string anUnindexedName (theNodes->GetName());
5237 string aNewName = generateGroupName(anUnindexedName + "_double");
5238 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5239 aNewGroup->Add(anIds);
5240 pyDump << aNewGroup << " = ";
5244 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5245 << theModifiedElems << " )";
5247 return aNewGroup._retn();
5249 SMESH_CATCH( SMESH::throwCorbaException );
5253 //================================================================================
5255 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5256 This method provided for convenience works as DoubleNodes() described above.
5257 \param theNodes - list of groups of nodes to be doubled
5258 \param theModifiedElems - list of groups of elements to be updated.
5259 \return TRUE if operation has been completed successfully, FALSE otherwise
5260 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5262 //================================================================================
5264 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5265 const SMESH::ListOfGroups& theModifiedElems )
5266 throw (SALOME::SALOME_Exception)
5271 std::list< int > aNodes;
5273 for ( i = 0, n = theNodes.length(); i < n; i++ )
5275 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5276 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5278 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5279 for ( j = 0, m = aCurr->length(); j < m; j++ )
5280 aNodes.push_back( aCurr[ j ] );
5284 std::list< int > anElems;
5285 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5287 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5288 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5290 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5291 for ( j = 0, m = aCurr->length(); j < m; j++ )
5292 anElems.push_back( aCurr[ j ] );
5296 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5298 declareMeshModified( /*isReComputeSafe=*/false );
5300 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5304 SMESH_CATCH( SMESH::throwCorbaException );
5308 //================================================================================
5310 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5311 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5312 * \param theNodes - group of nodes to be doubled.
5313 * \param theModifiedElems - group of elements to be updated.
5314 * \return a new group with newly created nodes
5315 * \sa DoubleNodeGroups()
5317 //================================================================================
5319 SMESH::SMESH_Group_ptr
5320 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5321 const SMESH::ListOfGroups& theModifiedElems )
5322 throw (SALOME::SALOME_Exception)
5324 SMESH::SMESH_Group_var aNewGroup;
5326 TPythonDump pyDump; // suppress dump by the next line
5328 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5332 // Create group with newly created nodes
5333 SMESH::long_array_var anIds = GetLastCreatedNodes();
5334 if (anIds->length() > 0) {
5335 string anUnindexedName (theNodes[0]->GetName());
5336 string aNewName = generateGroupName(anUnindexedName + "_double");
5337 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5338 aNewGroup->Add(anIds);
5339 pyDump << aNewGroup << " = ";
5343 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5344 << theModifiedElems << " )";
5346 return aNewGroup._retn();
5350 //================================================================================
5352 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5353 \param theElems - the list of elements (edges or faces) to be replicated
5354 The nodes for duplication could be found from these elements
5355 \param theNodesNot - list of nodes to NOT replicate
5356 \param theAffectedElems - the list of elements (cells and edges) to which the
5357 replicated nodes should be associated to.
5358 \return TRUE if operation has been completed successfully, FALSE otherwise
5359 \sa DoubleNodeGroup(), DoubleNodeGroups()
5361 //================================================================================
5363 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5364 const SMESH::long_array& theNodesNot,
5365 const SMESH::long_array& theAffectedElems )
5366 throw (SALOME::SALOME_Exception)
5371 SMESHDS_Mesh* aMeshDS = getMeshDS();
5372 TIDSortedElemSet anElems, aNodes, anAffected;
5373 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5374 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5375 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5377 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5379 // Update Python script
5380 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5381 << theNodesNot << ", " << theAffectedElems << " )";
5383 declareMeshModified( /*isReComputeSafe=*/false );
5386 SMESH_CATCH( SMESH::throwCorbaException );
5390 //================================================================================
5392 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5393 \param theElems - the list of elements (edges or faces) to be replicated
5394 The nodes for duplication could be found from these elements
5395 \param theNodesNot - list of nodes to NOT replicate
5396 \param theShape - shape to detect affected elements (element which geometric center
5397 located on or inside shape).
5398 The replicated nodes should be associated to affected elements.
5399 \return TRUE if operation has been completed successfully, FALSE otherwise
5400 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5402 //================================================================================
5404 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5405 const SMESH::long_array& theNodesNot,
5406 GEOM::GEOM_Object_ptr theShape )
5407 throw (SALOME::SALOME_Exception)
5413 SMESHDS_Mesh* aMeshDS = getMeshDS();
5414 TIDSortedElemSet anElems, aNodes;
5415 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5416 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5418 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5419 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5421 // Update Python script
5422 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5423 << theNodesNot << ", " << theShape << " )";
5425 declareMeshModified( /*isReComputeSafe=*/false );
5428 SMESH_CATCH( SMESH::throwCorbaException );
5432 //================================================================================
5434 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5435 \param theElems - group of of elements (edges or faces) to be replicated
5436 \param theNodesNot - group of nodes not to replicated
5437 \param theAffectedElems - group of elements to which the replicated nodes
5438 should be associated to.
5439 \return TRUE if operation has been completed successfully, FALSE otherwise
5440 \sa DoubleNodes(), DoubleNodeGroups()
5442 //================================================================================
5445 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5446 SMESH::SMESH_GroupBase_ptr theNodesNot,
5447 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5448 throw (SALOME::SALOME_Exception)
5451 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5457 SMESHDS_Mesh* aMeshDS = getMeshDS();
5458 TIDSortedElemSet anElems, aNodes, anAffected;
5459 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5460 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5461 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5463 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5465 // Update Python script
5466 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5467 << theNodesNot << ", " << theAffectedElems << " )";
5469 declareMeshModified( /*isReComputeSafe=*/false );
5472 SMESH_CATCH( SMESH::throwCorbaException );
5476 //================================================================================
5478 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5479 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5480 * \param theElems - group of of elements (edges or faces) to be replicated
5481 * \param theNodesNot - group of nodes not to replicated
5482 * \param theAffectedElems - group of elements to which the replicated nodes
5483 * should be associated to.
5484 * \return a new group with newly created elements
5485 * \sa DoubleNodeElemGroup()
5487 //================================================================================
5489 SMESH::SMESH_Group_ptr
5490 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5491 SMESH::SMESH_GroupBase_ptr theNodesNot,
5492 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5493 throw (SALOME::SALOME_Exception)
5496 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5500 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5501 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5503 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5505 << theNodesNot << ", "
5506 << theAffectedElems << " )";
5508 return elemGroup._retn();
5511 //================================================================================
5513 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5514 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5515 * \param theElems - group of of elements (edges or faces) to be replicated
5516 * \param theNodesNot - group of nodes not to replicated
5517 * \param theAffectedElems - group of elements to which the replicated nodes
5518 * should be associated to.
5519 * \return a new group with newly created elements
5520 * \sa DoubleNodeElemGroup()
5522 //================================================================================
5524 SMESH::ListOfGroups*
5525 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5526 SMESH::SMESH_GroupBase_ptr theNodesNot,
5527 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5528 CORBA::Boolean theElemGroupNeeded,
5529 CORBA::Boolean theNodeGroupNeeded)
5530 throw (SALOME::SALOME_Exception)
5533 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5534 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5535 aTwoGroups->length( 2 );
5537 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5538 return aTwoGroups._retn();
5543 SMESHDS_Mesh* aMeshDS = getMeshDS();
5544 TIDSortedElemSet anElems, aNodes, anAffected;
5545 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5546 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5547 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5550 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5552 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5558 // Create group with newly created elements
5559 CORBA::String_var elemGroupName = theElems->GetName();
5560 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5561 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5563 SMESH::long_array_var anIds = GetLastCreatedElems();
5564 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5565 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5566 aNewElemGroup->Add(anIds);
5568 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5570 SMESH::long_array_var anIds = GetLastCreatedNodes();
5571 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5572 aNewNodeGroup->Add(anIds);
5576 // Update Python script
5579 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5580 else pyDump << aNewElemGroup << ", ";
5581 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5582 else pyDump << aNewNodeGroup << " ] = ";
5584 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5585 << theNodesNot << ", "
5586 << theAffectedElems << ", "
5587 << theElemGroupNeeded << ", "
5588 << theNodeGroupNeeded <<" )";
5590 aTwoGroups[0] = aNewElemGroup._retn();
5591 aTwoGroups[1] = aNewNodeGroup._retn();
5592 return aTwoGroups._retn();
5594 SMESH_CATCH( SMESH::throwCorbaException );
5598 //================================================================================
5600 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5601 \param theElems - group of of elements (edges or faces) to be replicated
5602 \param theNodesNot - group of nodes not to replicated
5603 \param theShape - shape to detect affected elements (element which geometric center
5604 located on or inside shape).
5605 The replicated nodes should be associated to affected elements.
5606 \return TRUE if operation has been completed successfully, FALSE otherwise
5607 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5609 //================================================================================
5612 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5613 SMESH::SMESH_GroupBase_ptr theNodesNot,
5614 GEOM::GEOM_Object_ptr theShape )
5615 throw (SALOME::SALOME_Exception)
5618 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5624 SMESHDS_Mesh* aMeshDS = getMeshDS();
5625 TIDSortedElemSet anElems, aNodes, anAffected;
5626 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5627 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5629 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5630 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5633 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5635 // Update Python script
5636 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5637 << theNodesNot << ", " << theShape << " )";
5640 SMESH_CATCH( SMESH::throwCorbaException );
5644 //================================================================================
5646 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5647 * \param [in] theGrpList - groups
5648 * \param [in] theMeshDS - mesh
5649 * \param [out] theElemSet - set of elements
5650 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5652 //================================================================================
5654 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5655 SMESHDS_Mesh* theMeshDS,
5656 TIDSortedElemSet& theElemSet,
5657 const bool theIsNodeGrp)
5659 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5661 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5662 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5663 : aGrp->GetType() != SMESH::NODE ) )
5665 SMESH::long_array_var anIDs = aGrp->GetIDs();
5666 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5671 //================================================================================
5673 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5674 This method provided for convenience works as DoubleNodes() described above.
5675 \param theElems - list of groups of elements (edges or faces) to be replicated
5676 \param theNodesNot - list of groups of nodes not to replicated
5677 \param theAffectedElems - group of elements to which the replicated nodes
5678 should be associated to.
5679 \return TRUE if operation has been completed successfully, FALSE otherwise
5680 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5682 //================================================================================
5685 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5686 const SMESH::ListOfGroups& theNodesNot,
5687 const SMESH::ListOfGroups& theAffectedElems)
5688 throw (SALOME::SALOME_Exception)
5694 SMESHDS_Mesh* aMeshDS = getMeshDS();
5695 TIDSortedElemSet anElems, aNodes, anAffected;
5696 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5697 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5698 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5700 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5702 // Update Python script
5703 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5704 << &theNodesNot << ", " << &theAffectedElems << " )";
5706 declareMeshModified( /*isReComputeSafe=*/false );
5709 SMESH_CATCH( SMESH::throwCorbaException );
5713 //================================================================================
5715 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5716 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5717 \param theElems - list of groups of elements (edges or faces) to be replicated
5718 \param theNodesNot - list of groups of nodes not to replicated
5719 \param theAffectedElems - group of elements to which the replicated nodes
5720 should be associated to.
5721 * \return a new group with newly created elements
5722 * \sa DoubleNodeElemGroups()
5724 //================================================================================
5726 SMESH::SMESH_Group_ptr
5727 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5728 const SMESH::ListOfGroups& theNodesNot,
5729 const SMESH::ListOfGroups& theAffectedElems)
5730 throw (SALOME::SALOME_Exception)
5733 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
5737 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5738 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5740 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
5742 << theNodesNot << ", "
5743 << theAffectedElems << " )";
5745 return elemGroup._retn();
5748 //================================================================================
5750 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5751 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5752 \param theElems - list of groups of elements (edges or faces) to be replicated
5753 \param theNodesNot - list of groups of nodes not to replicated
5754 \param theAffectedElems - group of elements to which the replicated nodes
5755 should be associated to.
5756 * \return a new group with newly created elements
5757 * \sa DoubleNodeElemGroups()
5759 //================================================================================
5761 SMESH::ListOfGroups*
5762 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
5763 const SMESH::ListOfGroups& theNodesNot,
5764 const SMESH::ListOfGroups& theAffectedElems,
5765 CORBA::Boolean theElemGroupNeeded,
5766 CORBA::Boolean theNodeGroupNeeded)
5767 throw (SALOME::SALOME_Exception)
5770 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5771 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5772 aTwoGroups->length( 2 );
5777 SMESHDS_Mesh* aMeshDS = getMeshDS();
5778 TIDSortedElemSet anElems, aNodes, anAffected;
5779 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5780 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5781 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5783 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5785 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5790 // Create group with newly created elements
5791 CORBA::String_var elemGroupName = theElems[0]->GetName();
5792 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5793 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5795 SMESH::long_array_var anIds = GetLastCreatedElems();
5796 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5797 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5798 aNewElemGroup->Add(anIds);
5800 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5802 SMESH::long_array_var anIds = GetLastCreatedNodes();
5803 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5804 aNewNodeGroup->Add(anIds);
5808 // Update Python script
5811 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5812 else pyDump << aNewElemGroup << ", ";
5813 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5814 else pyDump << aNewNodeGroup << " ] = ";
5816 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
5817 << &theNodesNot << ", "
5818 << &theAffectedElems << ", "
5819 << theElemGroupNeeded << ", "
5820 << theNodeGroupNeeded << " )";
5822 aTwoGroups[0] = aNewElemGroup._retn();
5823 aTwoGroups[1] = aNewNodeGroup._retn();
5824 return aTwoGroups._retn();
5826 SMESH_CATCH( SMESH::throwCorbaException );
5830 //================================================================================
5832 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5833 This method provided for convenience works as DoubleNodes() described above.
5834 \param theElems - list of groups of elements (edges or faces) to be replicated
5835 \param theNodesNot - list of groups of nodes not to replicated
5836 \param theShape - shape to detect affected elements (element which geometric center
5837 located on or inside shape).
5838 The replicated nodes should be associated to affected elements.
5839 \return TRUE if operation has been completed successfully, FALSE otherwise
5840 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5842 //================================================================================
5845 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5846 const SMESH::ListOfGroups& theNodesNot,
5847 GEOM::GEOM_Object_ptr theShape )
5848 throw (SALOME::SALOME_Exception)
5854 SMESHDS_Mesh* aMeshDS = getMeshDS();
5855 TIDSortedElemSet anElems, aNodes;
5856 listOfGroupToSet(theElems, aMeshDS, anElems,false );
5857 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5859 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5860 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5862 // Update Python script
5863 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5864 << &theNodesNot << ", " << theShape << " )";
5866 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5869 SMESH_CATCH( SMESH::throwCorbaException );
5873 //================================================================================
5875 \brief Identify the elements that will be affected by node duplication (actual
5876 duplication is not performed.
5877 This method is the first step of DoubleNodeElemGroupsInRegion.
5878 \param theElems - list of groups of elements (edges or faces) to be replicated
5879 \param theNodesNot - list of groups of nodes not to replicated
5880 \param theShape - shape to detect affected elements (element which geometric center
5881 located on or inside shape).
5882 The replicated nodes should be associated to affected elements.
5883 \return groups of affected elements
5884 \sa DoubleNodeElemGroupsInRegion()
5886 //================================================================================
5887 SMESH::ListOfGroups*
5888 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
5889 const SMESH::ListOfGroups& theNodesNot,
5890 GEOM::GEOM_Object_ptr theShape )
5891 throw (SALOME::SALOME_Exception)
5894 MESSAGE("AffectedElemGroupsInRegion");
5895 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
5896 bool isEdgeGroup = false;
5897 bool isFaceGroup = false;
5898 bool isVolumeGroup = false;
5899 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
5900 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
5901 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
5905 ::SMESH_MeshEditor aMeshEditor(myMesh);
5907 SMESHDS_Mesh* aMeshDS = getMeshDS();
5908 TIDSortedElemSet anElems, aNodes;
5909 listOfGroupToSet(theElems, aMeshDS, anElems, false);
5910 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
5912 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
5913 TIDSortedElemSet anAffected;
5914 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
5917 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5922 int lg = anAffected.size();
5923 MESSAGE("lg="<< lg);
5924 SMESH::long_array_var volumeIds = new SMESH::long_array;
5925 volumeIds->length(lg);
5926 SMESH::long_array_var faceIds = new SMESH::long_array;
5927 faceIds->length(lg);
5928 SMESH::long_array_var edgeIds = new SMESH::long_array;
5929 edgeIds->length(lg);
5934 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
5935 for (; eIt != anAffected.end(); ++eIt)
5937 const SMDS_MeshElement* anElem = *eIt;
5940 int elemId = anElem->GetID();
5941 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
5942 volumeIds[ivol++] = elemId;
5943 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
5944 faceIds[iface++] = elemId;
5945 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
5946 edgeIds[iedge++] = elemId;
5948 volumeIds->length(ivol);
5949 faceIds->length(iface);
5950 edgeIds->length(iedge);
5952 aNewVolumeGroup->Add(volumeIds);
5953 aNewFaceGroup->Add(faceIds);
5954 aNewEdgeGroup->Add(edgeIds);
5955 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
5956 isFaceGroup = (aNewFaceGroup->Size() > 0);
5957 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
5961 if (isEdgeGroup) nbGroups++;
5962 if (isFaceGroup) nbGroups++;
5963 if (isVolumeGroup) nbGroups++;
5964 aListOfGroups->length(nbGroups);
5967 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
5968 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
5969 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
5971 // Update Python script
5974 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
5975 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
5976 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
5978 pyDump << this << ".AffectedElemGroupsInRegion( "
5979 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
5981 return aListOfGroups._retn();
5983 SMESH_CATCH( SMESH::throwCorbaException );
5987 //================================================================================
5989 \brief Generated skin mesh (containing 2D cells) from 3D mesh
5990 The created 2D mesh elements based on nodes of free faces of boundary volumes
5991 \return TRUE if operation has been completed successfully, FALSE otherwise
5993 //================================================================================
5995 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
5996 throw (SALOME::SALOME_Exception)
6001 bool aResult = getEditor().Make2DMeshFrom3D();
6003 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6005 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6008 SMESH_CATCH( SMESH::throwCorbaException );
6012 //================================================================================
6014 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6015 * The list of groups must contain at least two groups. The groups have to be disjoint:
6016 * no common element into two different groups.
6017 * The nodes of the internal faces at the boundaries of the groups are doubled.
6018 * Optionally, the internal faces are replaced by flat elements.
6019 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6020 * The flat elements are stored in groups of volumes.
6021 * These groups are named according to the position of the group in the list:
6022 * 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.
6023 * 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.
6024 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6025 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6026 * \param theDomains - list of groups of volumes
6027 * \param createJointElems - if TRUE, create the elements
6028 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6029 * the boundary between \a theDomains and the rest mesh
6030 * \return TRUE if operation has been completed successfully, FALSE otherwise
6032 //================================================================================
6035 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6036 CORBA::Boolean createJointElems,
6037 CORBA::Boolean onAllBoundaries )
6038 throw (SALOME::SALOME_Exception)
6045 SMESHDS_Mesh* aMeshDS = getMeshDS();
6047 // MESSAGE("theDomains.length = "<<theDomains.length());
6048 if ( theDomains.length() <= 1 && !onAllBoundaries )
6049 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6051 vector<TIDSortedElemSet> domains;
6052 domains.resize( theDomains.length() );
6054 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6056 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6057 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6059 // if ( aGrp->GetType() != SMESH::VOLUME )
6060 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6061 SMESH::long_array_var anIDs = aGrp->GetIDs();
6062 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6066 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6067 // TODO publish the groups of flat elements in study
6069 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6071 // Update Python script
6072 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6073 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6075 SMESH_CATCH( SMESH::throwCorbaException );
6077 myMesh_i->CreateGroupServants(); // publish created groups if any
6082 //================================================================================
6084 * \brief Double nodes on some external faces and create flat elements.
6085 * Flat elements are mainly used by some types of mechanic calculations.
6087 * Each group of the list must be constituted of faces.
6088 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6089 * @param theGroupsOfFaces - list of groups of faces
6090 * @return TRUE if operation has been completed successfully, FALSE otherwise
6092 //================================================================================
6095 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6096 throw (SALOME::SALOME_Exception)
6101 SMESHDS_Mesh* aMeshDS = getMeshDS();
6103 vector<TIDSortedElemSet> faceGroups;
6106 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6108 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6109 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6111 TIDSortedElemSet faceGroup;
6113 faceGroups.push_back(faceGroup);
6114 SMESH::long_array_var anIDs = aGrp->GetIDs();
6115 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6119 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6120 // TODO publish the groups of flat elements in study
6122 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6124 // Update Python script
6125 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6128 SMESH_CATCH( SMESH::throwCorbaException );
6132 //================================================================================
6134 * \brief Identify all the elements around a geom shape, get the faces delimiting
6137 * Build groups of volume to remove, groups of faces to replace on the skin of the
6138 * object, groups of faces to remove inside the object, (idem edges).
6139 * Build ordered list of nodes at the border of each group of faces to replace
6140 * (to be used to build a geom subshape).
6142 //================================================================================
6144 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6145 GEOM::GEOM_Object_ptr theShape,
6146 const char* groupName,
6147 const SMESH::double_array& theNodesCoords,
6148 SMESH::array_of_long_array_out GroupsOfNodes)
6149 throw (SALOME::SALOME_Exception)
6154 std::vector<std::vector<int> > aListOfListOfNodes;
6155 ::SMESH_MeshEditor aMeshEditor( myMesh );
6157 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6158 if ( !theNodeSearcher )
6159 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6161 vector<double> nodesCoords;
6162 for (int i = 0; i < theNodesCoords.length(); i++)
6164 nodesCoords.push_back( theNodesCoords[i] );
6167 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6168 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6169 nodesCoords, aListOfListOfNodes);
6171 GroupsOfNodes = new SMESH::array_of_long_array;
6172 GroupsOfNodes->length( aListOfListOfNodes.size() );
6173 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6174 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6176 vector<int>& aListOfNodes = *llIt;
6177 vector<int>::iterator lIt = aListOfNodes.begin();;
6178 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6179 aGroup.length( aListOfNodes.size() );
6180 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6181 aGroup[ j ] = (*lIt);
6183 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6186 << ", '" << groupName << "', "
6187 << theNodesCoords << " )";
6189 SMESH_CATCH( SMESH::throwCorbaException );
6192 // issue 20749 ===================================================================
6194 * \brief Creates missing boundary elements
6195 * \param elements - elements whose boundary is to be checked
6196 * \param dimension - defines type of boundary elements to create
6197 * \param groupName - a name of group to store created boundary elements in,
6198 * "" means not to create the group
6199 * \param meshName - a name of new mesh to store created boundary elements in,
6200 * "" means not to create the new mesh
6201 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6202 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6203 * boundary elements will be copied into the new mesh
6204 * \param group - returns the create group, if any
6205 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6207 // ================================================================================
6209 SMESH::SMESH_Mesh_ptr
6210 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6211 SMESH::Bnd_Dimension dim,
6212 const char* groupName,
6213 const char* meshName,
6214 CORBA::Boolean toCopyElements,
6215 CORBA::Boolean toCopyExistingBondary,
6216 SMESH::SMESH_Group_out group)
6217 throw (SALOME::SALOME_Exception)
6222 if ( dim > SMESH::BND_1DFROM2D )
6223 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6225 SMESHDS_Mesh* aMeshDS = getMeshDS();
6227 SMESH::SMESH_Mesh_var mesh_var;
6228 SMESH::SMESH_Group_var group_var;
6232 TIDSortedElemSet elements;
6233 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6234 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6238 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6239 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6241 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6243 // group of new boundary elements
6244 SMESH_Group* smesh_group = 0;
6245 if ( strlen(groupName) )
6247 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6248 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6249 smesh_group = group_i->GetSmeshGroup();
6253 getEditor().MakeBoundaryMesh( elements,
6254 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6258 toCopyExistingBondary);
6261 smesh_mesh->GetMeshDS()->Modified();
6264 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6266 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6267 if ( mesh_var->_is_nil() )
6268 pyDump << myMesh_i->_this() << ", ";
6270 pyDump << mesh_var << ", ";
6271 if ( group_var->_is_nil() )
6272 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6274 pyDump << group_var << " = ";
6275 pyDump << this << ".MakeBoundaryMesh( "
6277 << "SMESH." << dimName[int(dim)] << ", "
6278 << "'" << groupName << "', "
6279 << "'" << meshName<< "', "
6280 << toCopyElements << ", "
6281 << toCopyExistingBondary << ")";
6283 group = group_var._retn();
6284 return mesh_var._retn();
6286 SMESH_CATCH( SMESH::throwCorbaException );
6287 return SMESH::SMESH_Mesh::_nil();
6290 //================================================================================
6292 * \brief Creates missing boundary elements
6293 * \param dimension - defines type of boundary elements to create
6294 * \param groupName - a name of group to store all boundary elements in,
6295 * "" means not to create the group
6296 * \param meshName - a name of a new mesh, which is a copy of the initial
6297 * mesh + created boundary elements; "" means not to create the new mesh
6298 * \param toCopyAll - if true, the whole initial mesh will be copied into
6299 * the new mesh else only boundary elements will be copied into the new mesh
6300 * \param groups - optional groups of elements to make boundary around
6301 * \param mesh - returns the mesh where elements were added to
6302 * \param group - returns the created group, if any
6303 * \retval long - number of added boundary elements
6305 //================================================================================
6307 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6308 const char* groupName,
6309 const char* meshName,
6310 CORBA::Boolean toCopyAll,
6311 const SMESH::ListOfIDSources& groups,
6312 SMESH::SMESH_Mesh_out mesh,
6313 SMESH::SMESH_Group_out group)
6314 throw (SALOME::SALOME_Exception)
6319 if ( dim > SMESH::BND_1DFROM2D )
6320 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6322 // separate groups belonging to this and other mesh
6323 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6324 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6325 groupsOfThisMesh->length( groups.length() );
6326 groupsOfOtherMesh->length( groups.length() );
6327 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6328 for ( int i = 0; i < groups.length(); ++i )
6330 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6331 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6332 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6334 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6335 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6336 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6338 groupsOfThisMesh->length( nbGroups );
6339 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6344 if ( nbGroupsOfOtherMesh > 0 )
6346 // process groups belonging to another mesh
6347 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6348 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6349 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6350 groupsOfOtherMesh, mesh, group );
6353 SMESH::SMESH_Mesh_var mesh_var;
6354 SMESH::SMESH_Group_var group_var;
6357 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6358 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6362 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6364 /*toCopyGroups=*/false,
6365 /*toKeepIDs=*/true);
6367 mesh_var = makeMesh(meshName);
6369 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6370 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6373 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6374 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6376 // group of boundary elements
6377 SMESH_Group* smesh_group = 0;
6378 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6379 if ( strlen(groupName) )
6381 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6382 group_var = mesh_i->CreateGroup( groupType, groupName );
6383 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6384 smesh_group = group_i->GetSmeshGroup();
6387 TIDSortedElemSet elements;
6389 if ( groups.length() > 0 )
6391 for ( int i = 0; i < nbGroups; ++i )
6394 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6396 SMESH::Bnd_Dimension bdim =
6397 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6398 nbAdded += getEditor().MakeBoundaryMesh( elements,
6399 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6402 /*toCopyElements=*/false,
6403 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6404 /*toAddExistingBondary=*/true,
6405 /*aroundElements=*/true);
6411 nbAdded += getEditor().MakeBoundaryMesh( elements,
6412 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6415 /*toCopyElements=*/false,
6416 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6417 /*toAddExistingBondary=*/true);
6419 tgtMesh->GetMeshDS()->Modified();
6421 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6423 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6424 pyDump << "nbAdded, ";
6425 if ( mesh_var->_is_nil() )
6426 pyDump << myMesh_i->_this() << ", ";
6428 pyDump << mesh_var << ", ";
6429 if ( group_var->_is_nil() )
6430 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6432 pyDump << group_var << " = ";
6433 pyDump << this << ".MakeBoundaryElements( "
6434 << "SMESH." << dimName[int(dim)] << ", "
6435 << "'" << groupName << "', "
6436 << "'" << meshName<< "', "
6437 << toCopyAll << ", "
6440 mesh = mesh_var._retn();
6441 group = group_var._retn();
6444 SMESH_CATCH( SMESH::throwCorbaException );