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 Returns the mesh
446 //================================================================================
448 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
450 return myMesh_i->_this();
453 //================================================================================
455 * \brief Clear members
457 //================================================================================
459 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
461 if ( myIsPreviewMode ) {
462 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
465 if ( deleteSearchers )
466 TSearchersDeleter::Delete();
468 getEditor().GetError().reset();
469 getEditor().ClearLastCreated();
472 //================================================================================
474 * \brief Increment mesh modif time and optionally record that the performed
475 * modification may influence futher mesh re-compute.
476 * \param [in] isReComputeSafe - true if the modification does not infulence
477 * futher mesh re-compute
479 //================================================================================
481 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
483 myMesh->GetMeshDS()->Modified();
484 if ( !isReComputeSafe )
485 myMesh->SetIsModified( true );
488 //================================================================================
490 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
491 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
493 //================================================================================
495 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
497 if ( myIsPreviewMode && !myPreviewEditor ) {
498 if ( !myPreviewMesh ) getPreviewMesh();
499 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
501 return myIsPreviewMode ? *myPreviewEditor : myEditor;
504 //================================================================================
506 * \brief Initialize and return myPreviewMesh
507 * \param previewElements - type of elements to show in preview
509 * WARNING: call it once par a method!
511 //================================================================================
513 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
515 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
517 delete myPreviewEditor;
519 delete myPreviewMesh;
520 myPreviewMesh = new TPreviewMesh( previewElements );
522 myPreviewMesh->Clear();
523 return myPreviewMesh;
526 //================================================================================
528 * Return data of mesh edition preview
530 //================================================================================
532 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
533 throw (SALOME::SALOME_Exception)
536 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
538 if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
540 list<int> aNodesConnectivity;
541 typedef map<int, int> TNodesMap;
544 SMESHDS_Mesh* aMeshDS;
545 std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
547 aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
548 aMeshDS = aMeshPartDS.get();
551 aMeshDS = getEditor().GetMeshDS();
553 myPreviewData = new SMESH::MeshPreviewStruct();
554 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
557 SMDSAbs_ElementType previewType = SMDSAbs_All;
559 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
560 previewType = aPreviewMesh->myPreviewType;
561 switch ( previewType ) {
562 case SMDSAbs_Edge : break;
563 case SMDSAbs_Face : break;
564 case SMDSAbs_Volume: break;
566 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
570 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
572 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
574 while ( itMeshElems->more() ) {
575 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
576 SMDS_NodeIteratorPtr itElemNodes = aMeshElem->nodeIterator();
577 while ( itElemNodes->more() ) {
578 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
579 int aNodeID = aMeshNode->GetID();
580 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
581 if ( anIter == nodesMap.end() ) {
582 // filling the nodes coordinates
583 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
584 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
585 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
586 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
589 aNodesConnectivity.push_back(anIter->second);
592 // filling the elements types
593 SMDSAbs_ElementType aType = aMeshElem->GetType();
594 bool isPoly = aMeshElem->IsPoly();
595 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
596 myPreviewData->elementTypes[i].isPoly = isPoly;
597 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
600 myPreviewData->nodesXYZ.length( j );
602 // filling the elements connectivities
603 list<int>::iterator aConnIter = aNodesConnectivity.begin();
604 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
605 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
606 myPreviewData->elementConnectivities[i] = *aConnIter;
608 return myPreviewData._retn();
610 SMESH_CATCH( SMESH::throwCorbaException );
614 //================================================================================
616 * \brief Returns list of it's IDs of created nodes
617 * \retval SMESH::long_array* - list of node ID
619 //================================================================================
621 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
622 throw (SALOME::SALOME_Exception)
625 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
627 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
628 myLastCreatedNodes->length( aSeq.Length() );
629 for (int i = 1; i <= aSeq.Length(); i++)
630 myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID();
632 return myLastCreatedNodes._retn();
633 SMESH_CATCH( SMESH::throwCorbaException );
637 //================================================================================
639 * \brief Returns list of it's IDs of created elements
640 * \retval SMESH::long_array* - list of elements' ID
642 //================================================================================
644 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
645 throw (SALOME::SALOME_Exception)
648 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
650 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
651 myLastCreatedElems->length( aSeq.Length() );
652 for ( int i = 1; i <= aSeq.Length(); i++ )
653 myLastCreatedElems[i-1] = aSeq.Value(i)->GetID();
655 return myLastCreatedElems._retn();
656 SMESH_CATCH( SMESH::throwCorbaException );
660 //=======================================================================
661 //function : ClearLastCreated
662 //purpose : Clears sequences of last created elements and nodes
663 //=======================================================================
665 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
668 getEditor().ClearLastCreated();
669 SMESH_CATCH( SMESH::throwCorbaException );
672 //=======================================================================
674 * Returns description of an error/warning occured during the last operation
675 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
677 //=======================================================================
679 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
680 throw (SALOME::SALOME_Exception)
683 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
684 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
685 if ( errIn && !errIn->IsOK() )
687 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
688 errOut->comment = errIn->myComment.c_str();
689 errOut->subShapeID = -1;
690 errOut->hasBadMesh = !errIn->myBadElements.empty();
695 errOut->subShapeID = -1;
696 errOut->hasBadMesh = false;
699 return errOut._retn();
700 SMESH_CATCH( SMESH::throwCorbaException );
704 //=======================================================================
705 //function : MakeIDSource
706 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
707 // Call UnRegister() as you fininsh using it!!
708 //=======================================================================
710 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
711 public virtual SALOME::GenericObj_i
713 SMESH::long_array _ids;
714 SMESH::ElementType _type;
715 SMESH::SMESH_Mesh_ptr _mesh;
716 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
717 SMESH::long_array* GetMeshInfo() { return 0; }
718 SMESH::long_array* GetNbElementsByType()
720 SMESH::long_array_var aRes = new SMESH::long_array();
721 aRes->length(SMESH::NB_ELEMENT_TYPES);
722 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
723 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
726 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
727 bool IsMeshInfoCorrect() { return true; }
728 SMESH::array_of_ElementType* GetTypes()
730 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
731 if ( _ids.length() > 0 ) {
735 return types._retn();
737 SALOMEDS::TMPFile* GetVtkUgStream()
739 SALOMEDS::TMPFile_var SeqFile;
740 return SeqFile._retn();
744 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
745 SMESH::ElementType type)
747 _IDSource* idSrc = new _IDSource;
748 idSrc->_mesh = myMesh_i->_this();
751 if ( type == SMESH::ALL && ids.length() > 0 )
752 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
754 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
756 return anIDSourceVar._retn();
759 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
761 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
764 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
767 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
769 nbIds = (int) tmpIdSource->_ids.length();
770 return & tmpIdSource->_ids[0];
776 // void SMESH_MeshEditor_i::deleteAuxIDSources()
778 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
779 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
781 // myAuxIDSources.clear();
784 //=============================================================================
788 //=============================================================================
791 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
792 throw (SALOME::SALOME_Exception)
799 for (int i = 0; i < IDsOfElements.length(); i++)
800 IdList.push_back( IDsOfElements[i] );
802 // Update Python script
803 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
806 bool ret = getEditor().Remove( IdList, false );
808 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
811 SMESH_CATCH( SMESH::throwCorbaException );
815 //=============================================================================
819 //=============================================================================
821 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
822 throw (SALOME::SALOME_Exception)
828 for (int i = 0; i < IDsOfNodes.length(); i++)
829 IdList.push_back( IDsOfNodes[i] );
831 // Update Python script
832 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
834 bool ret = getEditor().Remove( IdList, true );
836 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
839 SMESH_CATCH( SMESH::throwCorbaException );
843 //=============================================================================
847 //=============================================================================
849 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
850 throw (SALOME::SALOME_Exception)
855 // Update Python script
856 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
858 // Create filter to find all orphan nodes
859 SMESH::Controls::Filter::TIdSequence seq;
860 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
861 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
863 // remove orphan nodes (if there are any)
865 for ( int i = 0; i < seq.size(); i++ )
866 IdList.push_back( seq[i] );
868 int nbNodesBefore = myMesh->NbNodes();
869 getEditor().Remove( IdList, true );
870 int nbNodesAfter = myMesh->NbNodes();
872 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
873 return nbNodesBefore - nbNodesAfter;
875 SMESH_CATCH( SMESH::throwCorbaException );
879 //=============================================================================
883 //=============================================================================
885 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
886 throw (SALOME::SALOME_Exception)
891 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
893 // Update Python script
894 TPythonDump() << "nodeID = " << this << ".AddNode( "
895 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
897 declareMeshModified( /*isReComputeSafe=*/false );
900 SMESH_CATCH( SMESH::throwCorbaException );
904 //=============================================================================
906 * Create 0D element on the given node.
908 //=============================================================================
910 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
911 throw (SALOME::SALOME_Exception)
916 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
917 SMDS_MeshElement* elem = getMeshDS()->Add0DElement(aNode);
919 // Update Python script
920 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
922 declareMeshModified( /*isReComputeSafe=*/false );
924 return elem ? elem->GetID() : 0;
926 SMESH_CATCH( SMESH::throwCorbaException );
930 //=============================================================================
932 * Create a ball element on the given node.
934 //=============================================================================
936 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
937 throw (SALOME::SALOME_Exception)
942 if ( diameter < std::numeric_limits<double>::min() )
943 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
945 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
946 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
948 // Update Python script
949 TPythonDump() << "ballElem = "
950 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
952 declareMeshModified( /*isReComputeSafe=*/false );
953 return elem ? elem->GetID() : 0;
955 SMESH_CATCH( SMESH::throwCorbaException );
959 //=============================================================================
961 * Create an edge, either linear and quadratic (this is determed
962 * by number of given nodes, two or three)
964 //=============================================================================
966 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
967 throw (SALOME::SALOME_Exception)
972 int NbNodes = IDsOfNodes.length();
973 SMDS_MeshElement* elem = 0;
976 CORBA::Long index1 = IDsOfNodes[0];
977 CORBA::Long index2 = IDsOfNodes[1];
978 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
979 getMeshDS()->FindNode(index2));
981 // Update Python script
982 TPythonDump() << "edge = " << this << ".AddEdge([ "
983 << index1 << ", " << index2 <<" ])";
986 CORBA::Long n1 = IDsOfNodes[0];
987 CORBA::Long n2 = IDsOfNodes[1];
988 CORBA::Long n12 = IDsOfNodes[2];
989 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
990 getMeshDS()->FindNode(n2),
991 getMeshDS()->FindNode(n12));
992 // Update Python script
993 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
994 <<n1<<", "<<n2<<", "<<n12<<" ])";
997 declareMeshModified( /*isReComputeSafe=*/false );
998 return elem ? elem->GetID() : 0;
1000 SMESH_CATCH( SMESH::throwCorbaException );
1004 //=============================================================================
1008 //=============================================================================
1010 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1011 throw (SALOME::SALOME_Exception)
1016 int NbNodes = IDsOfNodes.length();
1022 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1023 for (int i = 0; i < NbNodes; i++)
1024 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1026 SMDS_MeshElement* elem = 0;
1028 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1029 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1030 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1031 nodes[4], nodes[5]); break;
1032 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1033 nodes[4], nodes[5], nodes[6]); break;
1034 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1035 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1036 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1037 nodes[4], nodes[5], nodes[6], nodes[7],
1039 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1042 // Update Python script
1043 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1045 declareMeshModified( /*isReComputeSafe=*/false );
1047 return elem ? elem->GetID() : 0;
1049 SMESH_CATCH( SMESH::throwCorbaException );
1053 //=============================================================================
1057 //=============================================================================
1058 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1059 throw (SALOME::SALOME_Exception)
1064 int NbNodes = IDsOfNodes.length();
1065 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1066 for (int i = 0; i < NbNodes; i++)
1067 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1069 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1071 // Update Python script
1072 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1074 declareMeshModified( /*isReComputeSafe=*/false );
1075 return elem ? elem->GetID() : 0;
1077 SMESH_CATCH( SMESH::throwCorbaException );
1081 //=============================================================================
1083 * Create volume, either linear and quadratic (this is determed
1084 * by number of given nodes)
1086 //=============================================================================
1088 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1089 throw (SALOME::SALOME_Exception)
1094 int NbNodes = IDsOfNodes.length();
1095 vector< const SMDS_MeshNode*> n(NbNodes);
1096 for(int i=0;i<NbNodes;i++)
1097 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1099 SMDS_MeshElement* elem = 0;
1102 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1103 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1104 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1105 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1106 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1107 n[6],n[7],n[8],n[9]);
1109 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1110 n[6],n[7],n[8],n[9],n[10],n[11]);
1112 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1113 n[7],n[8],n[9],n[10],n[11],n[12]);
1115 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1116 n[9],n[10],n[11],n[12],n[13],n[14]);
1118 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1119 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1120 n[15],n[16],n[17],n[18],n[19]);
1122 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1123 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1124 n[15],n[16],n[17],n[18],n[19],
1125 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1129 // Update Python script
1130 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1132 declareMeshModified( /*isReComputeSafe=*/false );
1133 return elem ? elem->GetID() : 0;
1135 SMESH_CATCH( SMESH::throwCorbaException );
1139 //=============================================================================
1141 * AddPolyhedralVolume
1143 //=============================================================================
1144 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1145 const SMESH::long_array & Quantities)
1146 throw (SALOME::SALOME_Exception)
1151 int NbNodes = IDsOfNodes.length();
1152 std::vector<const SMDS_MeshNode*> n (NbNodes);
1153 for (int i = 0; i < NbNodes; i++)
1155 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1156 if (!aNode) return 0;
1160 int NbFaces = Quantities.length();
1161 std::vector<int> q (NbFaces);
1162 for (int j = 0; j < NbFaces; j++)
1163 q[j] = Quantities[j];
1165 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1167 // Update Python script
1168 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1169 << IDsOfNodes << ", " << Quantities << " )";
1171 declareMeshModified( /*isReComputeSafe=*/false );
1172 return elem ? elem->GetID() : 0;
1174 SMESH_CATCH( SMESH::throwCorbaException );
1178 //=============================================================================
1180 * AddPolyhedralVolumeByFaces
1182 //=============================================================================
1184 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1185 throw (SALOME::SALOME_Exception)
1190 int NbFaces = IdsOfFaces.length();
1191 std::vector<const SMDS_MeshNode*> poly_nodes;
1192 std::vector<int> quantities (NbFaces);
1194 for (int i = 0; i < NbFaces; i++) {
1195 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1196 quantities[i] = aFace->NbNodes();
1198 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1199 while (It->more()) {
1200 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1204 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1206 // Update Python script
1207 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1208 << IdsOfFaces << " )";
1210 declareMeshModified( /*isReComputeSafe=*/false );
1211 return elem ? elem->GetID() : 0;
1213 SMESH_CATCH( SMESH::throwCorbaException );
1217 //=============================================================================
1219 // \brief Create 0D elements on all nodes of the given object except those
1220 // nodes on which a 0D element already exists.
1221 // \param theObject object on whose nodes 0D elements will be created.
1222 // \param theGroupName optional name of a group to add 0D elements created
1223 // and/or found on nodes of \a theObject.
1224 // \return an object (a new group or a temporary SMESH_IDSource) holding
1225 // ids of new and/or found 0D elements.
1227 //=============================================================================
1229 SMESH::SMESH_IDSource_ptr
1230 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1231 const char* theGroupName)
1232 throw (SALOME::SALOME_Exception)
1237 SMESH::SMESH_IDSource_var result;
1240 TIDSortedElemSet elements, elems0D;
1241 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1242 getEditor().Create0DElementsOnAllNodes( elements, elems0D );
1244 SMESH::long_array_var newElems = new SMESH::long_array;
1245 newElems->length( elems0D.size() );
1246 TIDSortedElemSet::iterator eIt = elems0D.begin();
1247 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1248 newElems[ i ] = (*eIt)->GetID();
1250 SMESH::SMESH_GroupBase_var groupToFill;
1251 if ( theGroupName && strlen( theGroupName ))
1253 // Get existing group named theGroupName
1254 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1255 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1256 SMESH::SMESH_GroupBase_var group = groups[i];
1257 if ( !group->_is_nil() ) {
1258 CORBA::String_var name = group->GetName();
1259 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1260 groupToFill = group;
1265 if ( groupToFill->_is_nil() )
1266 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1267 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1268 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1271 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1273 group_i->Add( newElems );
1274 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1275 pyDump << groupToFill;
1279 result = MakeIDSource( newElems, SMESH::ELEM0D );
1280 pyDump << "elem0DIDs";
1283 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1284 << theObject << ", '" << theGroupName << "' )";
1286 return result._retn();
1288 SMESH_CATCH( SMESH::throwCorbaException );
1292 //=============================================================================
1294 * \brief Bind a node to a vertex
1295 * \param NodeID - node ID
1296 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1297 * \retval boolean - false if NodeID or VertexID is invalid
1299 //=============================================================================
1301 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1302 throw (SALOME::SALOME_Exception)
1306 SMESHDS_Mesh * mesh = getMeshDS();
1307 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1309 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1311 if ( mesh->MaxShapeIndex() < VertexID )
1312 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1314 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1315 if ( shape.ShapeType() != TopAbs_VERTEX )
1316 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1318 mesh->SetNodeOnVertex( node, VertexID );
1320 myMesh->SetIsModified( true );
1322 SMESH_CATCH( SMESH::throwCorbaException );
1325 //=============================================================================
1327 * \brief Store node position on an edge
1328 * \param NodeID - node ID
1329 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1330 * \param paramOnEdge - parameter on edge where the node is located
1331 * \retval boolean - false if any parameter is invalid
1333 //=============================================================================
1335 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1336 CORBA::Double paramOnEdge)
1337 throw (SALOME::SALOME_Exception)
1341 SMESHDS_Mesh * mesh = getMeshDS();
1342 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1344 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1346 if ( mesh->MaxShapeIndex() < EdgeID )
1347 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1349 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1350 if ( shape.ShapeType() != TopAbs_EDGE )
1351 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1354 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1355 if ( paramOnEdge < f || paramOnEdge > l )
1356 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1358 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1360 myMesh->SetIsModified( true );
1362 SMESH_CATCH( SMESH::throwCorbaException );
1365 //=============================================================================
1367 * \brief Store node position on a face
1368 * \param NodeID - node ID
1369 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1370 * \param u - U parameter on face where the node is located
1371 * \param v - V parameter on face where the node is located
1372 * \retval boolean - false if any parameter is invalid
1374 //=============================================================================
1376 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1377 CORBA::Double u, CORBA::Double v)
1378 throw (SALOME::SALOME_Exception)
1381 SMESHDS_Mesh * mesh = getMeshDS();
1382 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1384 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1386 if ( mesh->MaxShapeIndex() < FaceID )
1387 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1389 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1390 if ( shape.ShapeType() != TopAbs_FACE )
1391 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1393 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1394 bool isOut = ( u < surf.FirstUParameter() ||
1395 u > surf.LastUParameter() ||
1396 v < surf.FirstVParameter() ||
1397 v > surf.LastVParameter() );
1401 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1402 << " u( " << surf.FirstUParameter()
1403 << "," << surf.LastUParameter()
1404 << ") v( " << surf.FirstVParameter()
1405 << "," << surf.LastVParameter() << ")" );
1407 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1410 mesh->SetNodeOnFace( node, FaceID, u, v );
1411 myMesh->SetIsModified( true );
1413 SMESH_CATCH( SMESH::throwCorbaException );
1416 //=============================================================================
1418 * \brief Bind a node to a solid
1419 * \param NodeID - node ID
1420 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1421 * \retval boolean - false if NodeID or SolidID is invalid
1423 //=============================================================================
1425 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1426 throw (SALOME::SALOME_Exception)
1429 SMESHDS_Mesh * mesh = getMeshDS();
1430 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1432 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1434 if ( mesh->MaxShapeIndex() < SolidID )
1435 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1437 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1438 if ( shape.ShapeType() != TopAbs_SOLID &&
1439 shape.ShapeType() != TopAbs_SHELL)
1440 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1442 mesh->SetNodeInVolume( node, SolidID );
1444 SMESH_CATCH( SMESH::throwCorbaException );
1447 //=============================================================================
1449 * \brief Bind an element to a shape
1450 * \param ElementID - element ID
1451 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1453 //=============================================================================
1455 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1456 CORBA::Long ShapeID)
1457 throw (SALOME::SALOME_Exception)
1460 SMESHDS_Mesh * mesh = getMeshDS();
1461 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1463 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1465 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1466 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1468 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1469 if ( shape.ShapeType() != TopAbs_EDGE &&
1470 shape.ShapeType() != TopAbs_FACE &&
1471 shape.ShapeType() != TopAbs_SOLID &&
1472 shape.ShapeType() != TopAbs_SHELL )
1473 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1475 mesh->SetMeshElementOnShape( elem, ShapeID );
1477 myMesh->SetIsModified( true );
1479 SMESH_CATCH( SMESH::throwCorbaException );
1482 //=============================================================================
1486 //=============================================================================
1488 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1489 CORBA::Long NodeID2)
1490 throw (SALOME::SALOME_Exception)
1495 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1496 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1500 // Update Python script
1501 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1502 << NodeID1 << ", " << NodeID2 << " )";
1504 int ret = getEditor().InverseDiag ( n1, n2 );
1506 declareMeshModified( /*isReComputeSafe=*/false );
1509 SMESH_CATCH( SMESH::throwCorbaException );
1513 //=============================================================================
1517 //=============================================================================
1519 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1520 CORBA::Long NodeID2)
1521 throw (SALOME::SALOME_Exception)
1526 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1527 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1531 // Update Python script
1532 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1533 << NodeID1 << ", " << NodeID2 << " )";
1536 bool stat = getEditor().DeleteDiag ( n1, n2 );
1538 declareMeshModified( /*isReComputeSafe=*/!stat );
1542 SMESH_CATCH( SMESH::throwCorbaException );
1546 //=============================================================================
1550 //=============================================================================
1552 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1553 throw (SALOME::SALOME_Exception)
1558 for (int i = 0; i < IDsOfElements.length(); i++)
1560 CORBA::Long index = IDsOfElements[i];
1561 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1563 getEditor().Reorient( elem );
1565 // Update Python script
1566 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1568 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1571 SMESH_CATCH( SMESH::throwCorbaException );
1575 //=============================================================================
1579 //=============================================================================
1581 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1582 throw (SALOME::SALOME_Exception)
1587 TPythonDump aTPythonDump; // suppress dump in Reorient()
1589 prepareIdSource( theObject );
1591 SMESH::long_array_var anElementsId = theObject->GetIDs();
1592 CORBA::Boolean isDone = Reorient(anElementsId);
1594 // Update Python script
1595 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1597 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1600 SMESH_CATCH( SMESH::throwCorbaException );
1604 //=======================================================================
1605 //function : Reorient2D
1606 //purpose : Reorient faces contained in \a the2Dgroup.
1607 // the2Dgroup - the mesh or its part to reorient
1608 // theDirection - desired direction of normal of \a theFace
1609 // theFace - ID of face whose orientation is checked.
1610 // It can be < 1 then \a thePoint is used to find a face.
1611 // thePoint - is used to find a face if \a theFace < 1.
1612 // return number of reoriented elements.
1613 //=======================================================================
1615 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1616 const SMESH::DirStruct& theDirection,
1617 CORBA::Long theFace,
1618 const SMESH::PointStruct& thePoint)
1619 throw (SALOME::SALOME_Exception)
1622 initData(/*deleteSearchers=*/false);
1624 TIDSortedElemSet elements;
1625 IDSource_Error error;
1626 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1627 if ( error == IDSource_EMPTY )
1629 if ( error == IDSource_INVALID )
1630 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1633 const SMDS_MeshElement* face = 0;
1636 face = getMeshDS()->FindElement( theFace );
1638 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1639 if ( face->GetType() != SMDSAbs_Face )
1640 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1644 // create theElementSearcher if needed
1645 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1646 if ( !theElementSearcher )
1648 if ( elements.empty() ) // search in the whole mesh
1650 if ( myMesh->NbFaces() == 0 )
1651 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1653 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1657 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1658 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1660 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1664 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1665 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1668 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1669 if ( !elements.empty() && !elements.count( face ))
1670 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1673 const SMESH::PointStruct * P = &theDirection.PS;
1674 gp_Vec dirVec( P->x, P->y, P->z );
1675 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1676 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1678 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1681 declareMeshModified( /*isReComputeSafe=*/false );
1683 TPythonDump() << this << ".Reorient2D( "
1684 << the2Dgroup << ", "
1685 << theDirection << ", "
1687 << thePoint << " )";
1691 SMESH_CATCH( SMESH::throwCorbaException );
1695 //=======================================================================
1696 //function : Reorient2DBy3D
1697 //purpose : Reorient faces basing on orientation of adjacent volumes.
1698 //=======================================================================
1700 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1701 SMESH::SMESH_IDSource_ptr volumeGroup,
1702 CORBA::Boolean outsideNormal)
1703 throw (SALOME::SALOME_Exception)
1708 TIDSortedElemSet volumes;
1709 IDSource_Error volsError;
1710 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1713 for ( size_t i = 0; i < faceGroups.length(); ++i )
1715 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1717 TIDSortedElemSet faces;
1718 IDSource_Error error;
1719 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1720 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1721 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1722 if ( error == IDSource_OK && volsError != IDSource_OK )
1723 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1725 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1727 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1732 declareMeshModified( /*isReComputeSafe=*/false );
1734 TPythonDump() << this << ".Reorient2DBy3D( "
1735 << faceGroups << ", "
1736 << volumeGroup << ", "
1737 << outsideNormal << " )";
1741 SMESH_CATCH( SMESH::throwCorbaException );
1745 //=============================================================================
1747 * \brief Fuse neighbour triangles into quadrangles.
1749 //=============================================================================
1751 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1752 SMESH::NumericalFunctor_ptr Criterion,
1753 CORBA::Double MaxAngle)
1754 throw (SALOME::SALOME_Exception)
1759 SMESHDS_Mesh* aMesh = getMeshDS();
1760 TIDSortedElemSet faces,copyFaces;
1761 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1762 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1763 TIDSortedElemSet* workElements = & faces;
1765 if ( myIsPreviewMode ) {
1766 SMDSAbs_ElementType select = SMDSAbs_Face;
1767 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1768 workElements = & copyFaces;
1771 SMESH::NumericalFunctor_i* aNumericalFunctor =
1772 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1773 SMESH::Controls::NumericalFunctorPtr aCrit;
1774 if ( !aNumericalFunctor )
1775 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1777 aCrit = aNumericalFunctor->GetNumericalFunctor();
1779 if ( !myIsPreviewMode ) {
1780 // Update Python script
1781 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1782 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1785 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1787 declareMeshModified( /*isReComputeSafe=*/!stat );
1790 SMESH_CATCH( SMESH::throwCorbaException );
1794 //=============================================================================
1796 * \brief Fuse neighbour triangles into quadrangles.
1798 //=============================================================================
1800 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1801 SMESH::NumericalFunctor_ptr Criterion,
1802 CORBA::Double MaxAngle)
1803 throw (SALOME::SALOME_Exception)
1808 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1810 prepareIdSource( theObject );
1811 SMESH::long_array_var anElementsId = theObject->GetIDs();
1812 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1814 if ( !myIsPreviewMode ) {
1815 SMESH::NumericalFunctor_i* aNumericalFunctor =
1816 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1818 // Update Python script
1819 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1820 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1825 SMESH_CATCH( SMESH::throwCorbaException );
1829 //=============================================================================
1831 * \brief Split quadrangles into triangles.
1833 //=============================================================================
1835 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1836 SMESH::NumericalFunctor_ptr Criterion)
1837 throw (SALOME::SALOME_Exception)
1842 SMESHDS_Mesh* aMesh = getMeshDS();
1843 TIDSortedElemSet faces;
1844 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1846 SMESH::NumericalFunctor_i* aNumericalFunctor =
1847 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1848 SMESH::Controls::NumericalFunctorPtr aCrit;
1849 if ( !aNumericalFunctor )
1850 aCrit.reset( new SMESH::Controls::AspectRatio() );
1852 aCrit = aNumericalFunctor->GetNumericalFunctor();
1855 // Update Python script
1856 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1858 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1860 declareMeshModified( /*isReComputeSafe=*/false );
1863 SMESH_CATCH( SMESH::throwCorbaException );
1867 //=============================================================================
1869 * \brief Split quadrangles into triangles.
1871 //=============================================================================
1873 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1874 SMESH::NumericalFunctor_ptr Criterion)
1875 throw (SALOME::SALOME_Exception)
1880 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1882 prepareIdSource( theObject );
1883 SMESH::long_array_var anElementsId = theObject->GetIDs();
1884 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1886 SMESH::NumericalFunctor_i* aNumericalFunctor =
1887 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1889 // Update Python script
1890 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1892 declareMeshModified( /*isReComputeSafe=*/false );
1895 SMESH_CATCH( SMESH::throwCorbaException );
1899 //================================================================================
1901 * \brief Split each of quadrangles into 4 triangles.
1902 * \param [in] theObject - theQuads Container of quadrangles to split.
1904 //================================================================================
1906 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1907 throw (SALOME::SALOME_Exception)
1912 TIDSortedElemSet faces;
1913 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1915 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1917 getEditor().QuadTo4Tri( faces );
1918 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1920 SMESH_CATCH( SMESH::throwCorbaException );
1923 //=============================================================================
1925 * \brief Split quadrangles into triangles.
1927 //=============================================================================
1929 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1930 CORBA::Boolean Diag13)
1931 throw (SALOME::SALOME_Exception)
1936 SMESHDS_Mesh* aMesh = getMeshDS();
1937 TIDSortedElemSet faces;
1938 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1940 // Update Python script
1941 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1942 << IDsOfElements << ", " << Diag13 << " )";
1944 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1946 declareMeshModified( /*isReComputeSafe=*/ !stat );
1949 SMESH_CATCH( SMESH::throwCorbaException );
1953 //=============================================================================
1955 * \brief Split quadrangles into triangles.
1957 //=============================================================================
1959 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1960 CORBA::Boolean Diag13)
1961 throw (SALOME::SALOME_Exception)
1966 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
1968 prepareIdSource( theObject );
1969 SMESH::long_array_var anElementsId = theObject->GetIDs();
1970 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1972 // Update Python script
1973 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
1974 << theObject << ", " << Diag13 << " )";
1976 declareMeshModified( /*isReComputeSafe=*/!isDone );
1979 SMESH_CATCH( SMESH::throwCorbaException );
1984 //=============================================================================
1986 * Find better splitting of the given quadrangle.
1987 * \param IDOfQuad ID of the quadrangle to be splitted.
1988 * \param Criterion A criterion to choose a diagonal for splitting.
1989 * \return 1 if 1-3 diagonal is better, 2 if 2-4
1990 * diagonal is better, 0 if error occurs.
1992 //=============================================================================
1994 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
1995 SMESH::NumericalFunctor_ptr Criterion)
1996 throw (SALOME::SALOME_Exception)
2001 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2002 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2004 SMESH::NumericalFunctor_i* aNumericalFunctor =
2005 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2006 SMESH::Controls::NumericalFunctorPtr aCrit;
2007 if (aNumericalFunctor)
2008 aCrit = aNumericalFunctor->GetNumericalFunctor();
2010 aCrit.reset(new SMESH::Controls::AspectRatio());
2012 int id = getEditor().BestSplit(quad, aCrit);
2013 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2017 SMESH_CATCH( SMESH::throwCorbaException );
2021 //================================================================================
2023 * \brief Split volumic elements into tetrahedrons
2025 //================================================================================
2027 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2028 CORBA::Short methodFlags)
2029 throw (SALOME::SALOME_Exception)
2034 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2035 const int noneFacet = -1;
2036 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2037 while( volIt->more() )
2038 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2040 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2041 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2043 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2044 << elems << ", " << methodFlags << " )";
2046 SMESH_CATCH( SMESH::throwCorbaException );
2049 //================================================================================
2051 * \brief Split hexahedra into triangular prisms
2052 * \param elems - elements to split
2053 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2054 * to split into triangles
2055 * \param methodFlags - flags passing splitting method:
2056 * 1 - split the hexahedron into 2 prisms
2057 * 2 - split the hexahedron into 4 prisms
2059 //================================================================================
2061 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr elems,
2062 const SMESH::PointStruct & startHexPoint,
2063 const SMESH::DirStruct& facetToSplitNormal,
2064 CORBA::Short methodFlags,
2065 CORBA::Boolean allDomains)
2066 throw (SALOME::SALOME_Exception)
2070 prepareIdSource( elems );
2072 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2075 gp_Dir( facetToSplitNormal.PS.x,
2076 facetToSplitNormal.PS.y,
2077 facetToSplitNormal.PS.z ));
2078 TIDSortedElemSet elemSet;
2079 SMESH::long_array_var anElementsId = elems->GetIDs();
2080 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2081 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2083 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2084 while ( !elemSet.empty() )
2086 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2090 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2091 for ( ; ef != elemFacets.end(); ++ef )
2092 elemSet.erase( ef->first );
2095 if ( methodFlags == 2 )
2096 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2098 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2100 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2101 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2103 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2105 << startHexPoint << ", "
2106 << facetToSplitNormal<< ", "
2107 << methodFlags<< ", "
2108 << allDomains << " )";
2110 SMESH_CATCH( SMESH::throwCorbaException );
2113 //=======================================================================
2116 //=======================================================================
2119 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2120 const SMESH::long_array & IDsOfFixedNodes,
2121 CORBA::Long MaxNbOfIterations,
2122 CORBA::Double MaxAspectRatio,
2123 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2124 throw (SALOME::SALOME_Exception)
2126 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2127 MaxAspectRatio, Method, false );
2131 //=======================================================================
2132 //function : SmoothParametric
2134 //=======================================================================
2137 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2138 const SMESH::long_array & IDsOfFixedNodes,
2139 CORBA::Long MaxNbOfIterations,
2140 CORBA::Double MaxAspectRatio,
2141 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2142 throw (SALOME::SALOME_Exception)
2144 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2145 MaxAspectRatio, Method, true );
2149 //=======================================================================
2150 //function : SmoothObject
2152 //=======================================================================
2155 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2156 const SMESH::long_array & IDsOfFixedNodes,
2157 CORBA::Long MaxNbOfIterations,
2158 CORBA::Double MaxAspectRatio,
2159 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2160 throw (SALOME::SALOME_Exception)
2162 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2163 MaxAspectRatio, Method, false);
2167 //=======================================================================
2168 //function : SmoothParametricObject
2170 //=======================================================================
2173 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2174 const SMESH::long_array & IDsOfFixedNodes,
2175 CORBA::Long MaxNbOfIterations,
2176 CORBA::Double MaxAspectRatio,
2177 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2178 throw (SALOME::SALOME_Exception)
2180 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2181 MaxAspectRatio, Method, true);
2185 //=============================================================================
2189 //=============================================================================
2192 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2193 const SMESH::long_array & IDsOfFixedNodes,
2194 CORBA::Long MaxNbOfIterations,
2195 CORBA::Double MaxAspectRatio,
2196 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2198 throw (SALOME::SALOME_Exception)
2203 SMESHDS_Mesh* aMesh = getMeshDS();
2205 TIDSortedElemSet elements;
2206 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2208 set<const SMDS_MeshNode*> fixedNodes;
2209 for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
2210 CORBA::Long index = IDsOfFixedNodes[i];
2211 const SMDS_MeshNode * node = aMesh->FindNode(index);
2213 fixedNodes.insert( node );
2215 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2216 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2217 method = ::SMESH_MeshEditor::CENTROIDAL;
2219 getEditor().Smooth(elements, fixedNodes, method,
2220 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2222 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2224 // Update Python script
2225 TPythonDump() << "isDone = " << this << "."
2226 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2227 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2228 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2229 << "SMESH.SMESH_MeshEditor."
2230 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2231 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2235 SMESH_CATCH( SMESH::throwCorbaException );
2239 //=============================================================================
2243 //=============================================================================
2246 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2247 const SMESH::long_array & IDsOfFixedNodes,
2248 CORBA::Long MaxNbOfIterations,
2249 CORBA::Double MaxAspectRatio,
2250 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2252 throw (SALOME::SALOME_Exception)
2257 TPythonDump aTPythonDump; // suppress dump in smooth()
2259 prepareIdSource( theObject );
2260 SMESH::long_array_var anElementsId = theObject->GetIDs();
2261 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2262 MaxAspectRatio, Method, IsParametric);
2264 // Update Python script
2265 aTPythonDump << "isDone = " << this << "."
2266 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2267 << theObject << ", " << IDsOfFixedNodes << ", "
2268 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2269 << "SMESH.SMESH_MeshEditor."
2270 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2271 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2275 SMESH_CATCH( SMESH::throwCorbaException );
2279 //=============================================================================
2283 //=============================================================================
2285 void SMESH_MeshEditor_i::RenumberNodes()
2286 throw (SALOME::SALOME_Exception)
2289 // Update Python script
2290 TPythonDump() << this << ".RenumberNodes()";
2292 getMeshDS()->Renumber( true );
2294 SMESH_CATCH( SMESH::throwCorbaException );
2297 //=============================================================================
2301 //=============================================================================
2303 void SMESH_MeshEditor_i::RenumberElements()
2304 throw (SALOME::SALOME_Exception)
2307 // Update Python script
2308 TPythonDump() << this << ".RenumberElements()";
2310 getMeshDS()->Renumber( false );
2312 SMESH_CATCH( SMESH::throwCorbaException );
2315 //=======================================================================
2317 * \brief Return groups by their IDs
2319 //=======================================================================
2321 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2322 throw (SALOME::SALOME_Exception)
2327 myMesh_i->CreateGroupServants();
2328 return myMesh_i->GetGroups( *groupIDs );
2330 SMESH_CATCH( SMESH::throwCorbaException );
2334 //=======================================================================
2335 //function : RotationSweepObjects
2337 //=======================================================================
2339 SMESH::ListOfGroups*
2340 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2341 const SMESH::ListOfIDSources & theEdges,
2342 const SMESH::ListOfIDSources & theFaces,
2343 const SMESH::AxisStruct & theAxis,
2344 CORBA::Double theAngleInRadians,
2345 CORBA::Long theNbOfSteps,
2346 CORBA::Double theTolerance,
2347 const bool theMakeGroups)
2348 throw (SALOME::SALOME_Exception)
2353 TIDSortedElemSet elemsNodes[2];
2354 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2355 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2356 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2358 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2359 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2360 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2361 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2363 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2364 bool makeWalls=true;
2365 if ( myIsPreviewMode )
2367 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2368 TPreviewMesh * tmpMesh = getPreviewMesh();
2369 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2370 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2371 workElements = & copyElements[0];
2372 //makeWalls = false; -- faces are needed for preview
2375 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2377 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2378 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2380 ::SMESH_MeshEditor::PGroupIDs groupIds =
2381 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2382 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2384 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2386 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2388 if ( !myIsPreviewMode )
2390 dumpGroupsList( aPythonDump, aGroups );
2391 aPythonDump << this<< ".RotationSweepObjects( "
2396 << TVar( theAngleInRadians ) << ", "
2397 << TVar( theNbOfSteps ) << ", "
2398 << TVar( theTolerance ) << ", "
2399 << theMakeGroups << " )";
2402 return aGroups ? aGroups : new SMESH::ListOfGroups;
2404 SMESH_CATCH( SMESH::throwCorbaException );
2408 namespace MeshEditor_I
2411 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2413 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2415 bool myIsExtrusionByNormal;
2417 static int makeFlags( CORBA::Boolean MakeGroups,
2418 CORBA::Boolean ByAverageNormal = false,
2419 CORBA::Boolean UseInputElemsOnly = false,
2420 CORBA::Long Flags = 0,
2421 CORBA::Boolean MakeBoundary = true )
2423 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2424 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2425 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2426 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2430 ExtrusionParams(const SMESH::DirStruct & theDir,
2431 CORBA::Long theNbOfSteps,
2432 CORBA::Boolean theMakeGroups):
2433 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2437 makeFlags( theMakeGroups )),
2438 myIsExtrusionByNormal( false )
2442 ExtrusionParams(const SMESH::DirStruct & theDir,
2443 CORBA::Long theNbOfSteps,
2444 CORBA::Boolean theMakeGroups,
2445 CORBA::Long theExtrFlags,
2446 CORBA::Double theSewTolerance):
2447 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2451 makeFlags( theMakeGroups, false, false,
2452 theExtrFlags, false ),
2454 myIsExtrusionByNormal( false )
2457 // params for extrusion by normal
2458 ExtrusionParams(CORBA::Double theStepSize,
2459 CORBA::Long theNbOfSteps,
2460 CORBA::Short theDim,
2461 CORBA::Boolean theUseInputElemsOnly,
2462 CORBA::Boolean theByAverageNormal,
2463 CORBA::Boolean theMakeGroups ):
2464 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2466 makeFlags( theMakeGroups,
2467 theByAverageNormal, theUseInputElemsOnly ),
2469 myIsExtrusionByNormal( true )
2475 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2480 //=======================================================================
2482 * \brief Generate dim+1 elements by extrusion of elements along vector
2483 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2484 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2485 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2486 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2487 * \param [in] nbOfSteps - number of elements to generate from one element
2488 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2489 * corresponding to groups the input elements included in.
2490 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2492 //=======================================================================
2494 SMESH::ListOfGroups*
2495 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2496 const SMESH::ListOfIDSources & theEdges,
2497 const SMESH::ListOfIDSources & theFaces,
2498 const SMESH::DirStruct & theStepVector,
2499 CORBA::Long theNbOfSteps,
2500 CORBA::Boolean theToMakeGroups)
2501 throw (SALOME::SALOME_Exception)
2506 ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
2508 TIDSortedElemSet elemsNodes[2];
2509 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2510 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2511 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2513 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2514 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2515 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2516 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2518 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2519 if ( myIsPreviewMode )
2521 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2522 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2523 // previewType = SMDSAbs_Edge;
2525 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2526 TPreviewMesh * tmpMesh = getPreviewMesh();
2527 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2528 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2529 workElements = & copyElements[0];
2531 params.SetNoGroups();
2533 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2535 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2536 ::SMESH_MeshEditor::PGroupIDs groupIds =
2537 getEditor().ExtrusionSweep( workElements, params, aHistory );
2539 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2541 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2543 if ( !myIsPreviewMode )
2545 dumpGroupsList( aPythonDump, aGroups );
2546 aPythonDump << this<< ".ExtrusionSweepObjects( "
2550 << theStepVector << ", "
2551 << TVar( theNbOfSteps ) << ", "
2552 << theToMakeGroups << " )";
2555 return aGroups ? aGroups : new SMESH::ListOfGroups;
2557 SMESH_CATCH( SMESH::throwCorbaException );
2561 //=======================================================================
2562 //function : ExtrusionByNormal
2564 //=======================================================================
2566 SMESH::ListOfGroups*
2567 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2568 CORBA::Double stepSize,
2569 CORBA::Long nbOfSteps,
2570 CORBA::Boolean byAverageNormal,
2571 CORBA::Boolean useInputElemsOnly,
2572 CORBA::Boolean makeGroups,
2574 throw (SALOME::SALOME_Exception)
2579 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2581 ExtrusionParams params( stepSize, nbOfSteps, dim,
2582 byAverageNormal, useInputElemsOnly, makeGroups );
2584 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2585 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2587 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2588 if (( elemTypes->length() == 1 ) &&
2589 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2590 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2593 TIDSortedElemSet elemsNodes[2];
2594 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2595 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2597 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2598 if ( myIsPreviewMode )
2600 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2601 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2602 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2603 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2604 workElements = & copyElements[0];
2606 params.SetNoGroups();
2609 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2610 ::SMESH_MeshEditor::PGroupIDs groupIds =
2611 getEditor().ExtrusionSweep( workElements, params, aHistory );
2613 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2615 if (!myIsPreviewMode) {
2616 dumpGroupsList(aPythonDump, aGroups);
2617 aPythonDump << this << ".ExtrusionByNormal( " << objects
2618 << ", " << TVar( stepSize )
2619 << ", " << TVar( nbOfSteps )
2620 << ", " << byAverageNormal
2621 << ", " << useInputElemsOnly
2622 << ", " << makeGroups
2627 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2629 return aGroups ? aGroups : new SMESH::ListOfGroups;
2631 SMESH_CATCH( SMESH::throwCorbaException );
2635 //=======================================================================
2636 //function : AdvancedExtrusion
2638 //=======================================================================
2640 SMESH::ListOfGroups*
2641 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2642 const SMESH::DirStruct & theStepVector,
2643 CORBA::Long theNbOfSteps,
2644 CORBA::Long theExtrFlags,
2645 CORBA::Double theSewTolerance,
2646 CORBA::Boolean theMakeGroups)
2647 throw (SALOME::SALOME_Exception)
2652 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2654 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2655 theExtrFlags, theSewTolerance );
2657 TIDSortedElemSet elemsNodes[2];
2658 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2660 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2661 ::SMESH_MeshEditor::PGroupIDs groupIds =
2662 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2664 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2666 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2668 if ( !myIsPreviewMode ) {
2669 dumpGroupsList(aPythonDump, aGroups);
2670 aPythonDump << this << ".AdvancedExtrusion( "
2671 << theIDsOfElements << ", "
2672 << theStepVector << ", "
2673 << theNbOfSteps << ", "
2674 << theExtrFlags << ", "
2675 << theSewTolerance << ", "
2676 << theMakeGroups << " )";
2679 return aGroups ? aGroups : new SMESH::ListOfGroups;
2681 SMESH_CATCH( SMESH::throwCorbaException );
2685 //================================================================================
2687 * \brief Convert extrusion error to IDL enum
2689 //================================================================================
2693 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2695 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2699 RETCASE( EXTR_NO_ELEMENTS );
2700 RETCASE( EXTR_PATH_NOT_EDGE );
2701 RETCASE( EXTR_BAD_PATH_SHAPE );
2702 RETCASE( EXTR_BAD_STARTING_NODE );
2703 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2704 RETCASE( EXTR_CANT_GET_TANGENT );
2706 return SMESH::SMESH_MeshEditor::EXTR_OK;
2710 //=======================================================================
2711 //function : extrusionAlongPath
2713 //=======================================================================
2714 SMESH::ListOfGroups*
2715 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2716 const SMESH::ListOfIDSources & theEdges,
2717 const SMESH::ListOfIDSources & theFaces,
2718 SMESH::SMESH_IDSource_ptr thePathMesh,
2719 GEOM::GEOM_Object_ptr thePathShape,
2720 CORBA::Long theNodeStart,
2721 CORBA::Boolean theHasAngles,
2722 const SMESH::double_array & theAngles,
2723 CORBA::Boolean theLinearVariation,
2724 CORBA::Boolean theHasRefPoint,
2725 const SMESH::PointStruct & theRefPoint,
2727 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2728 throw (SALOME::SALOME_Exception)
2733 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2735 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2736 if ( thePathMesh->_is_nil() )
2737 return aGroups._retn();
2740 SMESH_subMesh* aSubMesh = 0;
2741 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2742 if ( thePathShape->_is_nil() )
2744 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2745 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2747 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2748 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2749 if ( !aMeshImp ) return aGroups._retn();
2750 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2751 if ( !aSubMesh ) return aGroups._retn();
2753 else if ( !aMeshImp ||
2754 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2756 return aGroups._retn();
2761 if ( !aMeshImp ) return aGroups._retn();
2762 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2763 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2764 if ( !aSubMesh || !aSubMesh->GetSubMeshDS() )
2765 return aGroups._retn();
2768 SMDS_MeshNode* nodeStart =
2769 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2771 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2772 return aGroups._retn();
2775 TIDSortedElemSet elemsNodes[2];
2776 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2777 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2778 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2780 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2781 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2782 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2783 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2785 list<double> angles;
2786 for (int i = 0; i < theAngles.length(); i++) {
2787 angles.push_back( theAngles[i] );
2790 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2792 int nbOldGroups = myMesh->NbGroup();
2794 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2795 if ( myIsPreviewMode )
2797 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2798 TPreviewMesh * tmpMesh = getPreviewMesh();
2799 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2800 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2801 workElements = & copyElements[0];
2802 theMakeGroups = false;
2805 ::SMESH_MeshEditor::Extrusion_Error error;
2807 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2808 theHasAngles, angles, theLinearVariation,
2809 theHasRefPoint, refPnt, theMakeGroups );
2811 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2812 theHasAngles, angles, theLinearVariation,
2813 theHasRefPoint, refPnt, theMakeGroups );
2815 declareMeshModified( /*isReComputeSafe=*/true );
2816 theError = convExtrError( error );
2818 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2819 if ( theMakeGroups ) {
2820 list<int> groupIDs = myMesh->GetGroupIds();
2821 list<int>::iterator newBegin = groupIDs.begin();
2822 std::advance( newBegin, nbOldGroups ); // skip old groups
2823 groupIDs.erase( groupIDs.begin(), newBegin );
2824 aGroups = getGroups( & groupIDs );
2825 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2828 if ( !myIsPreviewMode ) {
2829 aPythonDump << "(" << aGroups << ", error) = "
2830 << this << ".ExtrusionAlongPathObjects( "
2834 << thePathMesh << ", "
2835 << thePathShape << ", "
2836 << theNodeStart << ", "
2837 << theHasAngles << ", "
2838 << theAngles << ", "
2839 << theLinearVariation << ", "
2840 << theHasRefPoint << ", "
2841 << "SMESH.PointStruct( "
2842 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2843 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2844 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2845 << theMakeGroups << " )";
2848 return aGroups._retn();
2850 SMESH_CATCH( SMESH::throwCorbaException );
2854 //================================================================================
2856 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2857 * of given angles along path steps
2858 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2859 * which proceeds the extrusion
2860 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2861 * is used to define the sub-mesh for the path
2863 //================================================================================
2865 SMESH::double_array*
2866 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2867 GEOM::GEOM_Object_ptr thePathShape,
2868 const SMESH::double_array & theAngles)
2870 SMESH::double_array_var aResult = new SMESH::double_array();
2871 int nbAngles = theAngles.length();
2872 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2874 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2875 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2876 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2877 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2878 return aResult._retn();
2879 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2880 if ( nbSteps == nbAngles )
2882 aResult.inout() = theAngles;
2886 aResult->length( nbSteps );
2887 double rAn2St = double( nbAngles ) / double( nbSteps );
2888 double angPrev = 0, angle;
2889 for ( int iSt = 0; iSt < nbSteps; ++iSt )
2891 double angCur = rAn2St * ( iSt+1 );
2892 double angCurFloor = floor( angCur );
2893 double angPrevFloor = floor( angPrev );
2894 if ( angPrevFloor == angCurFloor )
2895 angle = rAn2St * theAngles[ int( angCurFloor ) ];
2898 int iP = int( angPrevFloor );
2899 double angPrevCeil = ceil(angPrev);
2900 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2902 int iC = int( angCurFloor );
2903 if ( iC < nbAngles )
2904 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2906 iP = int( angPrevCeil );
2908 angle += theAngles[ iC ];
2910 aResult[ iSt ] = angle;
2915 // Update Python script
2916 TPythonDump() << "rotAngles = " << theAngles;
2917 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
2918 << thePathMesh << ", "
2919 << thePathShape << ", "
2922 return aResult._retn();
2925 //=======================================================================
2928 //=======================================================================
2930 SMESH::ListOfGroups*
2931 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
2932 const SMESH::AxisStruct & theAxis,
2933 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2934 CORBA::Boolean theCopy,
2936 ::SMESH_Mesh* theTargetMesh)
2937 throw (SALOME::SALOME_Exception)
2942 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2943 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2945 if ( theTargetMesh )
2949 switch ( theMirrorType ) {
2950 case SMESH::SMESH_MeshEditor::POINT:
2951 aTrsf.SetMirror( P );
2953 case SMESH::SMESH_MeshEditor::AXIS:
2954 aTrsf.SetMirror( gp_Ax1( P, V ));
2957 aTrsf.SetMirror( gp_Ax2( P, V ));
2960 TIDSortedElemSet copyElements;
2961 TIDSortedElemSet* workElements = & theElements;
2963 if ( myIsPreviewMode )
2965 TPreviewMesh * tmpMesh = getPreviewMesh();
2966 tmpMesh->Copy( theElements, copyElements);
2967 if ( !theCopy && !theTargetMesh )
2969 TIDSortedElemSet elemsAround, elemsAroundCopy;
2970 getElementsAround( theElements, getMeshDS(), elemsAround );
2971 tmpMesh->Copy( elemsAround, elemsAroundCopy);
2973 workElements = & copyElements;
2974 theMakeGroups = false;
2977 ::SMESH_MeshEditor::PGroupIDs groupIds =
2978 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2980 if ( theCopy && !myIsPreviewMode)
2982 if ( theTargetMesh )
2984 theTargetMesh->GetMeshDS()->Modified();
2988 declareMeshModified( /*isReComputeSafe=*/false );
2991 return theMakeGroups ? getGroups(groupIds.get()) : 0;
2993 SMESH_CATCH( SMESH::throwCorbaException );
2997 //=======================================================================
3000 //=======================================================================
3002 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3003 const SMESH::AxisStruct & theAxis,
3004 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3005 CORBA::Boolean theCopy)
3006 throw (SALOME::SALOME_Exception)
3008 if ( !myIsPreviewMode ) {
3009 TPythonDump() << this << ".Mirror( "
3010 << theIDsOfElements << ", "
3012 << mirrorTypeName(theMirrorType) << ", "
3015 if ( theIDsOfElements.length() > 0 )
3017 TIDSortedElemSet elements;
3018 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3019 mirror(elements, theAxis, theMirrorType, theCopy, false);
3024 //=======================================================================
3025 //function : MirrorObject
3027 //=======================================================================
3029 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3030 const SMESH::AxisStruct & theAxis,
3031 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3032 CORBA::Boolean theCopy)
3033 throw (SALOME::SALOME_Exception)
3035 if ( !myIsPreviewMode ) {
3036 TPythonDump() << this << ".MirrorObject( "
3037 << theObject << ", "
3039 << mirrorTypeName(theMirrorType) << ", "
3042 TIDSortedElemSet elements;
3044 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3046 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3047 mirror(elements, theAxis, theMirrorType, theCopy, false);
3050 //=======================================================================
3051 //function : MirrorMakeGroups
3053 //=======================================================================
3055 SMESH::ListOfGroups*
3056 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3057 const SMESH::AxisStruct& theMirror,
3058 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3059 throw (SALOME::SALOME_Exception)
3061 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3063 SMESH::ListOfGroups * aGroups = 0;
3064 if ( theIDsOfElements.length() > 0 )
3066 TIDSortedElemSet elements;
3067 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3068 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3070 if (!myIsPreviewMode) {
3071 dumpGroupsList(aPythonDump, aGroups);
3072 aPythonDump << this << ".MirrorMakeGroups( "
3073 << theIDsOfElements << ", "
3074 << theMirror << ", "
3075 << mirrorTypeName(theMirrorType) << " )";
3080 //=======================================================================
3081 //function : MirrorObjectMakeGroups
3083 //=======================================================================
3085 SMESH::ListOfGroups*
3086 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3087 const SMESH::AxisStruct& theMirror,
3088 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3089 throw (SALOME::SALOME_Exception)
3091 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3093 SMESH::ListOfGroups * aGroups = 0;
3094 TIDSortedElemSet elements;
3095 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3096 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3098 if (!myIsPreviewMode)
3100 dumpGroupsList(aPythonDump,aGroups);
3101 aPythonDump << this << ".MirrorObjectMakeGroups( "
3102 << theObject << ", "
3103 << theMirror << ", "
3104 << mirrorTypeName(theMirrorType) << " )";
3109 //=======================================================================
3110 //function : MirrorMakeMesh
3112 //=======================================================================
3114 SMESH::SMESH_Mesh_ptr
3115 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3116 const SMESH::AxisStruct& theMirror,
3117 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3118 CORBA::Boolean theCopyGroups,
3119 const char* theMeshName)
3120 throw (SALOME::SALOME_Exception)
3122 SMESH_Mesh_i* mesh_i;
3123 SMESH::SMESH_Mesh_var mesh;
3124 { // open new scope to dump "MakeMesh" command
3125 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3127 TPythonDump pydump; // to prevent dump at mesh creation
3129 mesh = makeMesh( theMeshName );
3130 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3131 if (mesh_i && theIDsOfElements.length() > 0 )
3133 TIDSortedElemSet elements;
3134 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3135 mirror(elements, theMirror, theMirrorType,
3136 false, theCopyGroups, & mesh_i->GetImpl());
3137 mesh_i->CreateGroupServants();
3140 if (!myIsPreviewMode) {
3141 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3142 << theIDsOfElements << ", "
3143 << theMirror << ", "
3144 << mirrorTypeName(theMirrorType) << ", "
3145 << theCopyGroups << ", '"
3146 << theMeshName << "' )";
3151 if (!myIsPreviewMode && mesh_i)
3152 mesh_i->GetGroups();
3154 return mesh._retn();
3157 //=======================================================================
3158 //function : MirrorObjectMakeMesh
3160 //=======================================================================
3162 SMESH::SMESH_Mesh_ptr
3163 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3164 const SMESH::AxisStruct& theMirror,
3165 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3166 CORBA::Boolean theCopyGroups,
3167 const char* theMeshName)
3168 throw (SALOME::SALOME_Exception)
3170 SMESH_Mesh_i* mesh_i;
3171 SMESH::SMESH_Mesh_var mesh;
3172 { // open new scope to dump "MakeMesh" command
3173 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3175 TPythonDump pydump; // to prevent dump at mesh creation
3177 mesh = makeMesh( theMeshName );
3178 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3179 TIDSortedElemSet elements;
3181 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3183 mirror(elements, theMirror, theMirrorType,
3184 false, theCopyGroups, & mesh_i->GetImpl());
3185 mesh_i->CreateGroupServants();
3187 if (!myIsPreviewMode) {
3188 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3189 << theObject << ", "
3190 << theMirror << ", "
3191 << mirrorTypeName(theMirrorType) << ", "
3192 << theCopyGroups << ", '"
3193 << theMeshName << "' )";
3198 if (!myIsPreviewMode && mesh_i)
3199 mesh_i->GetGroups();
3201 return mesh._retn();
3204 //=======================================================================
3205 //function : translate
3207 //=======================================================================
3209 SMESH::ListOfGroups*
3210 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3211 const SMESH::DirStruct & theVector,
3212 CORBA::Boolean theCopy,
3214 ::SMESH_Mesh* theTargetMesh)
3215 throw (SALOME::SALOME_Exception)
3220 if ( theTargetMesh )
3224 const SMESH::PointStruct * P = &theVector.PS;
3225 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3227 TIDSortedElemSet copyElements;
3228 TIDSortedElemSet* workElements = &theElements;
3230 if ( myIsPreviewMode )
3232 TPreviewMesh * tmpMesh = getPreviewMesh();
3233 tmpMesh->Copy( theElements, copyElements);
3234 if ( !theCopy && !theTargetMesh )
3236 TIDSortedElemSet elemsAround, elemsAroundCopy;
3237 getElementsAround( theElements, getMeshDS(), elemsAround );
3238 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3240 workElements = & copyElements;
3241 theMakeGroups = false;
3244 ::SMESH_MeshEditor::PGroupIDs groupIds =
3245 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3247 if ( theCopy && !myIsPreviewMode )
3249 if ( theTargetMesh )
3251 theTargetMesh->GetMeshDS()->Modified();
3255 declareMeshModified( /*isReComputeSafe=*/false );
3259 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3261 SMESH_CATCH( SMESH::throwCorbaException );
3265 //=======================================================================
3266 //function : Translate
3268 //=======================================================================
3270 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3271 const SMESH::DirStruct & theVector,
3272 CORBA::Boolean theCopy)
3273 throw (SALOME::SALOME_Exception)
3275 if (!myIsPreviewMode) {
3276 TPythonDump() << this << ".Translate( "
3277 << theIDsOfElements << ", "
3278 << theVector << ", "
3281 if (theIDsOfElements.length()) {
3282 TIDSortedElemSet elements;
3283 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3284 translate(elements, theVector, theCopy, false);
3288 //=======================================================================
3289 //function : TranslateObject
3291 //=======================================================================
3293 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3294 const SMESH::DirStruct & theVector,
3295 CORBA::Boolean theCopy)
3296 throw (SALOME::SALOME_Exception)
3298 if (!myIsPreviewMode) {
3299 TPythonDump() << this << ".TranslateObject( "
3300 << theObject << ", "
3301 << theVector << ", "
3304 TIDSortedElemSet elements;
3306 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3308 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3309 translate(elements, theVector, theCopy, false);
3312 //=======================================================================
3313 //function : TranslateMakeGroups
3315 //=======================================================================
3317 SMESH::ListOfGroups*
3318 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3319 const SMESH::DirStruct& theVector)
3320 throw (SALOME::SALOME_Exception)
3322 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3324 SMESH::ListOfGroups * aGroups = 0;
3325 if (theIDsOfElements.length()) {
3326 TIDSortedElemSet elements;
3327 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3328 aGroups = translate(elements,theVector,true,true);
3330 if (!myIsPreviewMode) {
3331 dumpGroupsList(aPythonDump, aGroups);
3332 aPythonDump << this << ".TranslateMakeGroups( "
3333 << theIDsOfElements << ", "
3334 << theVector << " )";
3339 //=======================================================================
3340 //function : TranslateObjectMakeGroups
3342 //=======================================================================
3344 SMESH::ListOfGroups*
3345 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3346 const SMESH::DirStruct& theVector)
3347 throw (SALOME::SALOME_Exception)
3349 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3351 SMESH::ListOfGroups * aGroups = 0;
3352 TIDSortedElemSet elements;
3353 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3354 aGroups = translate(elements, theVector, true, true);
3356 if (!myIsPreviewMode) {
3357 dumpGroupsList(aPythonDump, aGroups);
3358 aPythonDump << this << ".TranslateObjectMakeGroups( "
3359 << theObject << ", "
3360 << theVector << " )";
3365 //=======================================================================
3366 //function : TranslateMakeMesh
3368 //=======================================================================
3370 SMESH::SMESH_Mesh_ptr
3371 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3372 const SMESH::DirStruct& theVector,
3373 CORBA::Boolean theCopyGroups,
3374 const char* theMeshName)
3375 throw (SALOME::SALOME_Exception)
3377 SMESH_Mesh_i* mesh_i;
3378 SMESH::SMESH_Mesh_var mesh;
3380 { // open new scope to dump "MakeMesh" command
3381 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3383 TPythonDump pydump; // to prevent dump at mesh creation
3385 mesh = makeMesh( theMeshName );
3386 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3388 if ( mesh_i && theIDsOfElements.length() )
3390 TIDSortedElemSet elements;
3391 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3392 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3393 mesh_i->CreateGroupServants();
3396 if ( !myIsPreviewMode ) {
3397 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3398 << theIDsOfElements << ", "
3399 << theVector << ", "
3400 << theCopyGroups << ", '"
3401 << theMeshName << "' )";
3406 if (!myIsPreviewMode && mesh_i)
3407 mesh_i->GetGroups();
3409 return mesh._retn();
3412 //=======================================================================
3413 //function : TranslateObjectMakeMesh
3415 //=======================================================================
3417 SMESH::SMESH_Mesh_ptr
3418 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3419 const SMESH::DirStruct& theVector,
3420 CORBA::Boolean theCopyGroups,
3421 const char* theMeshName)
3422 throw (SALOME::SALOME_Exception)
3425 SMESH_Mesh_i* mesh_i;
3426 SMESH::SMESH_Mesh_var mesh;
3427 { // open new scope to dump "MakeMesh" command
3428 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3430 TPythonDump pydump; // to prevent dump at mesh creation
3431 mesh = makeMesh( theMeshName );
3432 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3434 TIDSortedElemSet elements;
3436 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3438 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3439 mesh_i->CreateGroupServants();
3441 if ( !myIsPreviewMode ) {
3442 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3443 << theObject << ", "
3444 << theVector << ", "
3445 << theCopyGroups << ", '"
3446 << theMeshName << "' )";
3451 if (!myIsPreviewMode && mesh_i)
3452 mesh_i->GetGroups();
3454 return mesh._retn();
3456 SMESH_CATCH( SMESH::throwCorbaException );
3460 //=======================================================================
3463 //=======================================================================
3465 SMESH::ListOfGroups*
3466 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3467 const SMESH::AxisStruct & theAxis,
3468 CORBA::Double theAngle,
3469 CORBA::Boolean theCopy,
3471 ::SMESH_Mesh* theTargetMesh)
3472 throw (SALOME::SALOME_Exception)
3477 if ( theTargetMesh )
3480 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3481 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3484 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3486 TIDSortedElemSet copyElements;
3487 TIDSortedElemSet* workElements = &theElements;
3488 if ( myIsPreviewMode ) {
3489 TPreviewMesh * tmpMesh = getPreviewMesh();
3490 tmpMesh->Copy( theElements, copyElements );
3491 if ( !theCopy && !theTargetMesh )
3493 TIDSortedElemSet elemsAround, elemsAroundCopy;
3494 getElementsAround( theElements, getMeshDS(), elemsAround );
3495 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3497 workElements = ©Elements;
3498 theMakeGroups = false;
3501 ::SMESH_MeshEditor::PGroupIDs groupIds =
3502 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3504 if ( theCopy && !myIsPreviewMode)
3506 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3507 else declareMeshModified( /*isReComputeSafe=*/false );
3510 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3512 SMESH_CATCH( SMESH::throwCorbaException );
3516 //=======================================================================
3519 //=======================================================================
3521 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3522 const SMESH::AxisStruct & theAxis,
3523 CORBA::Double theAngle,
3524 CORBA::Boolean theCopy)
3525 throw (SALOME::SALOME_Exception)
3527 if (!myIsPreviewMode) {
3528 TPythonDump() << this << ".Rotate( "
3529 << theIDsOfElements << ", "
3531 << TVar( theAngle ) << ", "
3534 if (theIDsOfElements.length() > 0)
3536 TIDSortedElemSet elements;
3537 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3538 rotate(elements,theAxis,theAngle,theCopy,false);
3542 //=======================================================================
3543 //function : RotateObject
3545 //=======================================================================
3547 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3548 const SMESH::AxisStruct & theAxis,
3549 CORBA::Double theAngle,
3550 CORBA::Boolean theCopy)
3551 throw (SALOME::SALOME_Exception)
3553 if ( !myIsPreviewMode ) {
3554 TPythonDump() << this << ".RotateObject( "
3555 << theObject << ", "
3557 << TVar( theAngle ) << ", "
3560 TIDSortedElemSet elements;
3561 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3562 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3563 rotate(elements,theAxis,theAngle,theCopy,false);
3566 //=======================================================================
3567 //function : RotateMakeGroups
3569 //=======================================================================
3571 SMESH::ListOfGroups*
3572 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3573 const SMESH::AxisStruct& theAxis,
3574 CORBA::Double theAngle)
3575 throw (SALOME::SALOME_Exception)
3577 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3579 SMESH::ListOfGroups * aGroups = 0;
3580 if (theIDsOfElements.length() > 0)
3582 TIDSortedElemSet elements;
3583 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3584 aGroups = rotate(elements,theAxis,theAngle,true,true);
3586 if (!myIsPreviewMode) {
3587 dumpGroupsList(aPythonDump, aGroups);
3588 aPythonDump << this << ".RotateMakeGroups( "
3589 << theIDsOfElements << ", "
3591 << TVar( theAngle ) << " )";
3596 //=======================================================================
3597 //function : RotateObjectMakeGroups
3599 //=======================================================================
3601 SMESH::ListOfGroups*
3602 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3603 const SMESH::AxisStruct& theAxis,
3604 CORBA::Double theAngle)
3605 throw (SALOME::SALOME_Exception)
3607 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3609 SMESH::ListOfGroups * aGroups = 0;
3610 TIDSortedElemSet elements;
3611 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3612 aGroups = rotate(elements, theAxis, theAngle, true, true);
3614 if (!myIsPreviewMode) {
3615 dumpGroupsList(aPythonDump, aGroups);
3616 aPythonDump << this << ".RotateObjectMakeGroups( "
3617 << theObject << ", "
3619 << TVar( theAngle ) << " )";
3624 //=======================================================================
3625 //function : RotateMakeMesh
3627 //=======================================================================
3629 SMESH::SMESH_Mesh_ptr
3630 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3631 const SMESH::AxisStruct& theAxis,
3632 CORBA::Double theAngleInRadians,
3633 CORBA::Boolean theCopyGroups,
3634 const char* theMeshName)
3635 throw (SALOME::SALOME_Exception)
3638 SMESH::SMESH_Mesh_var mesh;
3639 SMESH_Mesh_i* mesh_i;
3641 { // open new scope to dump "MakeMesh" command
3642 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3644 TPythonDump pydump; // to prevent dump at mesh creation
3646 mesh = makeMesh( theMeshName );
3647 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3649 if ( mesh_i && theIDsOfElements.length() > 0 )
3651 TIDSortedElemSet elements;
3652 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3653 rotate(elements, theAxis, theAngleInRadians,
3654 false, theCopyGroups, & mesh_i->GetImpl());
3655 mesh_i->CreateGroupServants();
3657 if ( !myIsPreviewMode ) {
3658 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3659 << theIDsOfElements << ", "
3661 << TVar( theAngleInRadians ) << ", "
3662 << theCopyGroups << ", '"
3663 << theMeshName << "' )";
3668 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3669 mesh_i->GetGroups();
3671 return mesh._retn();
3673 SMESH_CATCH( SMESH::throwCorbaException );
3677 //=======================================================================
3678 //function : RotateObjectMakeMesh
3680 //=======================================================================
3682 SMESH::SMESH_Mesh_ptr
3683 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3684 const SMESH::AxisStruct& theAxis,
3685 CORBA::Double theAngleInRadians,
3686 CORBA::Boolean theCopyGroups,
3687 const char* theMeshName)
3688 throw (SALOME::SALOME_Exception)
3691 SMESH::SMESH_Mesh_var mesh;
3692 SMESH_Mesh_i* mesh_i;
3694 {// open new scope to dump "MakeMesh" command
3695 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3697 TPythonDump pydump; // to prevent dump at mesh creation
3698 mesh = makeMesh( theMeshName );
3699 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3701 TIDSortedElemSet elements;
3703 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3705 rotate(elements, theAxis, theAngleInRadians,
3706 false, theCopyGroups, & mesh_i->GetImpl());
3707 mesh_i->CreateGroupServants();
3709 if ( !myIsPreviewMode ) {
3710 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3711 << theObject << ", "
3713 << TVar( theAngleInRadians ) << ", "
3714 << theCopyGroups << ", '"
3715 << theMeshName << "' )";
3720 if (!myIsPreviewMode && mesh_i)
3721 mesh_i->GetGroups();
3723 return mesh._retn();
3725 SMESH_CATCH( SMESH::throwCorbaException );
3729 //=======================================================================
3732 //=======================================================================
3734 SMESH::ListOfGroups*
3735 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3736 const SMESH::PointStruct& thePoint,
3737 const SMESH::double_array& theScaleFact,
3738 CORBA::Boolean theCopy,
3740 ::SMESH_Mesh* theTargetMesh)
3741 throw (SALOME::SALOME_Exception)
3745 if ( theScaleFact.length() < 1 )
3746 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3747 if ( theScaleFact.length() == 2 )
3748 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3750 if ( theTargetMesh )
3753 TIDSortedElemSet elements;
3754 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3755 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3760 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3761 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3763 double tol = std::numeric_limits<double>::max();
3766 #if OCC_VERSION_LARGE > 0x06070100
3767 // fight against ortagonalization
3768 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3769 // 0, S[1], 0, thePoint.y * (1-S[1]),
3770 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3771 aTrsf.SetTranslation( gp_Vec( thePoint.x * (1-S[0]),
3772 thePoint.y * (1-S[1]),
3773 thePoint.z * (1-S[2])));
3774 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3775 M.SetDiagonal( S[0], S[1], S[2] );
3778 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3779 0, S[1], 0, thePoint.y * (1-S[1]),
3780 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3783 TIDSortedElemSet copyElements;
3784 TIDSortedElemSet* workElements = &elements;
3785 if ( myIsPreviewMode )
3787 TPreviewMesh * tmpMesh = getPreviewMesh();
3788 tmpMesh->Copy( elements, copyElements);
3789 if ( !theCopy && !theTargetMesh )
3791 TIDSortedElemSet elemsAround, elemsAroundCopy;
3792 getElementsAround( elements, getMeshDS(), elemsAround );
3793 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3795 workElements = & copyElements;
3796 theMakeGroups = false;
3799 ::SMESH_MeshEditor::PGroupIDs groupIds =
3800 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3802 if ( theCopy && !myIsPreviewMode )
3804 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3805 else declareMeshModified( /*isReComputeSafe=*/false );
3807 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3809 SMESH_CATCH( SMESH::throwCorbaException );
3813 //=======================================================================
3816 //=======================================================================
3818 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3819 const SMESH::PointStruct& thePoint,
3820 const SMESH::double_array& theScaleFact,
3821 CORBA::Boolean theCopy)
3822 throw (SALOME::SALOME_Exception)
3824 if ( !myIsPreviewMode ) {
3825 TPythonDump() << this << ".Scale( "
3826 << theObject << ", "
3828 << TVar( theScaleFact ) << ", "
3831 scale(theObject, thePoint, theScaleFact, theCopy, false);
3835 //=======================================================================
3836 //function : ScaleMakeGroups
3838 //=======================================================================
3840 SMESH::ListOfGroups*
3841 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3842 const SMESH::PointStruct& thePoint,
3843 const SMESH::double_array& theScaleFact)
3844 throw (SALOME::SALOME_Exception)
3846 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3848 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3849 if (!myIsPreviewMode) {
3850 dumpGroupsList(aPythonDump, aGroups);
3851 aPythonDump << this << ".Scale("
3854 << TVar( theScaleFact ) << ",True,True)";
3860 //=======================================================================
3861 //function : ScaleMakeMesh
3863 //=======================================================================
3865 SMESH::SMESH_Mesh_ptr
3866 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3867 const SMESH::PointStruct& thePoint,
3868 const SMESH::double_array& theScaleFact,
3869 CORBA::Boolean theCopyGroups,
3870 const char* theMeshName)
3871 throw (SALOME::SALOME_Exception)
3873 SMESH_Mesh_i* mesh_i;
3874 SMESH::SMESH_Mesh_var mesh;
3875 { // open new scope to dump "MakeMesh" command
3876 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3878 TPythonDump pydump; // to prevent dump at mesh creation
3879 mesh = makeMesh( theMeshName );
3880 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3884 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3885 mesh_i->CreateGroupServants();
3887 if ( !myIsPreviewMode )
3888 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3889 << theObject << ", "
3891 << TVar( theScaleFact ) << ", "
3892 << theCopyGroups << ", '"
3893 << theMeshName << "' )";
3897 if (!myIsPreviewMode && mesh_i)
3898 mesh_i->GetGroups();
3900 return mesh._retn();
3904 //=======================================================================
3905 //function : FindCoincidentNodes
3907 //=======================================================================
3909 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tolerance,
3910 SMESH::array_of_long_array_out GroupsOfNodes)
3911 throw (SALOME::SALOME_Exception)
3916 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3917 TIDSortedNodeSet nodes; // no input nodes
3918 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3920 GroupsOfNodes = new SMESH::array_of_long_array;
3921 GroupsOfNodes->length( aListOfListOfNodes.size() );
3922 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3923 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3924 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3925 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3926 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3927 aGroup.length( aListOfNodes.size() );
3928 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3929 aGroup[ j ] = (*lIt)->GetID();
3931 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3932 << Tolerance << " )";
3934 SMESH_CATCH( SMESH::throwCorbaException );
3937 //=======================================================================
3938 //function : FindCoincidentNodesOnPart
3940 //=======================================================================
3942 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
3943 CORBA::Double Tolerance,
3944 SMESH::array_of_long_array_out GroupsOfNodes)
3945 throw (SALOME::SALOME_Exception)
3950 TIDSortedNodeSet nodes;
3951 idSourceToNodeSet( theObject, getMeshDS(), nodes );
3953 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3955 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3957 GroupsOfNodes = new SMESH::array_of_long_array;
3958 GroupsOfNodes->length( aListOfListOfNodes.size() );
3959 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3960 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3962 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3963 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3964 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3965 aGroup.length( aListOfNodes.size() );
3966 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3967 aGroup[ j ] = (*lIt)->GetID();
3969 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
3971 << Tolerance << " )";
3973 SMESH_CATCH( SMESH::throwCorbaException );
3976 //================================================================================
3978 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
3979 * ExceptSubMeshOrGroups
3981 //================================================================================
3983 void SMESH_MeshEditor_i::
3984 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
3985 CORBA::Double theTolerance,
3986 SMESH::array_of_long_array_out theGroupsOfNodes,
3987 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups)
3988 throw (SALOME::SALOME_Exception)
3993 TIDSortedNodeSet nodes;
3994 idSourceToNodeSet( theObject, getMeshDS(), nodes );
3996 for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
3998 TIDSortedNodeSet exceptNodes;
3999 idSourceToNodeSet( theExceptSubMeshOrGroups[i], getMeshDS(), exceptNodes );
4000 TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
4001 for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
4002 nodes.erase( *avoidNode );
4004 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4006 getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
4008 theGroupsOfNodes = new SMESH::array_of_long_array;
4009 theGroupsOfNodes->length( aListOfListOfNodes.size() );
4010 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4011 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4013 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4014 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4015 SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
4016 aGroup.length( aListOfNodes.size() );
4017 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4018 aGroup[ j ] = (*lIt)->GetID();
4020 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4022 << theTolerance << ", "
4023 << theExceptSubMeshOrGroups << " )";
4025 SMESH_CATCH( SMESH::throwCorbaException );
4028 //=======================================================================
4029 //function : MergeNodes
4031 //=======================================================================
4033 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
4034 throw (SALOME::SALOME_Exception)
4039 SMESHDS_Mesh* aMesh = getMeshDS();
4041 TPythonDump aTPythonDump;
4042 aTPythonDump << this << ".MergeNodes([";
4043 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4044 for (int i = 0; i < GroupsOfNodes.length(); i++)
4046 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4047 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4048 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4049 for ( int j = 0; j < aNodeGroup.length(); j++ )
4051 CORBA::Long index = aNodeGroup[ j ];
4052 const SMDS_MeshNode * node = aMesh->FindNode(index);
4054 aListOfNodes.push_back( node );
4056 if ( aListOfNodes.size() < 2 )
4057 aListOfListOfNodes.pop_back();
4059 if ( i > 0 ) aTPythonDump << ", ";
4060 aTPythonDump << aNodeGroup;
4062 getEditor().MergeNodes( aListOfListOfNodes );
4064 aTPythonDump << "])";
4066 declareMeshModified( /*isReComputeSafe=*/false );
4068 SMESH_CATCH( SMESH::throwCorbaException );
4071 //=======================================================================
4072 //function : FindEqualElements
4074 //=======================================================================
4076 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4077 SMESH::array_of_long_array_out GroupsOfElementsID)
4078 throw (SALOME::SALOME_Exception)
4083 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4084 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4086 TIDSortedElemSet elems;
4087 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4089 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4090 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4092 GroupsOfElementsID = new SMESH::array_of_long_array;
4093 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4095 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4096 aListOfListOfElementsID.begin();
4097 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4099 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4100 list<int>& listOfIDs = *arraysIt;
4101 aGroup.length( listOfIDs.size() );
4102 list<int>::iterator idIt = listOfIDs.begin();
4103 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4104 aGroup[ k ] = *idIt;
4107 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4111 SMESH_CATCH( SMESH::throwCorbaException );
4114 //=======================================================================
4115 //function : MergeElements
4117 //=======================================================================
4119 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4120 throw (SALOME::SALOME_Exception)
4125 TPythonDump aTPythonDump;
4126 aTPythonDump << this << ".MergeElements( [";
4128 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4130 for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4131 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4132 aListOfListOfElementsID.push_back( list< int >() );
4133 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4134 for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4135 CORBA::Long id = anElemsIDGroup[ j ];
4136 aListOfElemsID.push_back( id );
4138 if ( aListOfElemsID.size() < 2 )
4139 aListOfListOfElementsID.pop_back();
4140 if ( i > 0 ) aTPythonDump << ", ";
4141 aTPythonDump << anElemsIDGroup;
4144 getEditor().MergeElements(aListOfListOfElementsID);
4146 declareMeshModified( /*isReComputeSafe=*/true );
4148 aTPythonDump << "] )";
4150 SMESH_CATCH( SMESH::throwCorbaException );
4153 //=======================================================================
4154 //function : MergeEqualElements
4156 //=======================================================================
4158 void SMESH_MeshEditor_i::MergeEqualElements()
4159 throw (SALOME::SALOME_Exception)
4164 getEditor().MergeEqualElements();
4166 declareMeshModified( /*isReComputeSafe=*/true );
4168 TPythonDump() << this << ".MergeEqualElements()";
4170 SMESH_CATCH( SMESH::throwCorbaException );
4173 //=============================================================================
4175 * Move the node to a given point
4177 //=============================================================================
4179 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4183 throw (SALOME::SALOME_Exception)
4186 initData(/*deleteSearchers=*/false);
4188 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4192 if ( theNodeSearcher )
4193 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4195 if ( myIsPreviewMode ) // make preview data
4197 // in a preview mesh, make edges linked to a node
4198 TPreviewMesh& tmpMesh = *getPreviewMesh();
4199 TIDSortedElemSet linkedNodes;
4200 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4201 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4202 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4203 for ( ; nIt != linkedNodes.end(); ++nIt )
4205 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4206 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4210 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4211 // fill preview data
4213 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4214 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4216 getMeshDS()->MoveNode(node, x, y, z);
4218 if ( !myIsPreviewMode )
4220 // Update Python script
4221 TPythonDump() << "isDone = " << this << ".MoveNode( "
4222 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4223 declareMeshModified( /*isReComputeSafe=*/false );
4226 SMESH_CATCH( SMESH::throwCorbaException );
4231 //================================================================================
4233 * \brief Return ID of node closest to a given point
4235 //================================================================================
4237 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4240 throw (SALOME::SALOME_Exception)
4243 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4245 if ( !theNodeSearcher ) {
4246 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4249 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4250 return node->GetID();
4252 SMESH_CATCH( SMESH::throwCorbaException );
4256 //================================================================================
4258 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4259 * move the node closest to the point to point's location and return ID of the node
4261 //================================================================================
4263 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4266 CORBA::Long theNodeID)
4267 throw (SALOME::SALOME_Exception)
4270 // We keep theNodeSearcher until any mesh modification:
4271 // 1) initData() deletes theNodeSearcher at any edition,
4272 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4274 initData(/*deleteSearchers=*/false);
4276 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4278 int nodeID = theNodeID;
4279 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4280 if ( !node ) // preview moving node
4282 if ( !theNodeSearcher ) {
4283 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4286 node = theNodeSearcher->FindClosestTo( p );
4289 nodeID = node->GetID();
4290 if ( myIsPreviewMode ) // make preview data
4292 // in a preview mesh, make edges linked to a node
4293 TPreviewMesh tmpMesh = *getPreviewMesh();
4294 TIDSortedElemSet linkedNodes;
4295 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4296 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4297 for ( ; nIt != linkedNodes.end(); ++nIt )
4299 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4300 tmpMesh.Copy( &edge );
4303 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4305 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4306 // fill preview data
4308 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4310 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4314 getMeshDS()->MoveNode(node, x, y, z);
4318 if ( !myIsPreviewMode )
4320 TPythonDump() << "nodeID = " << this
4321 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4322 << ", " << nodeID << " )";
4324 declareMeshModified( /*isReComputeSafe=*/false );
4329 SMESH_CATCH( SMESH::throwCorbaException );
4333 //=======================================================================
4335 * Return elements of given type where the given point is IN or ON.
4337 * 'ALL' type means elements of any type excluding nodes
4339 //=======================================================================
4341 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4344 SMESH::ElementType type)
4345 throw (SALOME::SALOME_Exception)
4348 SMESH::long_array_var res = new SMESH::long_array;
4349 vector< const SMDS_MeshElement* > foundElems;
4351 theSearchersDeleter.Set( myMesh );
4352 if ( !theElementSearcher ) {
4353 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4355 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4356 SMDSAbs_ElementType( type ),
4358 res->length( foundElems.size() );
4359 for ( int i = 0; i < foundElems.size(); ++i )
4360 res[i] = foundElems[i]->GetID();
4364 SMESH_CATCH( SMESH::throwCorbaException );
4368 //=======================================================================
4369 //function : FindAmongElementsByPoint
4370 //purpose : Searching among the given elements, return elements of given type
4371 // where the given point is IN or ON.
4372 // 'ALL' type means elements of any type excluding nodes
4373 //=======================================================================
4376 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4380 SMESH::ElementType type)
4381 throw (SALOME::SALOME_Exception)
4384 SMESH::long_array_var res = new SMESH::long_array;
4386 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4387 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4388 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4389 type != types[0] ) // but search of elements of dim > 0
4392 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4393 return FindElementsByPoint( x,y,z, type );
4395 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4397 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4398 if ( !theElementSearcher )
4400 // create a searcher from elementIDs
4401 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4402 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4404 if ( !idSourceToSet( elementIDs, meshDS, elements,
4405 SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4408 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4409 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4411 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4414 vector< const SMDS_MeshElement* > foundElems;
4416 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4417 SMDSAbs_ElementType( type ),
4419 res->length( foundElems.size() );
4420 for ( int i = 0; i < foundElems.size(); ++i )
4421 res[i] = foundElems[i]->GetID();
4425 SMESH_CATCH( SMESH::throwCorbaException );
4429 //=======================================================================
4430 //function : GetPointState
4431 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4432 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4433 //=======================================================================
4435 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4438 throw (SALOME::SALOME_Exception)
4441 theSearchersDeleter.Set( myMesh );
4442 if ( !theElementSearcher ) {
4443 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4445 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4447 SMESH_CATCH( SMESH::throwCorbaException );
4451 //=======================================================================
4452 //function : convError
4454 //=======================================================================
4456 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4458 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4462 RETCASE( SEW_BORDER1_NOT_FOUND );
4463 RETCASE( SEW_BORDER2_NOT_FOUND );
4464 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4465 RETCASE( SEW_BAD_SIDE_NODES );
4466 RETCASE( SEW_VOLUMES_TO_SPLIT );
4467 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4468 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4469 RETCASE( SEW_BAD_SIDE1_NODES );
4470 RETCASE( SEW_BAD_SIDE2_NODES );
4472 return SMESH::SMESH_MeshEditor::SEW_OK;
4475 //=======================================================================
4476 //function : SewFreeBorders
4478 //=======================================================================
4480 SMESH::SMESH_MeshEditor::Sew_Error
4481 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4482 CORBA::Long SecondNodeID1,
4483 CORBA::Long LastNodeID1,
4484 CORBA::Long FirstNodeID2,
4485 CORBA::Long SecondNodeID2,
4486 CORBA::Long LastNodeID2,
4487 CORBA::Boolean CreatePolygons,
4488 CORBA::Boolean CreatePolyedrs)
4489 throw (SALOME::SALOME_Exception)
4494 SMESHDS_Mesh* aMesh = getMeshDS();
4496 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4497 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4498 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4499 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4500 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4501 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4503 if (!aBorderFirstNode ||
4504 !aBorderSecondNode||
4506 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4507 if (!aSide2FirstNode ||
4508 !aSide2SecondNode ||
4510 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4512 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4513 << FirstNodeID1 << ", "
4514 << SecondNodeID1 << ", "
4515 << LastNodeID1 << ", "
4516 << FirstNodeID2 << ", "
4517 << SecondNodeID2 << ", "
4518 << LastNodeID2 << ", "
4519 << CreatePolygons<< ", "
4520 << CreatePolyedrs<< " )";
4522 SMESH::SMESH_MeshEditor::Sew_Error error =
4523 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4534 declareMeshModified( /*isReComputeSafe=*/false );
4537 SMESH_CATCH( SMESH::throwCorbaException );
4538 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4542 //=======================================================================
4543 //function : SewConformFreeBorders
4545 //=======================================================================
4547 SMESH::SMESH_MeshEditor::Sew_Error
4548 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4549 CORBA::Long SecondNodeID1,
4550 CORBA::Long LastNodeID1,
4551 CORBA::Long FirstNodeID2,
4552 CORBA::Long SecondNodeID2)
4553 throw (SALOME::SALOME_Exception)
4558 SMESHDS_Mesh* aMesh = getMeshDS();
4560 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4561 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4562 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4563 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4564 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4565 const SMDS_MeshNode* aSide2ThirdNode = 0;
4567 if (!aBorderFirstNode ||
4568 !aBorderSecondNode||
4570 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4571 if (!aSide2FirstNode ||
4573 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4575 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4576 << FirstNodeID1 << ", "
4577 << SecondNodeID1 << ", "
4578 << LastNodeID1 << ", "
4579 << FirstNodeID2 << ", "
4580 << SecondNodeID2 << " )";
4582 SMESH::SMESH_MeshEditor::Sew_Error error =
4583 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4592 declareMeshModified( /*isReComputeSafe=*/false );
4595 SMESH_CATCH( SMESH::throwCorbaException );
4596 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4600 //=======================================================================
4601 //function : SewBorderToSide
4603 //=======================================================================
4605 SMESH::SMESH_MeshEditor::Sew_Error
4606 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4607 CORBA::Long SecondNodeIDOnFreeBorder,
4608 CORBA::Long LastNodeIDOnFreeBorder,
4609 CORBA::Long FirstNodeIDOnSide,
4610 CORBA::Long LastNodeIDOnSide,
4611 CORBA::Boolean CreatePolygons,
4612 CORBA::Boolean CreatePolyedrs)
4613 throw (SALOME::SALOME_Exception)
4618 SMESHDS_Mesh* aMesh = getMeshDS();
4620 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4621 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4622 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4623 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4624 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4625 const SMDS_MeshNode* aSide2ThirdNode = 0;
4627 if (!aBorderFirstNode ||
4628 !aBorderSecondNode||
4630 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4631 if (!aSide2FirstNode ||
4633 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4635 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4636 << FirstNodeIDOnFreeBorder << ", "
4637 << SecondNodeIDOnFreeBorder << ", "
4638 << LastNodeIDOnFreeBorder << ", "
4639 << FirstNodeIDOnSide << ", "
4640 << LastNodeIDOnSide << ", "
4641 << CreatePolygons << ", "
4642 << CreatePolyedrs << ") ";
4644 SMESH::SMESH_MeshEditor::Sew_Error error =
4645 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4655 declareMeshModified( /*isReComputeSafe=*/false );
4658 SMESH_CATCH( SMESH::throwCorbaException );
4659 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4663 //=======================================================================
4664 //function : SewSideElements
4666 //=======================================================================
4668 SMESH::SMESH_MeshEditor::Sew_Error
4669 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4670 const SMESH::long_array& IDsOfSide2Elements,
4671 CORBA::Long NodeID1OfSide1ToMerge,
4672 CORBA::Long NodeID1OfSide2ToMerge,
4673 CORBA::Long NodeID2OfSide1ToMerge,
4674 CORBA::Long NodeID2OfSide2ToMerge)
4675 throw (SALOME::SALOME_Exception)
4680 SMESHDS_Mesh* aMesh = getMeshDS();
4682 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
4683 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
4684 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4685 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4687 if (!aFirstNode1ToMerge ||
4688 !aFirstNode2ToMerge )
4689 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4690 if (!aSecondNode1ToMerge||
4691 !aSecondNode2ToMerge)
4692 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4694 TIDSortedElemSet aSide1Elems, aSide2Elems;
4695 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4696 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4698 TPythonDump() << "error = " << this << ".SewSideElements( "
4699 << IDsOfSide1Elements << ", "
4700 << IDsOfSide2Elements << ", "
4701 << NodeID1OfSide1ToMerge << ", "
4702 << NodeID1OfSide2ToMerge << ", "
4703 << NodeID2OfSide1ToMerge << ", "
4704 << NodeID2OfSide2ToMerge << ")";
4706 SMESH::SMESH_MeshEditor::Sew_Error error =
4707 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
4710 aSecondNode1ToMerge,
4711 aSecondNode2ToMerge));
4713 declareMeshModified( /*isReComputeSafe=*/false );
4716 SMESH_CATCH( SMESH::throwCorbaException );
4717 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4720 //================================================================================
4722 * \brief Set new nodes for given element
4723 * \param ide - element id
4724 * \param newIDs - new node ids
4725 * \retval CORBA::Boolean - true if result is OK
4727 //================================================================================
4729 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4730 const SMESH::long_array& newIDs)
4731 throw (SALOME::SALOME_Exception)
4736 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
4737 if(!elem) return false;
4739 int nbn = newIDs.length();
4741 vector<const SMDS_MeshNode*> aNodes(nbn);
4744 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
4747 aNodes[nbn1] = aNode;
4750 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4751 << ide << ", " << newIDs << " )";
4753 MESSAGE("ChangeElementNodes");
4754 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4756 declareMeshModified( /*isReComputeSafe=*/ !res );
4760 SMESH_CATCH( SMESH::throwCorbaException );
4764 //=======================================================================
4766 * \brief Makes a part of the mesh quadratic or bi-quadratic
4768 //=======================================================================
4770 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
4771 CORBA::Boolean theToBiQuad,
4772 SMESH::SMESH_IDSource_ptr theObject)
4773 throw (SALOME::SALOME_Exception)
4776 TIDSortedElemSet elems;
4778 if ( !( elemsOK = CORBA::is_nil( theObject )))
4780 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
4781 SMDSAbs_All, /*emptyIfIsMesh=*/true );
4785 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
4786 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4788 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
4789 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
4791 declareMeshModified( /*isReComputeSafe=*/false );
4794 SMESH_CATCH( SMESH::throwCorbaException );
4797 //=======================================================================
4798 //function : ConvertFromQuadratic
4800 //=======================================================================
4802 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4803 throw (SALOME::SALOME_Exception)
4805 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
4806 TPythonDump() << this << ".ConvertFromQuadratic()";
4807 declareMeshModified( /*isReComputeSafe=*/!isDone );
4811 //=======================================================================
4812 //function : ConvertToQuadratic
4814 //=======================================================================
4816 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4817 throw (SALOME::SALOME_Exception)
4819 convertToQuadratic( theForce3d, false );
4820 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
4823 //================================================================================
4825 * \brief Makes a part of the mesh quadratic
4827 //================================================================================
4829 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
4830 SMESH::SMESH_IDSource_ptr theObject)
4831 throw (SALOME::SALOME_Exception)
4833 convertToQuadratic( theForce3d, false, theObject );
4834 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
4837 //================================================================================
4839 * \brief Makes a part of the mesh bi-quadratic
4841 //================================================================================
4843 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
4844 SMESH::SMESH_IDSource_ptr theObject)
4845 throw (SALOME::SALOME_Exception)
4847 convertToQuadratic( theForce3d, true, theObject );
4848 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
4851 //================================================================================
4853 * \brief Makes a part of the mesh linear
4855 //================================================================================
4857 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
4858 throw (SALOME::SALOME_Exception)
4864 TIDSortedElemSet elems;
4865 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
4867 if ( elems.empty() )
4869 ConvertFromQuadratic();
4871 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
4873 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4877 getEditor().ConvertFromQuadratic(elems);
4880 declareMeshModified( /*isReComputeSafe=*/false );
4882 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
4884 SMESH_CATCH( SMESH::throwCorbaException );
4887 //=======================================================================
4888 //function : makeMesh
4889 //purpose : create a named imported mesh
4890 //=======================================================================
4892 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4894 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4895 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4896 SALOMEDS::Study_var study = gen->GetCurrentStudy();
4897 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
4898 gen->SetName( meshSO, theMeshName, "Mesh" );
4899 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4901 return mesh._retn();
4904 //=======================================================================
4905 //function : dumpGroupsList
4907 //=======================================================================
4909 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
4910 const SMESH::ListOfGroups * theGroupList)
4912 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
4913 if ( isDumpGroupList )
4914 theDumpPython << theGroupList << " = ";
4917 //================================================================================
4919 \brief Generates the unique group name.
4920 \param thePrefix name prefix
4923 //================================================================================
4925 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
4927 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4928 set<string> groupNames;
4930 // Get existing group names
4931 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
4932 SMESH::SMESH_GroupBase_var aGroup = groups[i];
4933 if (CORBA::is_nil(aGroup))
4936 CORBA::String_var name = aGroup->GetName();
4937 groupNames.insert( name.in() );
4941 string name = thePrefix;
4944 while (!groupNames.insert(name).second)
4945 name = SMESH_Comment( thePrefix ) << "_" << index++;
4950 //================================================================================
4952 * \brief Prepare SMESH_IDSource for work
4954 //================================================================================
4956 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
4958 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
4960 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
4961 filter->SetMesh( mesh );
4964 //================================================================================
4966 * \brief Retrieve elements of given type from SMESH_IDSource
4968 //================================================================================
4970 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
4971 const SMESHDS_Mesh* theMeshDS,
4972 TIDSortedElemSet& theElemSet,
4973 const SMDSAbs_ElementType theType,
4974 const bool emptyIfIsMesh,
4975 IDSource_Error* error)
4978 if ( error ) *error = IDSource_OK;
4980 if ( CORBA::is_nil( theIDSource ) )
4982 if ( error ) *error = IDSource_INVALID;
4985 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
4987 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
4988 *error = IDSource_EMPTY;
4991 prepareIdSource( theIDSource );
4992 SMESH::long_array_var anIDs = theIDSource->GetIDs();
4993 if ( anIDs->length() == 0 )
4995 if ( error ) *error = IDSource_EMPTY;
4998 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
4999 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5001 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5003 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5007 if ( error ) *error = IDSource_INVALID;
5013 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5014 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5016 if ( error ) *error = IDSource_INVALID;
5023 //================================================================================
5025 * \brief Duplicates given elements, i.e. creates new elements based on the
5026 * same nodes as the given ones.
5027 * \param theElements - container of elements to duplicate.
5028 * \param theGroupName - a name of group to contain the generated elements.
5029 * If a group with such a name already exists, the new elements
5030 * are added to the existng group, else a new group is created.
5031 * If \a theGroupName is empty, new elements are not added
5033 * \return a group where the new elements are added. NULL if theGroupName == "".
5036 //================================================================================
5038 SMESH::SMESH_Group_ptr
5039 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5040 const char* theGroupName)
5041 throw (SALOME::SALOME_Exception)
5043 SMESH::SMESH_Group_var newGroup;
5050 TIDSortedElemSet elems;
5051 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5053 getEditor().DoubleElements( elems );
5055 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5058 SMESH::ElementType type =
5059 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5060 // find existing group
5061 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5062 for ( size_t i = 0; i < groups->length(); ++i )
5063 if ( groups[i]->GetType() == type )
5065 CORBA::String_var name = groups[i]->GetName();
5066 if ( strcmp( name, theGroupName ) == 0 ) {
5067 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5071 // create a new group
5072 if ( newGroup->_is_nil() )
5073 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5075 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5077 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5078 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5079 for ( int i = 1; i <= aSeq.Length(); i++ )
5080 groupDS->SMDSGroup().Add( aSeq(i) );
5085 if ( !newGroup->_is_nil() )
5086 pyDump << newGroup << " = ";
5087 pyDump << this << ".DoubleElements( "
5088 << theElements << ", " << "'" << theGroupName <<"')";
5090 SMESH_CATCH( SMESH::throwCorbaException );
5092 return newGroup._retn();
5095 //================================================================================
5097 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5098 \param theNodes - identifiers of nodes to be doubled
5099 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5100 nodes. If list of element identifiers is empty then nodes are doubled but
5101 they not assigned to elements
5102 \return TRUE if operation has been completed successfully, FALSE otherwise
5103 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5105 //================================================================================
5107 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5108 const SMESH::long_array& theModifiedElems )
5109 throw (SALOME::SALOME_Exception)
5114 list< int > aListOfNodes;
5116 for ( i = 0, n = theNodes.length(); i < n; i++ )
5117 aListOfNodes.push_back( theNodes[ i ] );
5119 list< int > aListOfElems;
5120 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5121 aListOfElems.push_back( theModifiedElems[ i ] );
5123 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5125 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5127 // Update Python script
5128 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5132 SMESH_CATCH( SMESH::throwCorbaException );
5136 //================================================================================
5138 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5139 This method provided for convenience works as DoubleNodes() described above.
5140 \param theNodeId - identifier of node to be doubled.
5141 \param theModifiedElems - identifiers of elements to be updated.
5142 \return TRUE if operation has been completed successfully, FALSE otherwise
5143 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5145 //================================================================================
5147 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5148 const SMESH::long_array& theModifiedElems )
5149 throw (SALOME::SALOME_Exception)
5152 SMESH::long_array_var aNodes = new SMESH::long_array;
5153 aNodes->length( 1 );
5154 aNodes[ 0 ] = theNodeId;
5156 TPythonDump pyDump; // suppress dump by the next line
5158 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5160 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5164 SMESH_CATCH( SMESH::throwCorbaException );
5168 //================================================================================
5170 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5171 This method provided for convenience works as DoubleNodes() described above.
5172 \param theNodes - group of nodes to be doubled.
5173 \param theModifiedElems - group of elements to be updated.
5174 \return TRUE if operation has been completed successfully, FALSE otherwise
5175 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5177 //================================================================================
5179 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5180 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5181 throw (SALOME::SALOME_Exception)
5184 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5187 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5188 SMESH::long_array_var aModifiedElems;
5189 if ( !CORBA::is_nil( theModifiedElems ) )
5190 aModifiedElems = theModifiedElems->GetListOfID();
5193 aModifiedElems = new SMESH::long_array;
5194 aModifiedElems->length( 0 );
5197 TPythonDump pyDump; // suppress dump by the next line
5199 bool done = DoubleNodes( aNodes, aModifiedElems );
5201 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5205 SMESH_CATCH( SMESH::throwCorbaException );
5209 //================================================================================
5211 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5212 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5213 * \param theNodes - group of nodes to be doubled.
5214 * \param theModifiedElems - group of elements to be updated.
5215 * \return a new group with newly created nodes
5216 * \sa DoubleNodeGroup()
5218 //================================================================================
5220 SMESH::SMESH_Group_ptr
5221 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5222 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5223 throw (SALOME::SALOME_Exception)
5226 SMESH::SMESH_Group_var aNewGroup;
5228 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5229 return aNewGroup._retn();
5232 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5233 SMESH::long_array_var aModifiedElems;
5234 if ( !CORBA::is_nil( theModifiedElems ) )
5235 aModifiedElems = theModifiedElems->GetListOfID();
5237 aModifiedElems = new SMESH::long_array;
5238 aModifiedElems->length( 0 );
5241 TPythonDump pyDump; // suppress dump by the next line
5243 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5246 // Create group with newly created nodes
5247 SMESH::long_array_var anIds = GetLastCreatedNodes();
5248 if (anIds->length() > 0) {
5249 string anUnindexedName (theNodes->GetName());
5250 string aNewName = generateGroupName(anUnindexedName + "_double");
5251 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5252 aNewGroup->Add(anIds);
5253 pyDump << aNewGroup << " = ";
5257 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5258 << theModifiedElems << " )";
5260 return aNewGroup._retn();
5262 SMESH_CATCH( SMESH::throwCorbaException );
5266 //================================================================================
5268 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5269 This method provided for convenience works as DoubleNodes() described above.
5270 \param theNodes - list of groups of nodes to be doubled
5271 \param theModifiedElems - list of groups of elements to be updated.
5272 \return TRUE if operation has been completed successfully, FALSE otherwise
5273 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5275 //================================================================================
5277 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5278 const SMESH::ListOfGroups& theModifiedElems )
5279 throw (SALOME::SALOME_Exception)
5284 std::list< int > aNodes;
5286 for ( i = 0, n = theNodes.length(); i < n; i++ )
5288 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5289 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5291 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5292 for ( j = 0, m = aCurr->length(); j < m; j++ )
5293 aNodes.push_back( aCurr[ j ] );
5297 std::list< int > anElems;
5298 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5300 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5301 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5303 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5304 for ( j = 0, m = aCurr->length(); j < m; j++ )
5305 anElems.push_back( aCurr[ j ] );
5309 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5311 declareMeshModified( /*isReComputeSafe=*/false );
5313 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5317 SMESH_CATCH( SMESH::throwCorbaException );
5321 //================================================================================
5323 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5324 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5325 * \param theNodes - group of nodes to be doubled.
5326 * \param theModifiedElems - group of elements to be updated.
5327 * \return a new group with newly created nodes
5328 * \sa DoubleNodeGroups()
5330 //================================================================================
5332 SMESH::SMESH_Group_ptr
5333 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5334 const SMESH::ListOfGroups& theModifiedElems )
5335 throw (SALOME::SALOME_Exception)
5337 SMESH::SMESH_Group_var aNewGroup;
5339 TPythonDump pyDump; // suppress dump by the next line
5341 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5345 // Create group with newly created nodes
5346 SMESH::long_array_var anIds = GetLastCreatedNodes();
5347 if (anIds->length() > 0) {
5348 string anUnindexedName (theNodes[0]->GetName());
5349 string aNewName = generateGroupName(anUnindexedName + "_double");
5350 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5351 aNewGroup->Add(anIds);
5352 pyDump << aNewGroup << " = ";
5356 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5357 << theModifiedElems << " )";
5359 return aNewGroup._retn();
5363 //================================================================================
5365 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5366 \param theElems - the list of elements (edges or faces) to be replicated
5367 The nodes for duplication could be found from these elements
5368 \param theNodesNot - list of nodes to NOT replicate
5369 \param theAffectedElems - the list of elements (cells and edges) to which the
5370 replicated nodes should be associated to.
5371 \return TRUE if operation has been completed successfully, FALSE otherwise
5372 \sa DoubleNodeGroup(), DoubleNodeGroups()
5374 //================================================================================
5376 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5377 const SMESH::long_array& theNodesNot,
5378 const SMESH::long_array& theAffectedElems )
5379 throw (SALOME::SALOME_Exception)
5384 SMESHDS_Mesh* aMeshDS = getMeshDS();
5385 TIDSortedElemSet anElems, aNodes, anAffected;
5386 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5387 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5388 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5390 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5392 // Update Python script
5393 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5394 << theNodesNot << ", " << theAffectedElems << " )";
5396 declareMeshModified( /*isReComputeSafe=*/false );
5399 SMESH_CATCH( SMESH::throwCorbaException );
5403 //================================================================================
5405 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5406 \param theElems - the list of elements (edges or faces) to be replicated
5407 The nodes for duplication could be found from these elements
5408 \param theNodesNot - list of nodes to NOT replicate
5409 \param theShape - shape to detect affected elements (element which geometric center
5410 located on or inside shape).
5411 The replicated nodes should be associated to affected elements.
5412 \return TRUE if operation has been completed successfully, FALSE otherwise
5413 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5415 //================================================================================
5417 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5418 const SMESH::long_array& theNodesNot,
5419 GEOM::GEOM_Object_ptr theShape )
5420 throw (SALOME::SALOME_Exception)
5426 SMESHDS_Mesh* aMeshDS = getMeshDS();
5427 TIDSortedElemSet anElems, aNodes;
5428 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5429 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5431 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5432 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5434 // Update Python script
5435 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5436 << theNodesNot << ", " << theShape << " )";
5438 declareMeshModified( /*isReComputeSafe=*/false );
5441 SMESH_CATCH( SMESH::throwCorbaException );
5445 //================================================================================
5447 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5448 \param theElems - group of of elements (edges or faces) to be replicated
5449 \param theNodesNot - group of nodes not to replicated
5450 \param theAffectedElems - group of elements to which the replicated nodes
5451 should be associated to.
5452 \return TRUE if operation has been completed successfully, FALSE otherwise
5453 \sa DoubleNodes(), DoubleNodeGroups()
5455 //================================================================================
5458 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5459 SMESH::SMESH_GroupBase_ptr theNodesNot,
5460 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5461 throw (SALOME::SALOME_Exception)
5464 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5470 SMESHDS_Mesh* aMeshDS = getMeshDS();
5471 TIDSortedElemSet anElems, aNodes, anAffected;
5472 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5473 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5474 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5476 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5478 // Update Python script
5479 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5480 << theNodesNot << ", " << theAffectedElems << " )";
5482 declareMeshModified( /*isReComputeSafe=*/false );
5485 SMESH_CATCH( SMESH::throwCorbaException );
5489 //================================================================================
5491 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5492 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5493 * \param theElems - group of of elements (edges or faces) to be replicated
5494 * \param theNodesNot - group of nodes not to replicated
5495 * \param theAffectedElems - group of elements to which the replicated nodes
5496 * should be associated to.
5497 * \return a new group with newly created elements
5498 * \sa DoubleNodeElemGroup()
5500 //================================================================================
5502 SMESH::SMESH_Group_ptr
5503 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5504 SMESH::SMESH_GroupBase_ptr theNodesNot,
5505 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5506 throw (SALOME::SALOME_Exception)
5509 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5513 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5514 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5516 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5518 << theNodesNot << ", "
5519 << theAffectedElems << " )";
5521 return elemGroup._retn();
5524 //================================================================================
5526 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5527 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5528 * \param theElems - group of of elements (edges or faces) to be replicated
5529 * \param theNodesNot - group of nodes not to replicated
5530 * \param theAffectedElems - group of elements to which the replicated nodes
5531 * should be associated to.
5532 * \return a new group with newly created elements
5533 * \sa DoubleNodeElemGroup()
5535 //================================================================================
5537 SMESH::ListOfGroups*
5538 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5539 SMESH::SMESH_GroupBase_ptr theNodesNot,
5540 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5541 CORBA::Boolean theElemGroupNeeded,
5542 CORBA::Boolean theNodeGroupNeeded)
5543 throw (SALOME::SALOME_Exception)
5546 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5547 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5548 aTwoGroups->length( 2 );
5550 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5551 return aTwoGroups._retn();
5556 SMESHDS_Mesh* aMeshDS = getMeshDS();
5557 TIDSortedElemSet anElems, aNodes, anAffected;
5558 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5559 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5560 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5563 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5565 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5571 // Create group with newly created elements
5572 CORBA::String_var elemGroupName = theElems->GetName();
5573 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5574 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5576 SMESH::long_array_var anIds = GetLastCreatedElems();
5577 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5578 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5579 aNewElemGroup->Add(anIds);
5581 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5583 SMESH::long_array_var anIds = GetLastCreatedNodes();
5584 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5585 aNewNodeGroup->Add(anIds);
5589 // Update Python script
5592 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5593 else pyDump << aNewElemGroup << ", ";
5594 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5595 else pyDump << aNewNodeGroup << " ] = ";
5597 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5598 << theNodesNot << ", "
5599 << theAffectedElems << ", "
5600 << theElemGroupNeeded << ", "
5601 << theNodeGroupNeeded <<" )";
5603 aTwoGroups[0] = aNewElemGroup._retn();
5604 aTwoGroups[1] = aNewNodeGroup._retn();
5605 return aTwoGroups._retn();
5607 SMESH_CATCH( SMESH::throwCorbaException );
5611 //================================================================================
5613 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5614 \param theElems - group of of elements (edges or faces) to be replicated
5615 \param theNodesNot - group of nodes not to replicated
5616 \param theShape - shape to detect affected elements (element which geometric center
5617 located on or inside shape).
5618 The replicated nodes should be associated to affected elements.
5619 \return TRUE if operation has been completed successfully, FALSE otherwise
5620 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5622 //================================================================================
5625 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5626 SMESH::SMESH_GroupBase_ptr theNodesNot,
5627 GEOM::GEOM_Object_ptr theShape )
5628 throw (SALOME::SALOME_Exception)
5631 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5637 SMESHDS_Mesh* aMeshDS = getMeshDS();
5638 TIDSortedElemSet anElems, aNodes, anAffected;
5639 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5640 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5642 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5643 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5646 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5648 // Update Python script
5649 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5650 << theNodesNot << ", " << theShape << " )";
5653 SMESH_CATCH( SMESH::throwCorbaException );
5657 //================================================================================
5659 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5660 * \param [in] theGrpList - groups
5661 * \param [in] theMeshDS - mesh
5662 * \param [out] theElemSet - set of elements
5663 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5665 //================================================================================
5667 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5668 SMESHDS_Mesh* theMeshDS,
5669 TIDSortedElemSet& theElemSet,
5670 const bool theIsNodeGrp)
5672 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5674 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5675 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5676 : aGrp->GetType() != SMESH::NODE ) )
5678 SMESH::long_array_var anIDs = aGrp->GetIDs();
5679 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5684 //================================================================================
5686 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5687 This method provided for convenience works as DoubleNodes() described above.
5688 \param theElems - list of groups of elements (edges or faces) to be replicated
5689 \param theNodesNot - list of groups of nodes not to replicated
5690 \param theAffectedElems - group of elements to which the replicated nodes
5691 should be associated to.
5692 \return TRUE if operation has been completed successfully, FALSE otherwise
5693 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5695 //================================================================================
5698 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5699 const SMESH::ListOfGroups& theNodesNot,
5700 const SMESH::ListOfGroups& theAffectedElems)
5701 throw (SALOME::SALOME_Exception)
5707 SMESHDS_Mesh* aMeshDS = getMeshDS();
5708 TIDSortedElemSet anElems, aNodes, anAffected;
5709 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5710 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5711 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5713 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5715 // Update Python script
5716 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5717 << &theNodesNot << ", " << &theAffectedElems << " )";
5719 declareMeshModified( /*isReComputeSafe=*/false );
5722 SMESH_CATCH( SMESH::throwCorbaException );
5726 //================================================================================
5728 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5729 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5730 \param theElems - list of groups of elements (edges or faces) to be replicated
5731 \param theNodesNot - list of groups of nodes not to replicated
5732 \param theAffectedElems - group of elements to which the replicated nodes
5733 should be associated to.
5734 * \return a new group with newly created elements
5735 * \sa DoubleNodeElemGroups()
5737 //================================================================================
5739 SMESH::SMESH_Group_ptr
5740 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5741 const SMESH::ListOfGroups& theNodesNot,
5742 const SMESH::ListOfGroups& theAffectedElems)
5743 throw (SALOME::SALOME_Exception)
5746 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
5750 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5751 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5753 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
5755 << theNodesNot << ", "
5756 << theAffectedElems << " )";
5758 return elemGroup._retn();
5761 //================================================================================
5763 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5764 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5765 \param theElems - list of groups of elements (edges or faces) to be replicated
5766 \param theNodesNot - list of groups of nodes not to replicated
5767 \param theAffectedElems - group of elements to which the replicated nodes
5768 should be associated to.
5769 * \return a new group with newly created elements
5770 * \sa DoubleNodeElemGroups()
5772 //================================================================================
5774 SMESH::ListOfGroups*
5775 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
5776 const SMESH::ListOfGroups& theNodesNot,
5777 const SMESH::ListOfGroups& theAffectedElems,
5778 CORBA::Boolean theElemGroupNeeded,
5779 CORBA::Boolean theNodeGroupNeeded)
5780 throw (SALOME::SALOME_Exception)
5783 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5784 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5785 aTwoGroups->length( 2 );
5790 SMESHDS_Mesh* aMeshDS = getMeshDS();
5791 TIDSortedElemSet anElems, aNodes, anAffected;
5792 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5793 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5794 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5796 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5798 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5803 // Create group with newly created elements
5804 CORBA::String_var elemGroupName = theElems[0]->GetName();
5805 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5806 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5808 SMESH::long_array_var anIds = GetLastCreatedElems();
5809 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5810 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5811 aNewElemGroup->Add(anIds);
5813 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5815 SMESH::long_array_var anIds = GetLastCreatedNodes();
5816 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5817 aNewNodeGroup->Add(anIds);
5821 // Update Python script
5824 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5825 else pyDump << aNewElemGroup << ", ";
5826 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5827 else pyDump << aNewNodeGroup << " ] = ";
5829 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
5830 << &theNodesNot << ", "
5831 << &theAffectedElems << ", "
5832 << theElemGroupNeeded << ", "
5833 << theNodeGroupNeeded << " )";
5835 aTwoGroups[0] = aNewElemGroup._retn();
5836 aTwoGroups[1] = aNewNodeGroup._retn();
5837 return aTwoGroups._retn();
5839 SMESH_CATCH( SMESH::throwCorbaException );
5843 //================================================================================
5845 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5846 This method provided for convenience works as DoubleNodes() described above.
5847 \param theElems - list of groups of elements (edges or faces) to be replicated
5848 \param theNodesNot - list of groups of nodes not to replicated
5849 \param theShape - shape to detect affected elements (element which geometric center
5850 located on or inside shape).
5851 The replicated nodes should be associated to affected elements.
5852 \return TRUE if operation has been completed successfully, FALSE otherwise
5853 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5855 //================================================================================
5858 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5859 const SMESH::ListOfGroups& theNodesNot,
5860 GEOM::GEOM_Object_ptr theShape )
5861 throw (SALOME::SALOME_Exception)
5867 SMESHDS_Mesh* aMeshDS = getMeshDS();
5868 TIDSortedElemSet anElems, aNodes;
5869 listOfGroupToSet(theElems, aMeshDS, anElems,false );
5870 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5872 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5873 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5875 // Update Python script
5876 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5877 << &theNodesNot << ", " << theShape << " )";
5879 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5882 SMESH_CATCH( SMESH::throwCorbaException );
5886 //================================================================================
5888 \brief Identify the elements that will be affected by node duplication (actual
5889 duplication is not performed.
5890 This method is the first step of DoubleNodeElemGroupsInRegion.
5891 \param theElems - list of groups of elements (edges or faces) to be replicated
5892 \param theNodesNot - list of groups of nodes not to replicated
5893 \param theShape - shape to detect affected elements (element which geometric center
5894 located on or inside shape).
5895 The replicated nodes should be associated to affected elements.
5896 \return groups of affected elements
5897 \sa DoubleNodeElemGroupsInRegion()
5899 //================================================================================
5900 SMESH::ListOfGroups*
5901 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
5902 const SMESH::ListOfGroups& theNodesNot,
5903 GEOM::GEOM_Object_ptr theShape )
5904 throw (SALOME::SALOME_Exception)
5907 MESSAGE("AffectedElemGroupsInRegion");
5908 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
5909 bool isEdgeGroup = false;
5910 bool isFaceGroup = false;
5911 bool isVolumeGroup = false;
5912 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
5913 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
5914 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
5918 ::SMESH_MeshEditor aMeshEditor(myMesh);
5920 SMESHDS_Mesh* aMeshDS = getMeshDS();
5921 TIDSortedElemSet anElems, aNodes;
5922 listOfGroupToSet(theElems, aMeshDS, anElems, false);
5923 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
5925 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
5926 TIDSortedElemSet anAffected;
5927 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
5930 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5935 int lg = anAffected.size();
5936 MESSAGE("lg="<< lg);
5937 SMESH::long_array_var volumeIds = new SMESH::long_array;
5938 volumeIds->length(lg);
5939 SMESH::long_array_var faceIds = new SMESH::long_array;
5940 faceIds->length(lg);
5941 SMESH::long_array_var edgeIds = new SMESH::long_array;
5942 edgeIds->length(lg);
5947 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
5948 for (; eIt != anAffected.end(); ++eIt)
5950 const SMDS_MeshElement* anElem = *eIt;
5953 int elemId = anElem->GetID();
5954 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
5955 volumeIds[ivol++] = elemId;
5956 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
5957 faceIds[iface++] = elemId;
5958 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
5959 edgeIds[iedge++] = elemId;
5961 volumeIds->length(ivol);
5962 faceIds->length(iface);
5963 edgeIds->length(iedge);
5965 aNewVolumeGroup->Add(volumeIds);
5966 aNewFaceGroup->Add(faceIds);
5967 aNewEdgeGroup->Add(edgeIds);
5968 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
5969 isFaceGroup = (aNewFaceGroup->Size() > 0);
5970 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
5974 if (isEdgeGroup) nbGroups++;
5975 if (isFaceGroup) nbGroups++;
5976 if (isVolumeGroup) nbGroups++;
5977 aListOfGroups->length(nbGroups);
5980 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
5981 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
5982 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
5984 // Update Python script
5987 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
5988 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
5989 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
5991 pyDump << this << ".AffectedElemGroupsInRegion( "
5992 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
5994 return aListOfGroups._retn();
5996 SMESH_CATCH( SMESH::throwCorbaException );
6000 //================================================================================
6002 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6003 The created 2D mesh elements based on nodes of free faces of boundary volumes
6004 \return TRUE if operation has been completed successfully, FALSE otherwise
6006 //================================================================================
6008 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6009 throw (SALOME::SALOME_Exception)
6014 bool aResult = getEditor().Make2DMeshFrom3D();
6016 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6018 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6021 SMESH_CATCH( SMESH::throwCorbaException );
6025 //================================================================================
6027 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6028 * The list of groups must contain at least two groups. The groups have to be disjoint:
6029 * no common element into two different groups.
6030 * The nodes of the internal faces at the boundaries of the groups are doubled.
6031 * Optionally, the internal faces are replaced by flat elements.
6032 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6033 * The flat elements are stored in groups of volumes.
6034 * These groups are named according to the position of the group in the list:
6035 * 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.
6036 * 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.
6037 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6038 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6039 * \param theDomains - list of groups of volumes
6040 * \param createJointElems - if TRUE, create the elements
6041 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6042 * the boundary between \a theDomains and the rest mesh
6043 * \return TRUE if operation has been completed successfully, FALSE otherwise
6045 //================================================================================
6048 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6049 CORBA::Boolean createJointElems,
6050 CORBA::Boolean onAllBoundaries )
6051 throw (SALOME::SALOME_Exception)
6058 SMESHDS_Mesh* aMeshDS = getMeshDS();
6060 // MESSAGE("theDomains.length = "<<theDomains.length());
6061 if ( theDomains.length() <= 1 && !onAllBoundaries )
6062 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6064 vector<TIDSortedElemSet> domains;
6065 domains.resize( theDomains.length() );
6067 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6069 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6070 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6072 // if ( aGrp->GetType() != SMESH::VOLUME )
6073 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6074 SMESH::long_array_var anIDs = aGrp->GetIDs();
6075 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6079 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6080 // TODO publish the groups of flat elements in study
6082 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6084 // Update Python script
6085 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6086 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6088 SMESH_CATCH( SMESH::throwCorbaException );
6090 myMesh_i->CreateGroupServants(); // publish created groups if any
6095 //================================================================================
6097 * \brief Double nodes on some external faces and create flat elements.
6098 * Flat elements are mainly used by some types of mechanic calculations.
6100 * Each group of the list must be constituted of faces.
6101 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6102 * @param theGroupsOfFaces - list of groups of faces
6103 * @return TRUE if operation has been completed successfully, FALSE otherwise
6105 //================================================================================
6108 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6109 throw (SALOME::SALOME_Exception)
6114 SMESHDS_Mesh* aMeshDS = getMeshDS();
6116 vector<TIDSortedElemSet> faceGroups;
6119 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6121 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6122 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6124 TIDSortedElemSet faceGroup;
6126 faceGroups.push_back(faceGroup);
6127 SMESH::long_array_var anIDs = aGrp->GetIDs();
6128 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6132 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6133 // TODO publish the groups of flat elements in study
6135 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6137 // Update Python script
6138 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6141 SMESH_CATCH( SMESH::throwCorbaException );
6145 //================================================================================
6147 * \brief Identify all the elements around a geom shape, get the faces delimiting
6150 * Build groups of volume to remove, groups of faces to replace on the skin of the
6151 * object, groups of faces to remove inside the object, (idem edges).
6152 * Build ordered list of nodes at the border of each group of faces to replace
6153 * (to be used to build a geom subshape).
6155 //================================================================================
6157 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6158 GEOM::GEOM_Object_ptr theShape,
6159 const char* groupName,
6160 const SMESH::double_array& theNodesCoords,
6161 SMESH::array_of_long_array_out GroupsOfNodes)
6162 throw (SALOME::SALOME_Exception)
6167 std::vector<std::vector<int> > aListOfListOfNodes;
6168 ::SMESH_MeshEditor aMeshEditor( myMesh );
6170 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6171 if ( !theNodeSearcher )
6172 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6174 vector<double> nodesCoords;
6175 for (int i = 0; i < theNodesCoords.length(); i++)
6177 nodesCoords.push_back( theNodesCoords[i] );
6180 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6181 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6182 nodesCoords, aListOfListOfNodes);
6184 GroupsOfNodes = new SMESH::array_of_long_array;
6185 GroupsOfNodes->length( aListOfListOfNodes.size() );
6186 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6187 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6189 vector<int>& aListOfNodes = *llIt;
6190 vector<int>::iterator lIt = aListOfNodes.begin();;
6191 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6192 aGroup.length( aListOfNodes.size() );
6193 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6194 aGroup[ j ] = (*lIt);
6196 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6199 << ", '" << groupName << "', "
6200 << theNodesCoords << " )";
6202 SMESH_CATCH( SMESH::throwCorbaException );
6205 // issue 20749 ===================================================================
6207 * \brief Creates missing boundary elements
6208 * \param elements - elements whose boundary is to be checked
6209 * \param dimension - defines type of boundary elements to create
6210 * \param groupName - a name of group to store created boundary elements in,
6211 * "" means not to create the group
6212 * \param meshName - a name of new mesh to store created boundary elements in,
6213 * "" means not to create the new mesh
6214 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6215 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6216 * boundary elements will be copied into the new mesh
6217 * \param group - returns the create group, if any
6218 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6220 // ================================================================================
6222 SMESH::SMESH_Mesh_ptr
6223 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6224 SMESH::Bnd_Dimension dim,
6225 const char* groupName,
6226 const char* meshName,
6227 CORBA::Boolean toCopyElements,
6228 CORBA::Boolean toCopyExistingBondary,
6229 SMESH::SMESH_Group_out group)
6230 throw (SALOME::SALOME_Exception)
6235 if ( dim > SMESH::BND_1DFROM2D )
6236 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6238 SMESHDS_Mesh* aMeshDS = getMeshDS();
6240 SMESH::SMESH_Mesh_var mesh_var;
6241 SMESH::SMESH_Group_var group_var;
6245 TIDSortedElemSet elements;
6246 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6247 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6251 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6252 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6254 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6256 // group of new boundary elements
6257 SMESH_Group* smesh_group = 0;
6258 if ( strlen(groupName) )
6260 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6261 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6262 smesh_group = group_i->GetSmeshGroup();
6266 getEditor().MakeBoundaryMesh( elements,
6267 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6271 toCopyExistingBondary);
6274 smesh_mesh->GetMeshDS()->Modified();
6277 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6279 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6280 if ( mesh_var->_is_nil() )
6281 pyDump << myMesh_i->_this() << ", ";
6283 pyDump << mesh_var << ", ";
6284 if ( group_var->_is_nil() )
6285 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6287 pyDump << group_var << " = ";
6288 pyDump << this << ".MakeBoundaryMesh( "
6290 << "SMESH." << dimName[int(dim)] << ", "
6291 << "'" << groupName << "', "
6292 << "'" << meshName<< "', "
6293 << toCopyElements << ", "
6294 << toCopyExistingBondary << ")";
6296 group = group_var._retn();
6297 return mesh_var._retn();
6299 SMESH_CATCH( SMESH::throwCorbaException );
6300 return SMESH::SMESH_Mesh::_nil();
6303 //================================================================================
6305 * \brief Creates missing boundary elements
6306 * \param dimension - defines type of boundary elements to create
6307 * \param groupName - a name of group to store all boundary elements in,
6308 * "" means not to create the group
6309 * \param meshName - a name of a new mesh, which is a copy of the initial
6310 * mesh + created boundary elements; "" means not to create the new mesh
6311 * \param toCopyAll - if true, the whole initial mesh will be copied into
6312 * the new mesh else only boundary elements will be copied into the new mesh
6313 * \param groups - optional groups of elements to make boundary around
6314 * \param mesh - returns the mesh where elements were added to
6315 * \param group - returns the created group, if any
6316 * \retval long - number of added boundary elements
6318 //================================================================================
6320 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6321 const char* groupName,
6322 const char* meshName,
6323 CORBA::Boolean toCopyAll,
6324 const SMESH::ListOfIDSources& groups,
6325 SMESH::SMESH_Mesh_out mesh,
6326 SMESH::SMESH_Group_out group)
6327 throw (SALOME::SALOME_Exception)
6332 if ( dim > SMESH::BND_1DFROM2D )
6333 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6335 // separate groups belonging to this and other mesh
6336 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6337 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6338 groupsOfThisMesh->length( groups.length() );
6339 groupsOfOtherMesh->length( groups.length() );
6340 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6341 for ( int i = 0; i < groups.length(); ++i )
6343 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6344 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6345 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6347 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6348 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6349 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6351 groupsOfThisMesh->length( nbGroups );
6352 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6357 if ( nbGroupsOfOtherMesh > 0 )
6359 // process groups belonging to another mesh
6360 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6361 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6362 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6363 groupsOfOtherMesh, mesh, group );
6366 SMESH::SMESH_Mesh_var mesh_var;
6367 SMESH::SMESH_Group_var group_var;
6370 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6371 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6375 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6377 /*toCopyGroups=*/false,
6378 /*toKeepIDs=*/true);
6380 mesh_var = makeMesh(meshName);
6382 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6383 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6386 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6387 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6389 // group of boundary elements
6390 SMESH_Group* smesh_group = 0;
6391 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6392 if ( strlen(groupName) )
6394 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6395 group_var = mesh_i->CreateGroup( groupType, groupName );
6396 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6397 smesh_group = group_i->GetSmeshGroup();
6400 TIDSortedElemSet elements;
6402 if ( groups.length() > 0 )
6404 for ( int i = 0; i < nbGroups; ++i )
6407 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6409 SMESH::Bnd_Dimension bdim =
6410 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6411 nbAdded += getEditor().MakeBoundaryMesh( elements,
6412 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6415 /*toCopyElements=*/false,
6416 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6417 /*toAddExistingBondary=*/true,
6418 /*aroundElements=*/true);
6424 nbAdded += getEditor().MakeBoundaryMesh( elements,
6425 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6428 /*toCopyElements=*/false,
6429 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6430 /*toAddExistingBondary=*/true);
6432 tgtMesh->GetMeshDS()->Modified();
6434 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6436 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6437 pyDump << "nbAdded, ";
6438 if ( mesh_var->_is_nil() )
6439 pyDump << myMesh_i->_this() << ", ";
6441 pyDump << mesh_var << ", ";
6442 if ( group_var->_is_nil() )
6443 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6445 pyDump << group_var << " = ";
6446 pyDump << this << ".MakeBoundaryElements( "
6447 << "SMESH." << dimName[int(dim)] << ", "
6448 << "'" << groupName << "', "
6449 << "'" << meshName<< "', "
6450 << toCopyAll << ", "
6453 mesh = mesh_var._retn();
6454 group = group_var._retn();
6457 SMESH_CATCH( SMESH::throwCorbaException );