1 // Copyright (C) 2007-2016 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>
68 #include <BRepAdaptor_Surface.hxx>
69 #include <BRep_Tool.hxx>
70 #include <TopExp_Explorer.hxx>
72 #include <TopoDS_Edge.hxx>
73 #include <TopoDS_Face.hxx>
78 #include <Standard_Failure.hxx>
79 #include <Standard_ErrorHandler.hxx>
84 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
86 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
89 using SMESH::TPythonDump;
92 namespace MeshEditor_I {
94 //=============================================================================
96 * \brief Mesh to apply modifications for preview purposes
98 //=============================================================================
100 struct TPreviewMesh: public SMESH_Mesh
102 SMDSAbs_ElementType myPreviewType; // type to show
104 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
105 _isShapeToMesh = (_id =_studyId = 0);
106 _myMeshDS = new SMESHDS_Mesh( _id, true );
107 myPreviewType = previewElements;
109 //!< Copy a set of elements
110 void Copy(const TIDSortedElemSet & theElements,
111 TIDSortedElemSet& theCopyElements,
112 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
113 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
115 // loop on theIDsOfElements
116 TIDSortedElemSet::const_iterator eIt = theElements.begin();
117 for ( ; eIt != theElements.end(); ++eIt )
119 const SMDS_MeshElement* anElem = *eIt;
120 if ( !anElem ) continue;
121 SMDSAbs_ElementType type = anElem->GetType();
122 if ( type == theAvoidType ||
123 ( theSelectType != SMDSAbs_All && type != theSelectType ))
125 const SMDS_MeshElement* anElemCopy;
126 if ( type == SMDSAbs_Node)
127 anElemCopy = Copy( cast2Node(anElem) );
129 anElemCopy = Copy( anElem );
131 theCopyElements.insert( theCopyElements.end(), anElemCopy );
135 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
137 // copy element nodes
138 int anElemNbNodes = anElem->NbNodes();
139 vector< int > anElemNodesID( anElemNbNodes ) ;
140 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
141 for ( int i = 0; itElemNodes->more(); i++)
143 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
145 anElemNodesID[i] = anElemNode->GetID();
148 // creates a corresponding element on copied nodes
149 ::SMESH_MeshEditor::ElemFeatures elemType;
150 elemType.Init( anElem, /*basicOnly=*/false );
151 elemType.SetID( anElem->GetID() );
152 SMDS_MeshElement* anElemCopy =
153 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
157 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
159 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
160 anElemNode->GetID());
164 GetMeshDS()->ClearMesh();
166 void Remove( SMDSAbs_ElementType type )
168 SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator( type );
169 while ( eIt->more() )
170 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
172 };// struct TPreviewMesh
174 static SMESH_NodeSearcher * theNodeSearcher = 0;
175 static SMESH_ElementSearcher * theElementSearcher = 0;
177 //=============================================================================
179 * \brief Deleter of theNodeSearcher at any compute event occurred
181 //=============================================================================
183 struct TSearchersDeleter : public SMESH_subMeshEventListener
186 string myMeshPartIOR;
188 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
189 "SMESH_MeshEditor_i::TSearchersDeleter"),
191 //!< Delete theNodeSearcher
194 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
195 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
197 typedef map < int, SMESH_subMesh * > TDependsOnMap;
198 //!< The meshod called by submesh: do my main job
199 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
200 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
202 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
204 Unset( sm->GetFather() );
207 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
208 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
210 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
217 myMeshPartIOR = meshPartIOR;
218 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
219 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
220 while ( smIt->more() )
223 sm->SetEventListener( this, 0, sm );
227 //!< delete self from all submeshes
228 void Unset(SMESH_Mesh* mesh)
230 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
231 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
232 while ( smIt->more() )
233 smIt->next()->DeleteEventListener( this );
238 } theSearchersDeleter;
240 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
242 TCollection_AsciiString typeStr;
243 switch ( theMirrorType ) {
244 case SMESH::SMESH_MeshEditor::POINT:
245 typeStr = "SMESH.SMESH_MeshEditor.POINT";
247 case SMESH::SMESH_MeshEditor::AXIS:
248 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
251 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
255 //================================================================================
257 * \brief function for conversion of long_array to TIDSortedElemSet
258 * \param IDs - array of IDs
259 * \param aMesh - mesh
260 * \param aMap - collection to fill
261 * \param aType - element type
263 //================================================================================
265 void arrayToSet(const SMESH::long_array & IDs,
266 const SMESHDS_Mesh* aMesh,
267 TIDSortedElemSet& aMap,
268 const SMDSAbs_ElementType aType = SMDSAbs_All,
269 SMDS_MeshElement::Filter* aFilter = NULL)
271 SMDS_MeshElement::NonNullFilter filter1;
272 SMDS_MeshElement::TypeFilter filter2( aType );
274 if ( aFilter == NULL )
275 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
277 SMDS_MeshElement::Filter & filter = *aFilter;
279 if ( aType == SMDSAbs_Node )
280 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
281 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
283 aMap.insert( aMap.end(), elem );
286 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
287 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
289 aMap.insert( aMap.end(), elem );
293 //================================================================================
295 * \brief Retrieve nodes from SMESH_IDSource
297 //================================================================================
299 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
300 const SMESHDS_Mesh* theMeshDS,
301 TIDSortedNodeSet& theNodeSet)
304 if ( CORBA::is_nil( theObject ) )
306 SMESH::array_of_ElementType_var types = theObject->GetTypes();
307 SMESH::long_array_var aElementsId = theObject->GetIDs();
308 if ( types->length() == 1 && types[0] == SMESH::NODE)
310 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
311 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
312 theNodeSet.insert( theNodeSet.end(), n);
314 else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
316 SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
317 while ( nIt->more( ))
318 if ( const SMDS_MeshElement * elem = nIt->next() )
319 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
323 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
324 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
325 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
329 //================================================================================
331 * \brief Returns elements connected to the given elements
333 //================================================================================
335 void getElementsAround(const TIDSortedElemSet& theElements,
336 const SMESHDS_Mesh* theMeshDS,
337 TIDSortedElemSet& theElementsAround)
339 if ( theElements.empty() ) return;
341 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
342 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
344 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
345 return; // all the elements are in theElements
348 elemType = SMDSAbs_All;
350 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
352 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
353 for ( ; elemIt != theElements.end(); ++elemIt )
355 const SMDS_MeshElement* e = *elemIt;
356 int i = e->NbCornerNodes();
359 const SMDS_MeshNode* n = e->GetNode( i );
360 if ( !isNodeChecked[ n->GetID() ])
362 isNodeChecked[ n->GetID() ] = true;
363 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
364 while ( invIt->more() )
366 const SMDS_MeshElement* elemAround = invIt->next();
367 if ( !theElements.count( elemAround ))
368 theElementsAround.insert( elemAround );
375 //================================================================================
377 * \brief Return a string used to detect change of mesh part on which theElementSearcher
378 * is going to be used
380 //================================================================================
382 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
384 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
385 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
386 // take into account passible group modification
387 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
388 partIOR += SMESH_Comment( type );
392 } // namespace MeshEditor_I
394 using namespace MeshEditor_I;
396 //=============================================================================
400 //=============================================================================
402 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
404 myMesh( &theMesh->GetImpl() ),
406 myIsPreviewMode ( isPreview ),
412 //================================================================================
416 //================================================================================
418 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
420 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
421 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
422 poa->deactivate_object(anObjectId.in());
424 //deleteAuxIDSources();
425 delete myPreviewMesh; myPreviewMesh = 0;
426 delete myPreviewEditor; myPreviewEditor = 0;
429 //================================================================================
431 * \brief Returns the mesh
433 //================================================================================
435 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
437 return myMesh_i->_this();
440 //================================================================================
442 * \brief Clear members
444 //================================================================================
446 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
448 if ( myIsPreviewMode ) {
449 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
452 if ( deleteSearchers )
453 TSearchersDeleter::Delete();
455 getEditor().GetError().reset();
456 getEditor().ClearLastCreated();
459 //================================================================================
461 * \brief Increment mesh modif time and optionally record that the performed
462 * modification may influence further mesh re-compute.
463 * \param [in] isReComputeSafe - true if the modification does not influence
464 * further mesh re-compute
466 //================================================================================
468 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
470 myMesh->GetMeshDS()->Modified();
471 if ( !isReComputeSafe )
472 myMesh->SetIsModified( true );
475 //================================================================================
477 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
478 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
480 //================================================================================
482 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
484 if ( myIsPreviewMode && !myPreviewEditor ) {
485 if ( !myPreviewMesh ) getPreviewMesh();
486 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
488 return myIsPreviewMode ? *myPreviewEditor : myEditor;
491 //================================================================================
493 * \brief Initialize and return myPreviewMesh
494 * \param previewElements - type of elements to show in preview
496 * WARNING: call it once per method!
498 //================================================================================
500 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
502 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
504 delete myPreviewEditor;
506 delete myPreviewMesh;
507 myPreviewMesh = new TPreviewMesh( previewElements );
509 myPreviewMesh->Clear();
510 return myPreviewMesh;
513 //================================================================================
515 * Return data of mesh edition preview
517 //================================================================================
519 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
520 throw (SALOME::SALOME_Exception)
523 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
525 if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
527 list<int> aNodesConnectivity;
528 typedef map<int, int> TNodesMap;
531 SMESHDS_Mesh* aMeshDS;
532 std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
534 aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
535 aMeshDS = aMeshPartDS.get();
538 aMeshDS = getEditor().GetMeshDS();
540 myPreviewData = new SMESH::MeshPreviewStruct();
541 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
544 SMDSAbs_ElementType previewType = SMDSAbs_All;
546 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
547 previewType = aPreviewMesh->myPreviewType;
548 switch ( previewType ) {
549 case SMDSAbs_Edge : break;
550 case SMDSAbs_Face : break;
551 case SMDSAbs_Volume: break;
553 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
557 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
559 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
561 while ( itMeshElems->more() ) {
562 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
563 SMDS_NodeIteratorPtr itElemNodes =
564 (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
565 aMeshElem->interlacedNodesIterator() :
566 aMeshElem->nodeIterator() );
567 while ( itElemNodes->more() ) {
568 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
569 int aNodeID = aMeshNode->GetID();
570 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
571 if ( anIter == nodesMap.end() ) {
572 // filling the nodes coordinates
573 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
574 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
575 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
576 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
579 aNodesConnectivity.push_back(anIter->second);
582 // filling the elements types
583 SMDSAbs_ElementType aType = aMeshElem->GetType();
584 bool isPoly = aMeshElem->IsPoly();
585 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
586 myPreviewData->elementTypes[i].isPoly = isPoly;
587 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
590 myPreviewData->nodesXYZ.length( j );
592 // filling the elements connectivities
593 list<int>::iterator aConnIter = aNodesConnectivity.begin();
594 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
595 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
596 myPreviewData->elementConnectivities[i] = *aConnIter;
598 return myPreviewData._retn();
600 SMESH_CATCH( SMESH::throwCorbaException );
604 //================================================================================
606 * \brief Returns list of it's IDs of created nodes
607 * \retval SMESH::long_array* - list of node ID
609 //================================================================================
611 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
612 throw (SALOME::SALOME_Exception)
615 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
617 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
618 myLastCreatedNodes->length( aSeq.Length() );
619 for (int i = 1; i <= aSeq.Length(); i++)
620 myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID();
622 return myLastCreatedNodes._retn();
623 SMESH_CATCH( SMESH::throwCorbaException );
627 //================================================================================
629 * \brief Returns list of it's IDs of created elements
630 * \retval SMESH::long_array* - list of elements' ID
632 //================================================================================
634 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
635 throw (SALOME::SALOME_Exception)
638 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
640 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
641 myLastCreatedElems->length( aSeq.Length() );
642 for ( int i = 1; i <= aSeq.Length(); i++ )
643 myLastCreatedElems[i-1] = aSeq.Value(i)->GetID();
645 return myLastCreatedElems._retn();
646 SMESH_CATCH( SMESH::throwCorbaException );
650 //=======================================================================
651 //function : ClearLastCreated
652 //purpose : Clears sequences of last created elements and nodes
653 //=======================================================================
655 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
658 getEditor().ClearLastCreated();
659 SMESH_CATCH( SMESH::throwCorbaException );
662 //=======================================================================
664 * Returns description of an error/warning occurred during the last operation
665 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
667 //=======================================================================
669 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
670 throw (SALOME::SALOME_Exception)
673 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
674 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
675 if ( errIn && !errIn->IsOK() )
677 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
678 errOut->comment = errIn->myComment.c_str();
679 errOut->subShapeID = -1;
680 errOut->hasBadMesh = !errIn->myBadElements.empty();
685 errOut->subShapeID = -1;
686 errOut->hasBadMesh = false;
689 return errOut._retn();
690 SMESH_CATCH( SMESH::throwCorbaException );
694 //=======================================================================
695 //function : MakeIDSource
696 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
697 // Call UnRegister() as you fininsh using it!!
698 //=======================================================================
700 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
701 public virtual SALOME::GenericObj_i
703 SMESH::long_array _ids;
704 SMESH::ElementType _type;
705 SMESH::SMESH_Mesh_ptr _mesh;
706 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
707 SMESH::long_array* GetMeshInfo() { return 0; }
708 SMESH::long_array* GetNbElementsByType()
710 SMESH::long_array_var aRes = new SMESH::long_array();
711 aRes->length(SMESH::NB_ELEMENT_TYPES);
712 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
713 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
716 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
717 bool IsMeshInfoCorrect() { return true; }
718 SMESH::array_of_ElementType* GetTypes()
720 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
721 if ( _ids.length() > 0 ) {
725 return types._retn();
727 SALOMEDS::TMPFile* GetVtkUgStream()
729 SALOMEDS::TMPFile_var SeqFile;
730 return SeqFile._retn();
734 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
735 SMESH::ElementType type)
737 _IDSource* idSrc = new _IDSource;
738 idSrc->_mesh = myMesh_i->_this();
741 if ( type == SMESH::ALL && ids.length() > 0 )
742 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
744 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
746 return anIDSourceVar._retn();
749 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
751 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
754 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
757 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
759 nbIds = (int) tmpIdSource->_ids.length();
760 return & tmpIdSource->_ids[0];
766 // void SMESH_MeshEditor_i::deleteAuxIDSources()
768 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
769 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
771 // myAuxIDSources.clear();
774 //=============================================================================
778 //=============================================================================
781 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
782 throw (SALOME::SALOME_Exception)
789 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
790 IdList.push_back( IDsOfElements[i] );
792 // Update Python script
793 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
796 bool ret = getEditor().Remove( IdList, false );
798 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
801 SMESH_CATCH( SMESH::throwCorbaException );
805 //=============================================================================
809 //=============================================================================
811 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
812 throw (SALOME::SALOME_Exception)
818 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
819 IdList.push_back( IDsOfNodes[i] );
821 // Update Python script
822 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
824 bool ret = getEditor().Remove( IdList, true );
826 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
829 SMESH_CATCH( SMESH::throwCorbaException );
833 //=============================================================================
837 //=============================================================================
839 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
840 throw (SALOME::SALOME_Exception)
845 // Update Python script
846 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
848 // Create filter to find all orphan nodes
849 SMESH::Controls::Filter::TIdSequence seq;
850 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
851 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
853 // remove orphan nodes (if there are any)
854 list< int > IdList( seq.begin(), seq.end() );
856 int nbNodesBefore = myMesh->NbNodes();
857 getEditor().Remove( IdList, true );
858 int nbNodesAfter = myMesh->NbNodes();
860 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
861 return nbNodesBefore - nbNodesAfter;
863 SMESH_CATCH( SMESH::throwCorbaException );
867 //=============================================================================
871 //=============================================================================
873 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
874 throw (SALOME::SALOME_Exception)
879 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
881 // Update Python script
882 TPythonDump() << "nodeID = " << this << ".AddNode( "
883 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
885 declareMeshModified( /*isReComputeSafe=*/false );
888 SMESH_CATCH( SMESH::throwCorbaException );
892 //=============================================================================
894 * Create 0D element on the given node.
896 //=============================================================================
898 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode,
899 CORBA::Boolean DuplicateElements)
900 throw (SALOME::SALOME_Exception)
905 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
906 SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
908 SMDS_MeshElement* elem = 0;
909 if ( DuplicateElements || !it0D->more() )
910 elem = getMeshDS()->Add0DElement(aNode);
912 // Update Python script
913 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
915 declareMeshModified( /*isReComputeSafe=*/false );
917 return elem ? elem->GetID() : 0;
919 SMESH_CATCH( SMESH::throwCorbaException );
923 //=============================================================================
925 * Create a ball element on the given node.
927 //=============================================================================
929 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
930 throw (SALOME::SALOME_Exception)
935 if ( diameter < std::numeric_limits<double>::min() )
936 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
938 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
939 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
941 // Update Python script
942 TPythonDump() << "ballElem = "
943 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
945 declareMeshModified( /*isReComputeSafe=*/false );
946 return elem ? elem->GetID() : 0;
948 SMESH_CATCH( SMESH::throwCorbaException );
952 //=============================================================================
954 * Create an edge, either linear and quadratic (this is determed
955 * by number of given nodes, two or three)
957 //=============================================================================
959 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
960 throw (SALOME::SALOME_Exception)
965 int NbNodes = IDsOfNodes.length();
966 SMDS_MeshElement* elem = 0;
969 CORBA::Long index1 = IDsOfNodes[0];
970 CORBA::Long index2 = IDsOfNodes[1];
971 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
972 getMeshDS()->FindNode(index2));
974 // Update Python script
975 TPythonDump() << "edge = " << this << ".AddEdge([ "
976 << index1 << ", " << index2 <<" ])";
979 CORBA::Long n1 = IDsOfNodes[0];
980 CORBA::Long n2 = IDsOfNodes[1];
981 CORBA::Long n12 = IDsOfNodes[2];
982 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
983 getMeshDS()->FindNode(n2),
984 getMeshDS()->FindNode(n12));
985 // Update Python script
986 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
987 <<n1<<", "<<n2<<", "<<n12<<" ])";
990 declareMeshModified( /*isReComputeSafe=*/false );
991 return elem ? elem->GetID() : 0;
993 SMESH_CATCH( SMESH::throwCorbaException );
997 //=============================================================================
1001 //=============================================================================
1003 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1004 throw (SALOME::SALOME_Exception)
1009 int NbNodes = IDsOfNodes.length();
1015 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1016 for (int i = 0; i < NbNodes; i++)
1017 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1019 SMDS_MeshElement* elem = 0;
1021 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1022 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1023 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1024 nodes[4], nodes[5]); break;
1025 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1026 nodes[4], nodes[5], nodes[6]); break;
1027 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1028 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1029 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1030 nodes[4], nodes[5], nodes[6], nodes[7],
1032 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1035 // Update Python script
1036 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1038 declareMeshModified( /*isReComputeSafe=*/false );
1040 return elem ? elem->GetID() : 0;
1042 SMESH_CATCH( SMESH::throwCorbaException );
1046 //=============================================================================
1050 //=============================================================================
1052 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1053 throw (SALOME::SALOME_Exception)
1058 int NbNodes = IDsOfNodes.length();
1059 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1060 for (int i = 0; i < NbNodes; i++)
1061 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1064 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1066 // Update Python script
1067 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1069 declareMeshModified( /*isReComputeSafe=*/false );
1070 return elem ? elem->GetID() : 0;
1072 SMESH_CATCH( SMESH::throwCorbaException );
1076 //=============================================================================
1078 * AddQuadPolygonalFace
1080 //=============================================================================
1082 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1083 throw (SALOME::SALOME_Exception)
1088 int NbNodes = IDsOfNodes.length();
1089 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1090 for (int i = 0; i < NbNodes; i++)
1091 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1093 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1095 // Update Python script
1096 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1098 declareMeshModified( /*isReComputeSafe=*/false );
1099 return elem ? elem->GetID() : 0;
1101 SMESH_CATCH( SMESH::throwCorbaException );
1105 //=============================================================================
1107 * Create volume, either linear and quadratic (this is determed
1108 * by number of given nodes)
1110 //=============================================================================
1112 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1113 throw (SALOME::SALOME_Exception)
1118 int NbNodes = IDsOfNodes.length();
1119 vector< const SMDS_MeshNode*> n(NbNodes);
1120 for(int i=0;i<NbNodes;i++)
1121 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1123 SMDS_MeshElement* elem = 0;
1126 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1127 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1128 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1129 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1130 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1131 n[6],n[7],n[8],n[9]);
1133 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1134 n[6],n[7],n[8],n[9],n[10],n[11]);
1136 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1137 n[7],n[8],n[9],n[10],n[11],n[12]);
1139 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1140 n[9],n[10],n[11],n[12],n[13],n[14]);
1142 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1143 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1144 n[15],n[16],n[17],n[18],n[19]);
1146 case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1147 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1150 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1151 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1152 n[15],n[16],n[17],n[18],n[19],
1153 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1157 // Update Python script
1158 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1160 declareMeshModified( /*isReComputeSafe=*/false );
1161 return elem ? elem->GetID() : 0;
1163 SMESH_CATCH( SMESH::throwCorbaException );
1167 //=============================================================================
1169 * AddPolyhedralVolume
1171 //=============================================================================
1172 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1173 const SMESH::long_array & Quantities)
1174 throw (SALOME::SALOME_Exception)
1179 int NbNodes = IDsOfNodes.length();
1180 std::vector<const SMDS_MeshNode*> n (NbNodes);
1181 for (int i = 0; i < NbNodes; i++)
1183 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1184 if (!aNode) return 0;
1188 int NbFaces = Quantities.length();
1189 std::vector<int> q (NbFaces);
1190 for (int j = 0; j < NbFaces; j++)
1191 q[j] = Quantities[j];
1193 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1195 // Update Python script
1196 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1197 << IDsOfNodes << ", " << Quantities << " )";
1199 declareMeshModified( /*isReComputeSafe=*/false );
1200 return elem ? elem->GetID() : 0;
1202 SMESH_CATCH( SMESH::throwCorbaException );
1206 //=============================================================================
1208 * AddPolyhedralVolumeByFaces
1210 //=============================================================================
1212 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1213 throw (SALOME::SALOME_Exception)
1218 int NbFaces = IdsOfFaces.length();
1219 std::vector<const SMDS_MeshNode*> poly_nodes;
1220 std::vector<int> quantities (NbFaces);
1222 for (int i = 0; i < NbFaces; i++) {
1223 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1224 quantities[i] = aFace->NbNodes();
1226 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1227 while (It->more()) {
1228 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1232 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1234 // Update Python script
1235 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1236 << IdsOfFaces << " )";
1238 declareMeshModified( /*isReComputeSafe=*/false );
1239 return elem ? elem->GetID() : 0;
1241 SMESH_CATCH( SMESH::throwCorbaException );
1245 //=============================================================================
1247 // \brief Create 0D elements on all nodes of the given object.
1248 // \param theObject object on whose nodes 0D elements will be created.
1249 // \param theGroupName optional name of a group to add 0D elements created
1250 // and/or found on nodes of \a theObject.
1251 // \param DuplicateElements to add one more 0D element to a node or not.
1252 // \return an object (a new group or a temporary SMESH_IDSource) holding
1253 // ids of new and/or found 0D elements.
1255 //=============================================================================
1257 SMESH::SMESH_IDSource_ptr
1258 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1259 const char* theGroupName,
1260 CORBA::Boolean theDuplicateElements)
1261 throw (SALOME::SALOME_Exception)
1266 SMESH::SMESH_IDSource_var result;
1269 TIDSortedElemSet elements, elems0D;
1270 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1271 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1273 SMESH::long_array_var newElems = new SMESH::long_array;
1274 newElems->length( elems0D.size() );
1275 TIDSortedElemSet::iterator eIt = elems0D.begin();
1276 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1277 newElems[ i ] = (*eIt)->GetID();
1279 SMESH::SMESH_GroupBase_var groupToFill;
1280 if ( theGroupName && strlen( theGroupName ))
1282 // Get existing group named theGroupName
1283 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1284 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1285 SMESH::SMESH_GroupBase_var group = groups[i];
1286 if ( !group->_is_nil() ) {
1287 CORBA::String_var name = group->GetName();
1288 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1289 groupToFill = group;
1294 if ( groupToFill->_is_nil() )
1295 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1296 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1297 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1300 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1302 group_i->Add( newElems );
1303 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1304 pyDump << groupToFill;
1308 result = MakeIDSource( newElems, SMESH::ELEM0D );
1309 pyDump << "elem0DIDs";
1312 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1313 << theObject << ", '" << theGroupName << "' )";
1315 return result._retn();
1317 SMESH_CATCH( SMESH::throwCorbaException );
1321 //=============================================================================
1323 * \brief Bind a node to a vertex
1324 * \param NodeID - node ID
1325 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1326 * \retval boolean - false if NodeID or VertexID is invalid
1328 //=============================================================================
1330 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1331 throw (SALOME::SALOME_Exception)
1335 SMESHDS_Mesh * mesh = getMeshDS();
1336 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1338 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1340 if ( mesh->MaxShapeIndex() < VertexID )
1341 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1343 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1344 if ( shape.ShapeType() != TopAbs_VERTEX )
1345 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1347 mesh->SetNodeOnVertex( node, VertexID );
1349 myMesh->SetIsModified( true );
1351 SMESH_CATCH( SMESH::throwCorbaException );
1354 //=============================================================================
1356 * \brief Store node position on an edge
1357 * \param NodeID - node ID
1358 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1359 * \param paramOnEdge - parameter on edge where the node is located
1360 * \retval boolean - false if any parameter is invalid
1362 //=============================================================================
1364 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1365 CORBA::Double paramOnEdge)
1366 throw (SALOME::SALOME_Exception)
1370 SMESHDS_Mesh * mesh = getMeshDS();
1371 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1373 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1375 if ( mesh->MaxShapeIndex() < EdgeID )
1376 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1378 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1379 if ( shape.ShapeType() != TopAbs_EDGE )
1380 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1383 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1384 if ( paramOnEdge < f || paramOnEdge > l )
1385 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1387 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1389 myMesh->SetIsModified( true );
1391 SMESH_CATCH( SMESH::throwCorbaException );
1394 //=============================================================================
1396 * \brief Store node position on a face
1397 * \param NodeID - node ID
1398 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1399 * \param u - U parameter on face where the node is located
1400 * \param v - V parameter on face where the node is located
1401 * \retval boolean - false if any parameter is invalid
1403 //=============================================================================
1405 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1406 CORBA::Double u, CORBA::Double v)
1407 throw (SALOME::SALOME_Exception)
1410 SMESHDS_Mesh * mesh = getMeshDS();
1411 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1413 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1415 if ( mesh->MaxShapeIndex() < FaceID )
1416 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1418 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1419 if ( shape.ShapeType() != TopAbs_FACE )
1420 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1422 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1423 bool isOut = ( u < surf.FirstUParameter() ||
1424 u > surf.LastUParameter() ||
1425 v < surf.FirstVParameter() ||
1426 v > surf.LastVParameter() );
1430 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1431 << " u( " << surf.FirstUParameter()
1432 << "," << surf.LastUParameter()
1433 << ") v( " << surf.FirstVParameter()
1434 << "," << surf.LastVParameter() << ")" );
1436 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1439 mesh->SetNodeOnFace( node, FaceID, u, v );
1440 myMesh->SetIsModified( true );
1442 SMESH_CATCH( SMESH::throwCorbaException );
1445 //=============================================================================
1447 * \brief Bind a node to a solid
1448 * \param NodeID - node ID
1449 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1450 * \retval boolean - false if NodeID or SolidID is invalid
1452 //=============================================================================
1454 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1455 throw (SALOME::SALOME_Exception)
1458 SMESHDS_Mesh * mesh = getMeshDS();
1459 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1461 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1463 if ( mesh->MaxShapeIndex() < SolidID )
1464 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1466 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1467 if ( shape.ShapeType() != TopAbs_SOLID &&
1468 shape.ShapeType() != TopAbs_SHELL)
1469 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1471 mesh->SetNodeInVolume( node, SolidID );
1473 SMESH_CATCH( SMESH::throwCorbaException );
1476 //=============================================================================
1478 * \brief Bind an element to a shape
1479 * \param ElementID - element ID
1480 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1482 //=============================================================================
1484 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1485 CORBA::Long ShapeID)
1486 throw (SALOME::SALOME_Exception)
1489 SMESHDS_Mesh * mesh = getMeshDS();
1490 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1492 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1494 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1495 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1497 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1498 if ( shape.ShapeType() != TopAbs_EDGE &&
1499 shape.ShapeType() != TopAbs_FACE &&
1500 shape.ShapeType() != TopAbs_SOLID &&
1501 shape.ShapeType() != TopAbs_SHELL )
1502 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1504 mesh->SetMeshElementOnShape( elem, ShapeID );
1506 myMesh->SetIsModified( true );
1508 SMESH_CATCH( SMESH::throwCorbaException );
1511 //=============================================================================
1515 //=============================================================================
1517 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1518 CORBA::Long NodeID2)
1519 throw (SALOME::SALOME_Exception)
1524 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1525 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1529 // Update Python script
1530 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1531 << NodeID1 << ", " << NodeID2 << " )";
1533 int ret = getEditor().InverseDiag ( n1, n2 );
1535 declareMeshModified( /*isReComputeSafe=*/false );
1538 SMESH_CATCH( SMESH::throwCorbaException );
1542 //=============================================================================
1546 //=============================================================================
1548 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1549 CORBA::Long NodeID2)
1550 throw (SALOME::SALOME_Exception)
1555 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1556 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1560 // Update Python script
1561 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1562 << NodeID1 << ", " << NodeID2 << " )";
1565 bool stat = getEditor().DeleteDiag ( n1, n2 );
1567 declareMeshModified( /*isReComputeSafe=*/!stat );
1571 SMESH_CATCH( SMESH::throwCorbaException );
1575 //=============================================================================
1579 //=============================================================================
1581 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1582 throw (SALOME::SALOME_Exception)
1587 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1589 CORBA::Long index = IDsOfElements[i];
1590 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1592 getEditor().Reorient( elem );
1594 // Update Python script
1595 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1597 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1600 SMESH_CATCH( SMESH::throwCorbaException );
1604 //=============================================================================
1608 //=============================================================================
1610 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1611 throw (SALOME::SALOME_Exception)
1616 TPythonDump aTPythonDump; // suppress dump in Reorient()
1618 prepareIdSource( theObject );
1620 SMESH::long_array_var anElementsId = theObject->GetIDs();
1621 CORBA::Boolean isDone = Reorient(anElementsId);
1623 // Update Python script
1624 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1626 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1629 SMESH_CATCH( SMESH::throwCorbaException );
1633 //=======================================================================
1634 //function : Reorient2D
1635 //purpose : Reorient faces contained in \a the2Dgroup.
1636 // the2Dgroup - the mesh or its part to reorient
1637 // theDirection - desired direction of normal of \a theFace
1638 // theFace - ID of face whose orientation is checked.
1639 // It can be < 1 then \a thePoint is used to find a face.
1640 // thePoint - is used to find a face if \a theFace < 1.
1641 // return number of reoriented elements.
1642 //=======================================================================
1644 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1645 const SMESH::DirStruct& theDirection,
1646 CORBA::Long theFace,
1647 const SMESH::PointStruct& thePoint)
1648 throw (SALOME::SALOME_Exception)
1651 initData(/*deleteSearchers=*/false);
1653 TIDSortedElemSet elements;
1654 IDSource_Error error;
1655 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1656 if ( error == IDSource_EMPTY )
1658 if ( error == IDSource_INVALID )
1659 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1662 const SMDS_MeshElement* face = 0;
1665 face = getMeshDS()->FindElement( theFace );
1667 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1668 if ( face->GetType() != SMDSAbs_Face )
1669 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1673 // create theElementSearcher if needed
1674 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1675 if ( !theElementSearcher )
1677 if ( elements.empty() ) // search in the whole mesh
1679 if ( myMesh->NbFaces() == 0 )
1680 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1682 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1686 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1687 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1689 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1693 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1694 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1697 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1698 if ( !elements.empty() && !elements.count( face ))
1699 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1702 const SMESH::PointStruct * P = &theDirection.PS;
1703 gp_Vec dirVec( P->x, P->y, P->z );
1704 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1705 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1707 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1710 declareMeshModified( /*isReComputeSafe=*/false );
1712 TPythonDump() << this << ".Reorient2D( "
1713 << the2Dgroup << ", "
1714 << theDirection << ", "
1716 << thePoint << " )";
1720 SMESH_CATCH( SMESH::throwCorbaException );
1724 //=======================================================================
1725 //function : Reorient2DBy3D
1726 //purpose : Reorient faces basing on orientation of adjacent volumes.
1727 //=======================================================================
1729 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1730 SMESH::SMESH_IDSource_ptr volumeGroup,
1731 CORBA::Boolean outsideNormal)
1732 throw (SALOME::SALOME_Exception)
1737 TIDSortedElemSet volumes;
1738 IDSource_Error volsError;
1739 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1742 for ( size_t i = 0; i < faceGroups.length(); ++i )
1744 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1746 TIDSortedElemSet faces;
1747 IDSource_Error error;
1748 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1749 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1750 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1751 if ( error == IDSource_OK && volsError != IDSource_OK )
1752 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1754 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1756 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1761 declareMeshModified( /*isReComputeSafe=*/false );
1763 TPythonDump() << this << ".Reorient2DBy3D( "
1764 << faceGroups << ", "
1765 << volumeGroup << ", "
1766 << outsideNormal << " )";
1770 SMESH_CATCH( SMESH::throwCorbaException );
1774 //=============================================================================
1776 * \brief Fuse neighbour triangles into quadrangles.
1778 //=============================================================================
1780 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1781 SMESH::NumericalFunctor_ptr Criterion,
1782 CORBA::Double MaxAngle)
1783 throw (SALOME::SALOME_Exception)
1788 SMESHDS_Mesh* aMesh = getMeshDS();
1789 TIDSortedElemSet faces,copyFaces;
1790 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1791 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1792 TIDSortedElemSet* workElements = & faces;
1794 if ( myIsPreviewMode ) {
1795 SMDSAbs_ElementType select = SMDSAbs_Face;
1796 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1797 workElements = & copyFaces;
1800 SMESH::NumericalFunctor_i* aNumericalFunctor =
1801 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1802 SMESH::Controls::NumericalFunctorPtr aCrit;
1803 if ( !aNumericalFunctor )
1804 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1806 aCrit = aNumericalFunctor->GetNumericalFunctor();
1808 if ( !myIsPreviewMode ) {
1809 // Update Python script
1810 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1811 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1814 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1816 declareMeshModified( /*isReComputeSafe=*/!stat );
1819 SMESH_CATCH( SMESH::throwCorbaException );
1823 //=============================================================================
1825 * \brief Fuse neighbour triangles into quadrangles.
1827 //=============================================================================
1829 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1830 SMESH::NumericalFunctor_ptr Criterion,
1831 CORBA::Double MaxAngle)
1832 throw (SALOME::SALOME_Exception)
1837 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1839 prepareIdSource( theObject );
1840 SMESH::long_array_var anElementsId = theObject->GetIDs();
1841 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1843 if ( !myIsPreviewMode ) {
1844 SMESH::NumericalFunctor_i* aNumericalFunctor =
1845 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1847 // Update Python script
1848 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1849 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1854 SMESH_CATCH( SMESH::throwCorbaException );
1858 //=============================================================================
1860 * \brief Split quadrangles into triangles.
1862 //=============================================================================
1864 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1865 SMESH::NumericalFunctor_ptr Criterion)
1866 throw (SALOME::SALOME_Exception)
1871 SMESHDS_Mesh* aMesh = getMeshDS();
1872 TIDSortedElemSet faces;
1873 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1875 SMESH::NumericalFunctor_i* aNumericalFunctor =
1876 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1877 SMESH::Controls::NumericalFunctorPtr aCrit;
1878 if ( !aNumericalFunctor )
1879 aCrit.reset( new SMESH::Controls::AspectRatio() );
1881 aCrit = aNumericalFunctor->GetNumericalFunctor();
1884 // Update Python script
1885 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1887 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1889 declareMeshModified( /*isReComputeSafe=*/false );
1892 SMESH_CATCH( SMESH::throwCorbaException );
1896 //=============================================================================
1898 * \brief Split quadrangles into triangles.
1900 //=============================================================================
1902 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1903 SMESH::NumericalFunctor_ptr Criterion)
1904 throw (SALOME::SALOME_Exception)
1909 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1911 prepareIdSource( theObject );
1912 SMESH::long_array_var anElementsId = theObject->GetIDs();
1913 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1915 SMESH::NumericalFunctor_i* aNumericalFunctor =
1916 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1918 // Update Python script
1919 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1921 declareMeshModified( /*isReComputeSafe=*/false );
1924 SMESH_CATCH( SMESH::throwCorbaException );
1928 //================================================================================
1930 * \brief Split each of quadrangles into 4 triangles.
1931 * \param [in] theObject - theQuads Container of quadrangles to split.
1933 //================================================================================
1935 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1936 throw (SALOME::SALOME_Exception)
1941 TIDSortedElemSet faces;
1942 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1944 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1946 getEditor().QuadTo4Tri( faces );
1947 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1949 SMESH_CATCH( SMESH::throwCorbaException );
1952 //=============================================================================
1954 * \brief Split quadrangles into triangles.
1956 //=============================================================================
1958 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1959 CORBA::Boolean Diag13)
1960 throw (SALOME::SALOME_Exception)
1965 SMESHDS_Mesh* aMesh = getMeshDS();
1966 TIDSortedElemSet faces;
1967 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1969 // Update Python script
1970 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1971 << IDsOfElements << ", " << Diag13 << " )";
1973 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1975 declareMeshModified( /*isReComputeSafe=*/ !stat );
1978 SMESH_CATCH( SMESH::throwCorbaException );
1982 //=============================================================================
1984 * \brief Split quadrangles into triangles.
1986 //=============================================================================
1988 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1989 CORBA::Boolean Diag13)
1990 throw (SALOME::SALOME_Exception)
1995 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
1997 prepareIdSource( theObject );
1998 SMESH::long_array_var anElementsId = theObject->GetIDs();
1999 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2001 // Update Python script
2002 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2003 << theObject << ", " << Diag13 << " )";
2005 declareMeshModified( /*isReComputeSafe=*/!isDone );
2008 SMESH_CATCH( SMESH::throwCorbaException );
2013 //=============================================================================
2015 * Find better splitting of the given quadrangle.
2016 * \param IDOfQuad ID of the quadrangle to be splitted.
2017 * \param Criterion A criterion to choose a diagonal for splitting.
2018 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2019 * diagonal is better, 0 if error occurs.
2021 //=============================================================================
2023 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2024 SMESH::NumericalFunctor_ptr Criterion)
2025 throw (SALOME::SALOME_Exception)
2030 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2031 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2033 SMESH::NumericalFunctor_i* aNumericalFunctor =
2034 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2035 SMESH::Controls::NumericalFunctorPtr aCrit;
2036 if (aNumericalFunctor)
2037 aCrit = aNumericalFunctor->GetNumericalFunctor();
2039 aCrit.reset(new SMESH::Controls::AspectRatio());
2041 int id = getEditor().BestSplit(quad, aCrit);
2042 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2046 SMESH_CATCH( SMESH::throwCorbaException );
2050 //================================================================================
2052 * \brief Split volumic elements into tetrahedrons
2054 //================================================================================
2056 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2057 CORBA::Short methodFlags)
2058 throw (SALOME::SALOME_Exception)
2063 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2064 const int noneFacet = -1;
2065 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2066 while( volIt->more() )
2067 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2069 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2070 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2072 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2073 << elems << ", " << methodFlags << " )";
2075 SMESH_CATCH( SMESH::throwCorbaException );
2078 //================================================================================
2080 * \brief Split hexahedra into triangular prisms
2081 * \param elems - elements to split
2082 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2083 * to split into triangles
2084 * \param methodFlags - flags passing splitting method:
2085 * 1 - split the hexahedron into 2 prisms
2086 * 2 - split the hexahedron into 4 prisms
2088 //================================================================================
2090 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2091 const SMESH::PointStruct & startHexPoint,
2092 const SMESH::DirStruct& facetToSplitNormal,
2093 CORBA::Short methodFlags,
2094 CORBA::Boolean allDomains)
2095 throw (SALOME::SALOME_Exception)
2099 prepareIdSource( elems );
2101 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2104 gp_Dir( facetToSplitNormal.PS.x,
2105 facetToSplitNormal.PS.y,
2106 facetToSplitNormal.PS.z ));
2107 TIDSortedElemSet elemSet;
2108 SMESH::long_array_var anElementsId = elems->GetIDs();
2109 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2110 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2112 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2113 while ( !elemSet.empty() )
2115 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2119 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2120 for ( ; ef != elemFacets.end(); ++ef )
2121 elemSet.erase( ef->first );
2124 if ( methodFlags == 2 )
2125 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2127 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2129 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2130 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2132 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2134 << startHexPoint << ", "
2135 << facetToSplitNormal<< ", "
2136 << methodFlags<< ", "
2137 << allDomains << " )";
2139 SMESH_CATCH( SMESH::throwCorbaException );
2142 //================================================================================
2144 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2145 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2146 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2147 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2148 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2149 * will be split in order to keep the mesh conformal.
2150 * \param elems - elements to split
2152 //================================================================================
2154 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2155 throw (SALOME::SALOME_Exception)
2160 TIDSortedElemSet elemSet;
2161 for ( size_t i = 0; i < theElems.length(); ++i )
2163 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2164 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2165 if ( mesh->GetId() != myMesh_i->GetId() )
2166 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2168 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2170 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2172 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2174 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2175 << theElems << " )";
2177 SMESH_CATCH( SMESH::throwCorbaException );
2180 //=======================================================================
2183 //=======================================================================
2186 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2187 const SMESH::long_array & IDsOfFixedNodes,
2188 CORBA::Long MaxNbOfIterations,
2189 CORBA::Double MaxAspectRatio,
2190 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2191 throw (SALOME::SALOME_Exception)
2193 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2194 MaxAspectRatio, Method, false );
2198 //=======================================================================
2199 //function : SmoothParametric
2201 //=======================================================================
2204 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2205 const SMESH::long_array & IDsOfFixedNodes,
2206 CORBA::Long MaxNbOfIterations,
2207 CORBA::Double MaxAspectRatio,
2208 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2209 throw (SALOME::SALOME_Exception)
2211 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2212 MaxAspectRatio, Method, true );
2216 //=======================================================================
2217 //function : SmoothObject
2219 //=======================================================================
2222 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2223 const SMESH::long_array & IDsOfFixedNodes,
2224 CORBA::Long MaxNbOfIterations,
2225 CORBA::Double MaxAspectRatio,
2226 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2227 throw (SALOME::SALOME_Exception)
2229 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2230 MaxAspectRatio, Method, false);
2234 //=======================================================================
2235 //function : SmoothParametricObject
2237 //=======================================================================
2240 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2241 const SMESH::long_array & IDsOfFixedNodes,
2242 CORBA::Long MaxNbOfIterations,
2243 CORBA::Double MaxAspectRatio,
2244 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2245 throw (SALOME::SALOME_Exception)
2247 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2248 MaxAspectRatio, Method, true);
2252 //=============================================================================
2256 //=============================================================================
2259 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2260 const SMESH::long_array & IDsOfFixedNodes,
2261 CORBA::Long MaxNbOfIterations,
2262 CORBA::Double MaxAspectRatio,
2263 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2265 throw (SALOME::SALOME_Exception)
2270 SMESHDS_Mesh* aMesh = getMeshDS();
2272 TIDSortedElemSet elements;
2273 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2275 set<const SMDS_MeshNode*> fixedNodes;
2276 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2277 CORBA::Long index = IDsOfFixedNodes[i];
2278 const SMDS_MeshNode * node = aMesh->FindNode(index);
2280 fixedNodes.insert( node );
2282 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2283 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2284 method = ::SMESH_MeshEditor::CENTROIDAL;
2286 getEditor().Smooth(elements, fixedNodes, method,
2287 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2289 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2291 // Update Python script
2292 TPythonDump() << "isDone = " << this << "."
2293 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2294 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2295 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2296 << "SMESH.SMESH_MeshEditor."
2297 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2298 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2302 SMESH_CATCH( SMESH::throwCorbaException );
2306 //=============================================================================
2310 //=============================================================================
2313 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2314 const SMESH::long_array & IDsOfFixedNodes,
2315 CORBA::Long MaxNbOfIterations,
2316 CORBA::Double MaxAspectRatio,
2317 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2319 throw (SALOME::SALOME_Exception)
2324 TPythonDump aTPythonDump; // suppress dump in smooth()
2326 prepareIdSource( theObject );
2327 SMESH::long_array_var anElementsId = theObject->GetIDs();
2328 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2329 MaxAspectRatio, Method, IsParametric);
2331 // Update Python script
2332 aTPythonDump << "isDone = " << this << "."
2333 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2334 << theObject << ", " << IDsOfFixedNodes << ", "
2335 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2336 << "SMESH.SMESH_MeshEditor."
2337 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2338 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2342 SMESH_CATCH( SMESH::throwCorbaException );
2346 //=============================================================================
2350 //=============================================================================
2352 void SMESH_MeshEditor_i::RenumberNodes()
2353 throw (SALOME::SALOME_Exception)
2356 // Update Python script
2357 TPythonDump() << this << ".RenumberNodes()";
2359 getMeshDS()->Renumber( true );
2361 SMESH_CATCH( SMESH::throwCorbaException );
2364 //=============================================================================
2368 //=============================================================================
2370 void SMESH_MeshEditor_i::RenumberElements()
2371 throw (SALOME::SALOME_Exception)
2374 // Update Python script
2375 TPythonDump() << this << ".RenumberElements()";
2377 getMeshDS()->Renumber( false );
2379 SMESH_CATCH( SMESH::throwCorbaException );
2382 //=======================================================================
2384 * \brief Return groups by their IDs
2386 //=======================================================================
2388 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2389 throw (SALOME::SALOME_Exception)
2394 myMesh_i->CreateGroupServants();
2395 return myMesh_i->GetGroups( *groupIDs );
2397 SMESH_CATCH( SMESH::throwCorbaException );
2401 //=======================================================================
2402 //function : RotationSweepObjects
2404 //=======================================================================
2406 SMESH::ListOfGroups*
2407 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2408 const SMESH::ListOfIDSources & theEdges,
2409 const SMESH::ListOfIDSources & theFaces,
2410 const SMESH::AxisStruct & theAxis,
2411 CORBA::Double theAngleInRadians,
2412 CORBA::Long theNbOfSteps,
2413 CORBA::Double theTolerance,
2414 const bool theMakeGroups)
2415 throw (SALOME::SALOME_Exception)
2420 TIDSortedElemSet elemsNodes[2];
2421 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2422 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2423 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2425 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2426 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2427 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2428 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2430 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2431 bool makeWalls=true;
2432 if ( myIsPreviewMode )
2434 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2435 TPreviewMesh * tmpMesh = getPreviewMesh();
2436 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2437 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2438 workElements = & copyElements[0];
2439 //makeWalls = false; -- faces are needed for preview
2442 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2444 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2445 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2447 ::SMESH_MeshEditor::PGroupIDs groupIds =
2448 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2449 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2451 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2453 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2455 if ( !myIsPreviewMode )
2457 dumpGroupsList( aPythonDump, aGroups );
2458 aPythonDump << this<< ".RotationSweepObjects( "
2463 << TVar( theAngleInRadians ) << ", "
2464 << TVar( theNbOfSteps ) << ", "
2465 << TVar( theTolerance ) << ", "
2466 << theMakeGroups << " )";
2470 getPreviewMesh()->Remove( SMDSAbs_Volume );
2473 return aGroups ? aGroups : new SMESH::ListOfGroups;
2475 SMESH_CATCH( SMESH::throwCorbaException );
2479 namespace MeshEditor_I
2482 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2484 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2486 bool myIsExtrusionByNormal;
2488 static int makeFlags( CORBA::Boolean MakeGroups,
2489 CORBA::Boolean LinearVariation = false,
2490 CORBA::Boolean ByAverageNormal = false,
2491 CORBA::Boolean UseInputElemsOnly = false,
2492 CORBA::Long Flags = 0,
2493 CORBA::Boolean MakeBoundary = true )
2495 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2496 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2497 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2498 if ( LinearVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2499 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2503 ExtrusionParams(const SMESH::DirStruct & theDir,
2504 CORBA::Long theNbOfSteps,
2505 const SMESH::double_array & theScaleFactors,
2506 CORBA::Boolean theLinearVariation,
2507 const SMESH::double_array & theBasePoint,
2508 CORBA::Boolean theMakeGroups):
2509 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2513 toList( theScaleFactors ),
2514 TBasePoint( theBasePoint ),
2515 makeFlags( theMakeGroups, theLinearVariation )),
2516 myIsExtrusionByNormal( false )
2520 ExtrusionParams(const SMESH::DirStruct & theDir,
2521 CORBA::Long theNbOfSteps,
2522 CORBA::Boolean theMakeGroups,
2523 CORBA::Long theExtrFlags,
2524 CORBA::Double theSewTolerance):
2525 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2529 std::list<double>(),
2531 makeFlags( theMakeGroups, false, false, false,
2532 theExtrFlags, false ),
2534 myIsExtrusionByNormal( false )
2537 // params for extrusion by normal
2538 ExtrusionParams(CORBA::Double theStepSize,
2539 CORBA::Long theNbOfSteps,
2540 CORBA::Short theDim,
2541 CORBA::Boolean theByAverageNormal,
2542 CORBA::Boolean theUseInputElemsOnly,
2543 CORBA::Boolean theMakeGroups ):
2544 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2546 makeFlags( theMakeGroups, false,
2547 theByAverageNormal, theUseInputElemsOnly ),
2549 myIsExtrusionByNormal( true )
2555 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2560 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2562 std::list<double> scales;
2563 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2564 scales.push_back( theScaleFactors[i] );
2568 // structure used to convert SMESH::double_array to gp_XYZ*
2572 TBasePoint( const SMESH::double_array & theBasePoint )
2575 if ( theBasePoint.length() == 3 )
2577 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2581 operator const gp_XYZ*() const { return pp; }
2586 //=======================================================================
2588 * \brief Generate dim+1 elements by extrusion of elements along vector
2589 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2590 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2591 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2592 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2593 * \param [in] nbOfSteps - number of elements to generate from one element
2594 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2595 * corresponding to groups the input elements included in.
2596 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2598 //=======================================================================
2600 SMESH::ListOfGroups*
2601 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2602 const SMESH::ListOfIDSources & theEdges,
2603 const SMESH::ListOfIDSources & theFaces,
2604 const SMESH::DirStruct & theStepVector,
2605 CORBA::Long theNbOfSteps,
2606 const SMESH::double_array & theScaleFactors,
2607 CORBA::Boolean theLinearVariation,
2608 const SMESH::double_array & theBasePoint,
2609 CORBA::Boolean theToMakeGroups)
2610 throw (SALOME::SALOME_Exception)
2615 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
2616 theLinearVariation, theBasePoint, theToMakeGroups );
2618 TIDSortedElemSet elemsNodes[2];
2619 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2620 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2621 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2623 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2624 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2625 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2626 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2628 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2629 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2630 if ( myIsPreviewMode )
2632 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2633 // previewType = SMDSAbs_Edge;
2635 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2636 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2637 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2638 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2639 workElements = & copyElements[0];
2641 params.SetNoGroups();
2643 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2645 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2646 ::SMESH_MeshEditor::PGroupIDs groupIds =
2647 getEditor().ExtrusionSweep( workElements, params, aHistory );
2649 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2651 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2653 if ( !myIsPreviewMode )
2655 dumpGroupsList( aPythonDump, aGroups );
2656 aPythonDump << this<< ".ExtrusionSweepObjects( "
2660 << theStepVector << ", "
2661 << TVar( theNbOfSteps ) << ", "
2662 << theToMakeGroups << " )";
2666 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2669 return aGroups ? aGroups : new SMESH::ListOfGroups;
2671 SMESH_CATCH( SMESH::throwCorbaException );
2675 //=======================================================================
2676 //function : ExtrusionByNormal
2678 //=======================================================================
2680 SMESH::ListOfGroups*
2681 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2682 CORBA::Double stepSize,
2683 CORBA::Long nbOfSteps,
2684 CORBA::Boolean byAverageNormal,
2685 CORBA::Boolean useInputElemsOnly,
2686 CORBA::Boolean makeGroups,
2688 throw (SALOME::SALOME_Exception)
2693 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2695 ExtrusionParams params( stepSize, nbOfSteps, dim,
2696 byAverageNormal, useInputElemsOnly, makeGroups );
2698 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2699 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2701 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2702 if (( elemTypes->length() == 1 ) &&
2703 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2704 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2707 TIDSortedElemSet elemsNodes[2];
2708 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2709 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2711 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2712 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2713 if ( myIsPreviewMode )
2715 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2716 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2717 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2718 workElements = & copyElements[0];
2720 params.SetNoGroups();
2723 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2724 ::SMESH_MeshEditor::PGroupIDs groupIds =
2725 getEditor().ExtrusionSweep( workElements, params, aHistory );
2727 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2729 if (!myIsPreviewMode) {
2730 dumpGroupsList(aPythonDump, aGroups);
2731 aPythonDump << this << ".ExtrusionByNormal( " << objects
2732 << ", " << TVar( stepSize )
2733 << ", " << TVar( nbOfSteps )
2734 << ", " << byAverageNormal
2735 << ", " << useInputElemsOnly
2736 << ", " << makeGroups
2742 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2745 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2747 return aGroups ? aGroups : new SMESH::ListOfGroups;
2749 SMESH_CATCH( SMESH::throwCorbaException );
2753 //=======================================================================
2754 //function : AdvancedExtrusion
2756 //=======================================================================
2758 SMESH::ListOfGroups*
2759 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2760 const SMESH::DirStruct & theStepVector,
2761 CORBA::Long theNbOfSteps,
2762 CORBA::Long theExtrFlags,
2763 CORBA::Double theSewTolerance,
2764 CORBA::Boolean theMakeGroups)
2765 throw (SALOME::SALOME_Exception)
2770 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2772 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2773 theExtrFlags, theSewTolerance );
2775 TIDSortedElemSet elemsNodes[2];
2776 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2778 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2779 ::SMESH_MeshEditor::PGroupIDs groupIds =
2780 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2782 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2784 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2786 if ( !myIsPreviewMode ) {
2787 dumpGroupsList(aPythonDump, aGroups);
2788 aPythonDump << this << ".AdvancedExtrusion( "
2789 << theIDsOfElements << ", "
2790 << theStepVector << ", "
2791 << theNbOfSteps << ", "
2792 << theExtrFlags << ", "
2793 << theSewTolerance << ", "
2794 << theMakeGroups << " )";
2798 getPreviewMesh()->Remove( SMDSAbs_Volume );
2801 return aGroups ? aGroups : new SMESH::ListOfGroups;
2803 SMESH_CATCH( SMESH::throwCorbaException );
2807 //================================================================================
2809 * \brief Convert extrusion error to IDL enum
2811 //================================================================================
2815 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2817 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2821 RETCASE( EXTR_NO_ELEMENTS );
2822 RETCASE( EXTR_PATH_NOT_EDGE );
2823 RETCASE( EXTR_BAD_PATH_SHAPE );
2824 RETCASE( EXTR_BAD_STARTING_NODE );
2825 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2826 RETCASE( EXTR_CANT_GET_TANGENT );
2828 return SMESH::SMESH_MeshEditor::EXTR_OK;
2832 //=======================================================================
2833 //function : extrusionAlongPath
2835 //=======================================================================
2836 SMESH::ListOfGroups*
2837 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2838 const SMESH::ListOfIDSources & theEdges,
2839 const SMESH::ListOfIDSources & theFaces,
2840 SMESH::SMESH_IDSource_ptr thePathMesh,
2841 GEOM::GEOM_Object_ptr thePathShape,
2842 CORBA::Long theNodeStart,
2843 CORBA::Boolean theHasAngles,
2844 const SMESH::double_array & theAngles,
2845 CORBA::Boolean theLinearVariation,
2846 CORBA::Boolean theHasRefPoint,
2847 const SMESH::PointStruct & theRefPoint,
2849 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2850 throw (SALOME::SALOME_Exception)
2855 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2857 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2858 if ( thePathMesh->_is_nil() )
2859 return aGroups._retn();
2862 SMESH_subMesh* aSubMesh = 0;
2863 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2864 if ( thePathShape->_is_nil() )
2866 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2867 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2869 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2870 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2871 if ( !aMeshImp ) return aGroups._retn();
2872 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2873 if ( !aSubMesh ) return aGroups._retn();
2875 else if ( !aMeshImp ||
2876 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2878 return aGroups._retn();
2883 if ( !aMeshImp ) return aGroups._retn();
2884 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2885 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2886 if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
2887 return aGroups._retn();
2890 SMDS_MeshNode* nodeStart =
2891 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2893 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2894 return aGroups._retn();
2897 TIDSortedElemSet elemsNodes[2];
2898 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2899 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2900 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2902 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2903 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2904 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2905 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2907 list<double> angles;
2908 for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) {
2909 angles.push_back( theAngles[i] );
2912 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2914 int nbOldGroups = myMesh->NbGroup();
2916 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2917 if ( myIsPreviewMode )
2919 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2920 TPreviewMesh * tmpMesh = getPreviewMesh();
2921 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2922 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2923 workElements = & copyElements[0];
2924 theMakeGroups = false;
2927 ::SMESH_MeshEditor::Extrusion_Error error;
2929 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2930 theHasAngles, angles, theLinearVariation,
2931 theHasRefPoint, refPnt, theMakeGroups );
2933 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2934 theHasAngles, angles, theLinearVariation,
2935 theHasRefPoint, refPnt, theMakeGroups );
2937 declareMeshModified( /*isReComputeSafe=*/true );
2938 theError = convExtrError( error );
2940 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2941 if ( theMakeGroups ) {
2942 list<int> groupIDs = myMesh->GetGroupIds();
2943 list<int>::iterator newBegin = groupIDs.begin();
2944 std::advance( newBegin, nbOldGroups ); // skip old groups
2945 groupIDs.erase( groupIDs.begin(), newBegin );
2946 aGroups = getGroups( & groupIDs );
2947 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2950 if ( !myIsPreviewMode ) {
2951 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2952 else aPythonDump << "(_noGroups, error) = ";
2953 aPythonDump << this << ".ExtrusionAlongPathObjects( "
2957 << thePathMesh << ", "
2958 << thePathShape << ", "
2959 << theNodeStart << ", "
2960 << theHasAngles << ", "
2961 << TVar( theAngles ) << ", "
2962 << theLinearVariation << ", "
2963 << theHasRefPoint << ", "
2964 << "SMESH.PointStruct( "
2965 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2966 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2967 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2968 << theMakeGroups << " )";
2972 getPreviewMesh()->Remove( SMDSAbs_Volume );
2975 return aGroups._retn();
2977 SMESH_CATCH( SMESH::throwCorbaException );
2981 //================================================================================
2983 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2984 * of given angles along path steps
2985 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2986 * which proceeds the extrusion
2987 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2988 * is used to define the sub-mesh for the path
2990 //================================================================================
2992 SMESH::double_array*
2993 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2994 GEOM::GEOM_Object_ptr thePathShape,
2995 const SMESH::double_array & theAngles)
2997 SMESH::double_array_var aResult = new SMESH::double_array();
2998 int nbAngles = theAngles.length();
2999 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3001 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3002 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3003 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3004 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3005 return aResult._retn();
3006 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3007 if ( nbSteps == nbAngles )
3009 aResult.inout() = theAngles;
3013 aResult->length( nbSteps );
3014 double rAn2St = double( nbAngles ) / double( nbSteps );
3015 double angPrev = 0, angle;
3016 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3018 double angCur = rAn2St * ( iSt+1 );
3019 double angCurFloor = floor( angCur );
3020 double angPrevFloor = floor( angPrev );
3021 if ( angPrevFloor == angCurFloor )
3022 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3025 int iP = int( angPrevFloor );
3026 double angPrevCeil = ceil(angPrev);
3027 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3029 int iC = int( angCurFloor );
3030 if ( iC < nbAngles )
3031 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3033 iP = int( angPrevCeil );
3035 angle += theAngles[ iC ];
3037 aResult[ iSt ] = angle;
3042 // Update Python script
3043 TPythonDump() << "rotAngles = " << theAngles;
3044 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3045 << thePathMesh << ", "
3046 << thePathShape << ", "
3049 return aResult._retn();
3052 //=======================================================================
3055 //=======================================================================
3057 SMESH::ListOfGroups*
3058 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3059 const SMESH::AxisStruct & theAxis,
3060 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3061 CORBA::Boolean theCopy,
3063 ::SMESH_Mesh* theTargetMesh)
3064 throw (SALOME::SALOME_Exception)
3069 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3070 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3072 if ( theTargetMesh )
3076 switch ( theMirrorType ) {
3077 case SMESH::SMESH_MeshEditor::POINT:
3078 aTrsf.SetMirror( P );
3080 case SMESH::SMESH_MeshEditor::AXIS:
3081 aTrsf.SetMirror( gp_Ax1( P, V ));
3084 aTrsf.SetMirror( gp_Ax2( P, V ));
3087 TIDSortedElemSet copyElements;
3088 TIDSortedElemSet* workElements = & theElements;
3090 if ( myIsPreviewMode )
3092 TPreviewMesh * tmpMesh = getPreviewMesh();
3093 tmpMesh->Copy( theElements, copyElements);
3094 if ( !theCopy && !theTargetMesh )
3096 TIDSortedElemSet elemsAround, elemsAroundCopy;
3097 getElementsAround( theElements, getMeshDS(), elemsAround );
3098 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3100 workElements = & copyElements;
3101 theMakeGroups = false;
3104 ::SMESH_MeshEditor::PGroupIDs groupIds =
3105 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3107 if ( !myIsPreviewMode )
3109 if ( theTargetMesh )
3110 theTargetMesh->GetMeshDS()->Modified();
3112 declareMeshModified( /*isReComputeSafe=*/false );
3115 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3117 SMESH_CATCH( SMESH::throwCorbaException );
3121 //=======================================================================
3124 //=======================================================================
3126 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3127 const SMESH::AxisStruct & theAxis,
3128 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3129 CORBA::Boolean theCopy)
3130 throw (SALOME::SALOME_Exception)
3132 if ( !myIsPreviewMode ) {
3133 TPythonDump() << this << ".Mirror( "
3134 << theIDsOfElements << ", "
3136 << mirrorTypeName(theMirrorType) << ", "
3139 if ( theIDsOfElements.length() > 0 )
3141 TIDSortedElemSet elements;
3142 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3143 mirror(elements, theAxis, theMirrorType, theCopy, false);
3148 //=======================================================================
3149 //function : MirrorObject
3151 //=======================================================================
3153 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3154 const SMESH::AxisStruct & theAxis,
3155 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3156 CORBA::Boolean theCopy)
3157 throw (SALOME::SALOME_Exception)
3159 if ( !myIsPreviewMode ) {
3160 TPythonDump() << this << ".MirrorObject( "
3161 << theObject << ", "
3163 << mirrorTypeName(theMirrorType) << ", "
3166 TIDSortedElemSet elements;
3168 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3170 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3171 mirror(elements, theAxis, theMirrorType, theCopy, false);
3174 //=======================================================================
3175 //function : MirrorMakeGroups
3177 //=======================================================================
3179 SMESH::ListOfGroups*
3180 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3181 const SMESH::AxisStruct& theMirror,
3182 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3183 throw (SALOME::SALOME_Exception)
3185 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3187 SMESH::ListOfGroups * aGroups = 0;
3188 if ( theIDsOfElements.length() > 0 )
3190 TIDSortedElemSet elements;
3191 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3192 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3194 if (!myIsPreviewMode) {
3195 dumpGroupsList(aPythonDump, aGroups);
3196 aPythonDump << this << ".MirrorMakeGroups( "
3197 << theIDsOfElements << ", "
3198 << theMirror << ", "
3199 << mirrorTypeName(theMirrorType) << " )";
3204 //=======================================================================
3205 //function : MirrorObjectMakeGroups
3207 //=======================================================================
3209 SMESH::ListOfGroups*
3210 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3211 const SMESH::AxisStruct& theMirror,
3212 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3213 throw (SALOME::SALOME_Exception)
3215 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3217 SMESH::ListOfGroups * aGroups = 0;
3218 TIDSortedElemSet elements;
3219 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3220 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3222 if (!myIsPreviewMode)
3224 dumpGroupsList(aPythonDump,aGroups);
3225 aPythonDump << this << ".MirrorObjectMakeGroups( "
3226 << theObject << ", "
3227 << theMirror << ", "
3228 << mirrorTypeName(theMirrorType) << " )";
3233 //=======================================================================
3234 //function : MirrorMakeMesh
3236 //=======================================================================
3238 SMESH::SMESH_Mesh_ptr
3239 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3240 const SMESH::AxisStruct& theMirror,
3241 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3242 CORBA::Boolean theCopyGroups,
3243 const char* theMeshName)
3244 throw (SALOME::SALOME_Exception)
3246 SMESH_Mesh_i* mesh_i;
3247 SMESH::SMESH_Mesh_var mesh;
3248 { // open new scope to dump "MakeMesh" command
3249 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3251 TPythonDump pydump; // to prevent dump at mesh creation
3253 mesh = makeMesh( theMeshName );
3254 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3255 if (mesh_i && theIDsOfElements.length() > 0 )
3257 TIDSortedElemSet elements;
3258 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3259 mirror(elements, theMirror, theMirrorType,
3260 false, theCopyGroups, & mesh_i->GetImpl());
3261 mesh_i->CreateGroupServants();
3264 if (!myIsPreviewMode) {
3265 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3266 << theIDsOfElements << ", "
3267 << theMirror << ", "
3268 << mirrorTypeName(theMirrorType) << ", "
3269 << theCopyGroups << ", '"
3270 << theMeshName << "' )";
3275 if (!myIsPreviewMode && mesh_i)
3276 mesh_i->GetGroups();
3278 return mesh._retn();
3281 //=======================================================================
3282 //function : MirrorObjectMakeMesh
3284 //=======================================================================
3286 SMESH::SMESH_Mesh_ptr
3287 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3288 const SMESH::AxisStruct& theMirror,
3289 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3290 CORBA::Boolean theCopyGroups,
3291 const char* theMeshName)
3292 throw (SALOME::SALOME_Exception)
3294 SMESH_Mesh_i* mesh_i;
3295 SMESH::SMESH_Mesh_var mesh;
3296 { // open new scope to dump "MakeMesh" command
3297 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3299 TPythonDump pydump; // to prevent dump at mesh creation
3301 mesh = makeMesh( theMeshName );
3302 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3303 TIDSortedElemSet elements;
3305 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3307 mirror(elements, theMirror, theMirrorType,
3308 false, theCopyGroups, & mesh_i->GetImpl());
3309 mesh_i->CreateGroupServants();
3311 if (!myIsPreviewMode) {
3312 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3313 << theObject << ", "
3314 << theMirror << ", "
3315 << mirrorTypeName(theMirrorType) << ", "
3316 << theCopyGroups << ", '"
3317 << theMeshName << "' )";
3322 if (!myIsPreviewMode && mesh_i)
3323 mesh_i->GetGroups();
3325 return mesh._retn();
3328 //=======================================================================
3329 //function : translate
3331 //=======================================================================
3333 SMESH::ListOfGroups*
3334 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3335 const SMESH::DirStruct & theVector,
3336 CORBA::Boolean theCopy,
3338 ::SMESH_Mesh* theTargetMesh)
3339 throw (SALOME::SALOME_Exception)
3344 if ( theTargetMesh )
3348 const SMESH::PointStruct * P = &theVector.PS;
3349 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3351 TIDSortedElemSet copyElements;
3352 TIDSortedElemSet* workElements = &theElements;
3354 if ( myIsPreviewMode )
3356 TPreviewMesh * tmpMesh = getPreviewMesh();
3357 tmpMesh->Copy( theElements, copyElements);
3358 if ( !theCopy && !theTargetMesh )
3360 TIDSortedElemSet elemsAround, elemsAroundCopy;
3361 getElementsAround( theElements, getMeshDS(), elemsAround );
3362 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3364 workElements = & copyElements;
3365 theMakeGroups = false;
3368 ::SMESH_MeshEditor::PGroupIDs groupIds =
3369 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3371 if ( !myIsPreviewMode )
3373 if ( theTargetMesh )
3374 theTargetMesh->GetMeshDS()->Modified();
3376 declareMeshModified( /*isReComputeSafe=*/false );
3379 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3381 SMESH_CATCH( SMESH::throwCorbaException );
3385 //=======================================================================
3386 //function : Translate
3388 //=======================================================================
3390 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3391 const SMESH::DirStruct & theVector,
3392 CORBA::Boolean theCopy)
3393 throw (SALOME::SALOME_Exception)
3395 if (!myIsPreviewMode) {
3396 TPythonDump() << this << ".Translate( "
3397 << theIDsOfElements << ", "
3398 << theVector << ", "
3401 if (theIDsOfElements.length()) {
3402 TIDSortedElemSet elements;
3403 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3404 translate(elements, theVector, theCopy, false);
3408 //=======================================================================
3409 //function : TranslateObject
3411 //=======================================================================
3413 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3414 const SMESH::DirStruct & theVector,
3415 CORBA::Boolean theCopy)
3416 throw (SALOME::SALOME_Exception)
3418 if (!myIsPreviewMode) {
3419 TPythonDump() << this << ".TranslateObject( "
3420 << theObject << ", "
3421 << theVector << ", "
3424 TIDSortedElemSet elements;
3426 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3428 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3429 translate(elements, theVector, theCopy, false);
3432 //=======================================================================
3433 //function : TranslateMakeGroups
3435 //=======================================================================
3437 SMESH::ListOfGroups*
3438 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3439 const SMESH::DirStruct& theVector)
3440 throw (SALOME::SALOME_Exception)
3442 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3444 SMESH::ListOfGroups * aGroups = 0;
3445 if (theIDsOfElements.length()) {
3446 TIDSortedElemSet elements;
3447 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3448 aGroups = translate(elements,theVector,true,true);
3450 if (!myIsPreviewMode) {
3451 dumpGroupsList(aPythonDump, aGroups);
3452 aPythonDump << this << ".TranslateMakeGroups( "
3453 << theIDsOfElements << ", "
3454 << theVector << " )";
3459 //=======================================================================
3460 //function : TranslateObjectMakeGroups
3462 //=======================================================================
3464 SMESH::ListOfGroups*
3465 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3466 const SMESH::DirStruct& theVector)
3467 throw (SALOME::SALOME_Exception)
3469 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3471 SMESH::ListOfGroups * aGroups = 0;
3472 TIDSortedElemSet elements;
3473 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3474 aGroups = translate(elements, theVector, true, true);
3476 if (!myIsPreviewMode) {
3477 dumpGroupsList(aPythonDump, aGroups);
3478 aPythonDump << this << ".TranslateObjectMakeGroups( "
3479 << theObject << ", "
3480 << theVector << " )";
3485 //=======================================================================
3486 //function : TranslateMakeMesh
3488 //=======================================================================
3490 SMESH::SMESH_Mesh_ptr
3491 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3492 const SMESH::DirStruct& theVector,
3493 CORBA::Boolean theCopyGroups,
3494 const char* theMeshName)
3495 throw (SALOME::SALOME_Exception)
3497 SMESH_Mesh_i* mesh_i;
3498 SMESH::SMESH_Mesh_var mesh;
3500 { // open new scope to dump "MakeMesh" command
3501 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3503 TPythonDump pydump; // to prevent dump at mesh creation
3505 mesh = makeMesh( theMeshName );
3506 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3508 if ( mesh_i && theIDsOfElements.length() )
3510 TIDSortedElemSet elements;
3511 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3512 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3513 mesh_i->CreateGroupServants();
3516 if ( !myIsPreviewMode ) {
3517 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3518 << theIDsOfElements << ", "
3519 << theVector << ", "
3520 << theCopyGroups << ", '"
3521 << theMeshName << "' )";
3526 if (!myIsPreviewMode && mesh_i)
3527 mesh_i->GetGroups();
3529 return mesh._retn();
3532 //=======================================================================
3533 //function : TranslateObjectMakeMesh
3535 //=======================================================================
3537 SMESH::SMESH_Mesh_ptr
3538 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3539 const SMESH::DirStruct& theVector,
3540 CORBA::Boolean theCopyGroups,
3541 const char* theMeshName)
3542 throw (SALOME::SALOME_Exception)
3545 SMESH_Mesh_i* mesh_i;
3546 SMESH::SMESH_Mesh_var mesh;
3547 { // open new scope to dump "MakeMesh" command
3548 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3550 TPythonDump pydump; // to prevent dump at mesh creation
3551 mesh = makeMesh( theMeshName );
3552 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3554 TIDSortedElemSet elements;
3556 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3558 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3559 mesh_i->CreateGroupServants();
3561 if ( !myIsPreviewMode ) {
3562 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3563 << theObject << ", "
3564 << theVector << ", "
3565 << theCopyGroups << ", '"
3566 << theMeshName << "' )";
3571 if (!myIsPreviewMode && mesh_i)
3572 mesh_i->GetGroups();
3574 return mesh._retn();
3576 SMESH_CATCH( SMESH::throwCorbaException );
3580 //=======================================================================
3583 //=======================================================================
3585 SMESH::ListOfGroups*
3586 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3587 const SMESH::AxisStruct & theAxis,
3588 CORBA::Double theAngle,
3589 CORBA::Boolean theCopy,
3591 ::SMESH_Mesh* theTargetMesh)
3592 throw (SALOME::SALOME_Exception)
3597 if ( theTargetMesh )
3600 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3601 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3604 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3606 TIDSortedElemSet copyElements;
3607 TIDSortedElemSet* workElements = &theElements;
3608 if ( myIsPreviewMode ) {
3609 TPreviewMesh * tmpMesh = getPreviewMesh();
3610 tmpMesh->Copy( theElements, copyElements );
3611 if ( !theCopy && !theTargetMesh )
3613 TIDSortedElemSet elemsAround, elemsAroundCopy;
3614 getElementsAround( theElements, getMeshDS(), elemsAround );
3615 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3617 workElements = ©Elements;
3618 theMakeGroups = false;
3621 ::SMESH_MeshEditor::PGroupIDs groupIds =
3622 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3624 if ( !myIsPreviewMode)
3626 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3627 else declareMeshModified( /*isReComputeSafe=*/false );
3630 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3632 SMESH_CATCH( SMESH::throwCorbaException );
3636 //=======================================================================
3639 //=======================================================================
3641 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3642 const SMESH::AxisStruct & theAxis,
3643 CORBA::Double theAngle,
3644 CORBA::Boolean theCopy)
3645 throw (SALOME::SALOME_Exception)
3647 if (!myIsPreviewMode) {
3648 TPythonDump() << this << ".Rotate( "
3649 << theIDsOfElements << ", "
3651 << TVar( theAngle ) << ", "
3654 if (theIDsOfElements.length() > 0)
3656 TIDSortedElemSet elements;
3657 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3658 rotate(elements,theAxis,theAngle,theCopy,false);
3662 //=======================================================================
3663 //function : RotateObject
3665 //=======================================================================
3667 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3668 const SMESH::AxisStruct & theAxis,
3669 CORBA::Double theAngle,
3670 CORBA::Boolean theCopy)
3671 throw (SALOME::SALOME_Exception)
3673 if ( !myIsPreviewMode ) {
3674 TPythonDump() << this << ".RotateObject( "
3675 << theObject << ", "
3677 << TVar( theAngle ) << ", "
3680 TIDSortedElemSet elements;
3681 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3682 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3683 rotate(elements,theAxis,theAngle,theCopy,false);
3686 //=======================================================================
3687 //function : RotateMakeGroups
3689 //=======================================================================
3691 SMESH::ListOfGroups*
3692 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3693 const SMESH::AxisStruct& theAxis,
3694 CORBA::Double theAngle)
3695 throw (SALOME::SALOME_Exception)
3697 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3699 SMESH::ListOfGroups * aGroups = 0;
3700 if (theIDsOfElements.length() > 0)
3702 TIDSortedElemSet elements;
3703 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3704 aGroups = rotate(elements,theAxis,theAngle,true,true);
3706 if (!myIsPreviewMode) {
3707 dumpGroupsList(aPythonDump, aGroups);
3708 aPythonDump << this << ".RotateMakeGroups( "
3709 << theIDsOfElements << ", "
3711 << TVar( theAngle ) << " )";
3716 //=======================================================================
3717 //function : RotateObjectMakeGroups
3719 //=======================================================================
3721 SMESH::ListOfGroups*
3722 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3723 const SMESH::AxisStruct& theAxis,
3724 CORBA::Double theAngle)
3725 throw (SALOME::SALOME_Exception)
3727 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3729 SMESH::ListOfGroups * aGroups = 0;
3730 TIDSortedElemSet elements;
3731 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3732 aGroups = rotate(elements, theAxis, theAngle, true, true);
3734 if (!myIsPreviewMode) {
3735 dumpGroupsList(aPythonDump, aGroups);
3736 aPythonDump << this << ".RotateObjectMakeGroups( "
3737 << theObject << ", "
3739 << TVar( theAngle ) << " )";
3744 //=======================================================================
3745 //function : RotateMakeMesh
3747 //=======================================================================
3749 SMESH::SMESH_Mesh_ptr
3750 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3751 const SMESH::AxisStruct& theAxis,
3752 CORBA::Double theAngleInRadians,
3753 CORBA::Boolean theCopyGroups,
3754 const char* theMeshName)
3755 throw (SALOME::SALOME_Exception)
3758 SMESH::SMESH_Mesh_var mesh;
3759 SMESH_Mesh_i* mesh_i;
3761 { // open new scope to dump "MakeMesh" command
3762 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3764 TPythonDump pydump; // to prevent dump at mesh creation
3766 mesh = makeMesh( theMeshName );
3767 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3769 if ( mesh_i && theIDsOfElements.length() > 0 )
3771 TIDSortedElemSet elements;
3772 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3773 rotate(elements, theAxis, theAngleInRadians,
3774 false, theCopyGroups, & mesh_i->GetImpl());
3775 mesh_i->CreateGroupServants();
3777 if ( !myIsPreviewMode ) {
3778 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3779 << theIDsOfElements << ", "
3781 << TVar( theAngleInRadians ) << ", "
3782 << theCopyGroups << ", '"
3783 << theMeshName << "' )";
3788 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3789 mesh_i->GetGroups();
3791 return mesh._retn();
3793 SMESH_CATCH( SMESH::throwCorbaException );
3797 //=======================================================================
3798 //function : RotateObjectMakeMesh
3800 //=======================================================================
3802 SMESH::SMESH_Mesh_ptr
3803 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3804 const SMESH::AxisStruct& theAxis,
3805 CORBA::Double theAngleInRadians,
3806 CORBA::Boolean theCopyGroups,
3807 const char* theMeshName)
3808 throw (SALOME::SALOME_Exception)
3811 SMESH::SMESH_Mesh_var mesh;
3812 SMESH_Mesh_i* mesh_i;
3814 {// open new scope to dump "MakeMesh" command
3815 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3817 TPythonDump pydump; // to prevent dump at mesh creation
3818 mesh = makeMesh( theMeshName );
3819 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3821 TIDSortedElemSet elements;
3823 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3825 rotate(elements, theAxis, theAngleInRadians,
3826 false, theCopyGroups, & mesh_i->GetImpl());
3827 mesh_i->CreateGroupServants();
3829 if ( !myIsPreviewMode ) {
3830 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3831 << theObject << ", "
3833 << TVar( theAngleInRadians ) << ", "
3834 << theCopyGroups << ", '"
3835 << theMeshName << "' )";
3840 if (!myIsPreviewMode && mesh_i)
3841 mesh_i->GetGroups();
3843 return mesh._retn();
3845 SMESH_CATCH( SMESH::throwCorbaException );
3849 //=======================================================================
3852 //=======================================================================
3854 SMESH::ListOfGroups*
3855 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3856 const SMESH::PointStruct& thePoint,
3857 const SMESH::double_array& theScaleFact,
3858 CORBA::Boolean theCopy,
3860 ::SMESH_Mesh* theTargetMesh)
3861 throw (SALOME::SALOME_Exception)
3865 if ( theScaleFact.length() < 1 )
3866 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3867 if ( theScaleFact.length() == 2 )
3868 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3870 if ( theTargetMesh )
3873 TIDSortedElemSet elements;
3874 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3875 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3880 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3881 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3885 // fight against orthogonalization
3886 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3887 // 0, S[1], 0, thePoint.y * (1-S[1]),
3888 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3889 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3890 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3891 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3892 loc.SetCoord( thePoint.x * (1-S[0]),
3893 thePoint.y * (1-S[1]),
3894 thePoint.z * (1-S[2]));
3895 M.SetDiagonal( S[0], S[1], S[2] );
3897 TIDSortedElemSet copyElements;
3898 TIDSortedElemSet* workElements = &elements;
3899 if ( myIsPreviewMode )
3901 TPreviewMesh * tmpMesh = getPreviewMesh();
3902 tmpMesh->Copy( elements, copyElements);
3903 if ( !theCopy && !theTargetMesh )
3905 TIDSortedElemSet elemsAround, elemsAroundCopy;
3906 getElementsAround( elements, getMeshDS(), elemsAround );
3907 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3909 workElements = & copyElements;
3910 theMakeGroups = false;
3913 ::SMESH_MeshEditor::PGroupIDs groupIds =
3914 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3916 if ( !myIsPreviewMode )
3918 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3919 else declareMeshModified( /*isReComputeSafe=*/false );
3921 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3923 SMESH_CATCH( SMESH::throwCorbaException );
3927 //=======================================================================
3930 //=======================================================================
3932 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3933 const SMESH::PointStruct& thePoint,
3934 const SMESH::double_array& theScaleFact,
3935 CORBA::Boolean theCopy)
3936 throw (SALOME::SALOME_Exception)
3938 if ( !myIsPreviewMode ) {
3939 TPythonDump() << this << ".Scale( "
3940 << theObject << ", "
3942 << TVar( theScaleFact ) << ", "
3945 scale(theObject, thePoint, theScaleFact, theCopy, false);
3949 //=======================================================================
3950 //function : ScaleMakeGroups
3952 //=======================================================================
3954 SMESH::ListOfGroups*
3955 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3956 const SMESH::PointStruct& thePoint,
3957 const SMESH::double_array& theScaleFact)
3958 throw (SALOME::SALOME_Exception)
3960 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3962 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3963 if (!myIsPreviewMode) {
3964 dumpGroupsList(aPythonDump, aGroups);
3965 aPythonDump << this << ".Scale("
3968 << TVar( theScaleFact ) << ",True,True)";
3974 //=======================================================================
3975 //function : ScaleMakeMesh
3977 //=======================================================================
3979 SMESH::SMESH_Mesh_ptr
3980 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3981 const SMESH::PointStruct& thePoint,
3982 const SMESH::double_array& theScaleFact,
3983 CORBA::Boolean theCopyGroups,
3984 const char* theMeshName)
3985 throw (SALOME::SALOME_Exception)
3987 SMESH_Mesh_i* mesh_i;
3988 SMESH::SMESH_Mesh_var mesh;
3989 { // open new scope to dump "MakeMesh" command
3990 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3992 TPythonDump pydump; // to prevent dump at mesh creation
3993 mesh = makeMesh( theMeshName );
3994 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3998 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3999 mesh_i->CreateGroupServants();
4001 if ( !myIsPreviewMode )
4002 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4003 << theObject << ", "
4005 << TVar( theScaleFact ) << ", "
4006 << theCopyGroups << ", '"
4007 << theMeshName << "' )";
4011 if (!myIsPreviewMode && mesh_i)
4012 mesh_i->GetGroups();
4014 return mesh._retn();
4018 //=======================================================================
4019 //function : findCoincidentNodes
4021 //=======================================================================
4023 void SMESH_MeshEditor_i::
4024 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4025 CORBA::Double Tolerance,
4026 SMESH::array_of_long_array_out GroupsOfNodes,
4027 CORBA::Boolean SeparateCornersAndMedium)
4029 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4030 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4032 GroupsOfNodes = new SMESH::array_of_long_array;
4033 GroupsOfNodes->length( aListOfListOfNodes.size() );
4034 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4035 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4037 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4038 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4039 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4040 aGroup.length( aListOfNodes.size() );
4041 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4042 aGroup[ j ] = (*lIt)->GetID();
4046 //=======================================================================
4047 //function : FindCoincidentNodes
4049 //=======================================================================
4051 void SMESH_MeshEditor_i::
4052 FindCoincidentNodes (CORBA::Double Tolerance,
4053 SMESH::array_of_long_array_out GroupsOfNodes,
4054 CORBA::Boolean SeparateCornersAndMedium)
4055 throw (SALOME::SALOME_Exception)
4060 TIDSortedNodeSet nodes; // no input nodes
4061 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4063 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4064 << Tolerance << ", "
4065 << SeparateCornersAndMedium << " )";
4067 SMESH_CATCH( SMESH::throwCorbaException );
4070 //=======================================================================
4071 //function : FindCoincidentNodesOnPart
4073 //=======================================================================
4075 void SMESH_MeshEditor_i::
4076 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4077 CORBA::Double Tolerance,
4078 SMESH::array_of_long_array_out GroupsOfNodes,
4079 CORBA::Boolean SeparateCornersAndMedium)
4080 throw (SALOME::SALOME_Exception)
4085 TIDSortedNodeSet nodes;
4086 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4088 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4090 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4092 << Tolerance << ", "
4093 << SeparateCornersAndMedium << " )";
4095 SMESH_CATCH( SMESH::throwCorbaException );
4098 //================================================================================
4100 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4101 * ExceptSubMeshOrGroups
4103 //================================================================================
4105 void SMESH_MeshEditor_i::
4106 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4107 CORBA::Double theTolerance,
4108 SMESH::array_of_long_array_out theGroupsOfNodes,
4109 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4110 CORBA::Boolean theSeparateCornersAndMedium)
4111 throw (SALOME::SALOME_Exception)
4116 TIDSortedNodeSet nodes;
4117 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4119 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4121 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4123 while ( nodeIt->more() )
4124 nodes.erase( cast2Node( nodeIt->next() ));
4126 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4128 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4130 << theTolerance << ", "
4131 << theExceptSubMeshOrGroups << ", "
4132 << theSeparateCornersAndMedium << " )";
4134 SMESH_CATCH( SMESH::throwCorbaException );
4137 //=======================================================================
4138 //function : MergeNodes
4140 //=======================================================================
4142 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4143 const SMESH::ListOfIDSources& NodesToKeep,
4144 CORBA::Boolean AvoidMakingHoles)
4145 throw (SALOME::SALOME_Exception)
4150 SMESHDS_Mesh* aMesh = getMeshDS();
4152 TPythonDump aTPythonDump;
4153 aTPythonDump << this << ".MergeNodes([";
4155 TIDSortedNodeSet setOfNodesToKeep;
4156 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4158 prepareIdSource( NodesToKeep[i] );
4159 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
4160 while ( nodeIt->more() )
4161 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4164 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4165 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4167 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4168 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4169 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4170 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4172 CORBA::Long index = aNodeGroup[ j ];
4173 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4175 if ( setOfNodesToKeep.count( node ))
4176 aListOfNodes.push_front( node );
4178 aListOfNodes.push_back( node );
4181 if ( aListOfNodes.size() < 2 )
4182 aListOfListOfNodes.pop_back();
4184 if ( i > 0 ) aTPythonDump << ", ";
4185 aTPythonDump << aNodeGroup;
4188 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4190 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4192 declareMeshModified( /*isReComputeSafe=*/false );
4194 SMESH_CATCH( SMESH::throwCorbaException );
4197 //=======================================================================
4198 //function : FindEqualElements
4200 //=======================================================================
4202 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4203 SMESH::array_of_long_array_out GroupsOfElementsID)
4204 throw (SALOME::SALOME_Exception)
4209 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4210 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4212 TIDSortedElemSet elems;
4213 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4215 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4216 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4218 GroupsOfElementsID = new SMESH::array_of_long_array;
4219 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4221 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4222 aListOfListOfElementsID.begin();
4223 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4225 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4226 list<int>& listOfIDs = *arraysIt;
4227 aGroup.length( listOfIDs.size() );
4228 list<int>::iterator idIt = listOfIDs.begin();
4229 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4230 aGroup[ k ] = *idIt;
4233 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4237 SMESH_CATCH( SMESH::throwCorbaException );
4240 //=======================================================================
4241 //function : MergeElements
4243 //=======================================================================
4245 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4246 throw (SALOME::SALOME_Exception)
4251 TPythonDump aTPythonDump;
4252 aTPythonDump << this << ".MergeElements( [";
4254 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4256 for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) {
4257 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4258 aListOfListOfElementsID.push_back( list< int >() );
4259 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4260 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) {
4261 CORBA::Long id = anElemsIDGroup[ j ];
4262 aListOfElemsID.push_back( id );
4264 if ( aListOfElemsID.size() < 2 )
4265 aListOfListOfElementsID.pop_back();
4266 if ( i > 0 ) aTPythonDump << ", ";
4267 aTPythonDump << anElemsIDGroup;
4270 getEditor().MergeElements(aListOfListOfElementsID);
4272 declareMeshModified( /*isReComputeSafe=*/true );
4274 aTPythonDump << "] )";
4276 SMESH_CATCH( SMESH::throwCorbaException );
4279 //=======================================================================
4280 //function : MergeEqualElements
4282 //=======================================================================
4284 void SMESH_MeshEditor_i::MergeEqualElements()
4285 throw (SALOME::SALOME_Exception)
4290 getEditor().MergeEqualElements();
4292 declareMeshModified( /*isReComputeSafe=*/true );
4294 TPythonDump() << this << ".MergeEqualElements()";
4296 SMESH_CATCH( SMESH::throwCorbaException );
4299 //=============================================================================
4301 * Move the node to a given point
4303 //=============================================================================
4305 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4309 throw (SALOME::SALOME_Exception)
4312 initData(/*deleteSearchers=*/false);
4314 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4318 if ( theNodeSearcher )
4319 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4321 if ( myIsPreviewMode ) // make preview data
4323 // in a preview mesh, make edges linked to a node
4324 TPreviewMesh& tmpMesh = *getPreviewMesh();
4325 TIDSortedElemSet linkedNodes;
4326 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4327 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4328 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4329 for ( ; nIt != linkedNodes.end(); ++nIt )
4331 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4332 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4336 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4337 // fill preview data
4339 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4340 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4342 getMeshDS()->MoveNode(node, x, y, z);
4344 if ( !myIsPreviewMode )
4346 // Update Python script
4347 TPythonDump() << "isDone = " << this << ".MoveNode( "
4348 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4349 declareMeshModified( /*isReComputeSafe=*/false );
4352 SMESH_CATCH( SMESH::throwCorbaException );
4357 //================================================================================
4359 * \brief Return ID of node closest to a given point
4361 //================================================================================
4363 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4366 throw (SALOME::SALOME_Exception)
4369 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4371 if ( !theNodeSearcher ) {
4372 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4375 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4376 return node->GetID();
4378 SMESH_CATCH( SMESH::throwCorbaException );
4382 //================================================================================
4384 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4385 * move the node closest to the point to point's location and return ID of the node
4387 //================================================================================
4389 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4392 CORBA::Long theNodeID)
4393 throw (SALOME::SALOME_Exception)
4396 // We keep theNodeSearcher until any mesh modification:
4397 // 1) initData() deletes theNodeSearcher at any edition,
4398 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4400 initData(/*deleteSearchers=*/false);
4402 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4404 int nodeID = theNodeID;
4405 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4406 if ( !node ) // preview moving node
4408 if ( !theNodeSearcher ) {
4409 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4412 node = theNodeSearcher->FindClosestTo( p );
4415 nodeID = node->GetID();
4416 if ( myIsPreviewMode ) // make preview data
4418 // in a preview mesh, make edges linked to a node
4419 TPreviewMesh tmpMesh = *getPreviewMesh();
4420 TIDSortedElemSet linkedNodes;
4421 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4422 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4423 for ( ; nIt != linkedNodes.end(); ++nIt )
4425 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4426 tmpMesh.Copy( &edge );
4429 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4431 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4432 // fill preview data
4434 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4436 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4440 getMeshDS()->MoveNode(node, x, y, z);
4444 if ( !myIsPreviewMode )
4446 TPythonDump() << "nodeID = " << this
4447 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4448 << ", " << nodeID << " )";
4450 declareMeshModified( /*isReComputeSafe=*/false );
4455 SMESH_CATCH( SMESH::throwCorbaException );
4459 //=======================================================================
4461 * Return elements of given type where the given point is IN or ON.
4463 * 'ALL' type means elements of any type excluding nodes
4465 //=======================================================================
4467 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4470 SMESH::ElementType type)
4471 throw (SALOME::SALOME_Exception)
4474 SMESH::long_array_var res = new SMESH::long_array;
4475 vector< const SMDS_MeshElement* > foundElems;
4477 theSearchersDeleter.Set( myMesh );
4478 if ( !theElementSearcher ) {
4479 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4481 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4482 SMDSAbs_ElementType( type ),
4484 res->length( foundElems.size() );
4485 for ( size_t i = 0; i < foundElems.size(); ++i )
4486 res[i] = foundElems[i]->GetID();
4490 SMESH_CATCH( SMESH::throwCorbaException );
4494 //=======================================================================
4495 //function : FindAmongElementsByPoint
4496 //purpose : Searching among the given elements, return elements of given type
4497 // where the given point is IN or ON.
4498 // 'ALL' type means elements of any type excluding nodes
4499 //=======================================================================
4502 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4506 SMESH::ElementType type)
4507 throw (SALOME::SALOME_Exception)
4510 SMESH::long_array_var res = new SMESH::long_array;
4512 if ( type != SMESH::NODE )
4514 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4515 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4516 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4517 type != types[0] ) // but search of elements of dim > 0
4520 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4521 return FindElementsByPoint( x,y,z, type );
4523 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4525 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4526 if ( !theElementSearcher )
4528 // create a searcher from elementIDs
4529 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4530 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4532 if ( !idSourceToSet( elementIDs, meshDS, elements,
4533 ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ),
4534 /*emptyIfIsMesh=*/true))
4537 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4538 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4540 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4543 vector< const SMDS_MeshElement* > foundElems;
4545 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4546 SMDSAbs_ElementType( type ),
4548 res->length( foundElems.size() );
4549 for ( size_t i = 0; i < foundElems.size(); ++i )
4550 res[i] = foundElems[i]->GetID();
4554 SMESH_CATCH( SMESH::throwCorbaException );
4558 //=======================================================================
4559 //function : GetPointState
4560 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4561 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4562 //=======================================================================
4564 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4567 throw (SALOME::SALOME_Exception)
4570 theSearchersDeleter.Set( myMesh );
4571 if ( !theElementSearcher ) {
4572 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4574 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4576 SMESH_CATCH( SMESH::throwCorbaException );
4580 //=======================================================================
4581 //function : convError
4583 //=======================================================================
4585 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4587 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4591 RETCASE( SEW_BORDER1_NOT_FOUND );
4592 RETCASE( SEW_BORDER2_NOT_FOUND );
4593 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4594 RETCASE( SEW_BAD_SIDE_NODES );
4595 RETCASE( SEW_VOLUMES_TO_SPLIT );
4596 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4597 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4598 RETCASE( SEW_BAD_SIDE1_NODES );
4599 RETCASE( SEW_BAD_SIDE2_NODES );
4600 RETCASE( SEW_INTERNAL_ERROR );
4602 return SMESH::SMESH_MeshEditor::SEW_OK;
4605 //=======================================================================
4607 * Returns groups of FreeBorder's coincident within the given tolerance.
4608 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
4609 * to free borders being compared is used.
4611 //=======================================================================
4613 SMESH::CoincidentFreeBorders*
4614 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
4616 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
4620 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
4621 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
4623 // copy free borders
4624 aCFB->borders.length( cfb._borders.size() );
4625 for ( size_t i = 0; i < cfb._borders.size(); ++i )
4627 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
4628 SMESH::FreeBorder& aBRD = aCFB->borders[i];
4629 aBRD.nodeIDs.length( nodes.size() );
4630 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4631 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
4634 // copy coincident parts
4635 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
4636 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
4638 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
4639 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
4640 aGRP.length( grp.size() );
4641 for ( size_t iP = 0; iP < grp.size(); ++iP )
4643 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
4644 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4645 aPART.border = part._border;
4646 aPART.node1 = part._node1;
4647 aPART.node2 = part._node2;
4648 aPART.nodeLast = part._nodeLast;
4651 SMESH_CATCH( SMESH::doNothing );
4653 TPythonDump() << "CoincidentFreeBorders = "
4654 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
4656 return aCFB._retn();
4659 //=======================================================================
4661 * Sew FreeBorder's of each group
4663 //=======================================================================
4665 CORBA::Short SMESH_MeshEditor_i::
4666 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
4667 CORBA::Boolean createPolygons,
4668 CORBA::Boolean createPolyhedra)
4669 throw (SALOME::SALOME_Exception)
4671 CORBA::Short nbSewed = 0;
4673 SMESH_MeshAlgos::TFreeBorderVec groups;
4674 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
4676 // check the input and collect nodes
4677 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
4679 borderNodes.clear();
4680 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
4681 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
4683 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4684 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
4685 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
4687 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
4689 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
4690 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
4691 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
4692 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
4693 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
4694 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4696 // do not keep these nodes for further sewing as nodes can be removed by the sewing
4697 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
4698 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
4699 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
4701 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
4703 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
4705 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4707 borderNodes.push_back( n1 );
4708 borderNodes.push_back( n2 );
4709 borderNodes.push_back( n3 );
4711 groups.push_back( borderNodes );
4714 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
4715 // to get nodes that replace other nodes during merge we create 0D elements
4716 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
4719 vector< const SMDS_MeshElement* > tmp0Delems;
4720 for ( size_t i = 0; i < groups.size(); ++i )
4722 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4723 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4725 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
4727 tmp0Delems.push_back( it0D->next() );
4729 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
4733 // cout << endl << "INIT" << endl;
4734 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4736 // cout << i << " ";
4737 // if ( i % 3 == 0 ) cout << "^ ";
4738 // tmp0Delems[i]->GetNode(0)->Print( cout );
4743 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
4745 for ( size_t i = 0; i < groups.size(); ++i )
4747 bool isBordToBord = true;
4748 bool groupSewed = false;
4749 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4750 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
4752 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
4753 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
4754 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
4756 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
4757 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
4758 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
4760 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
4763 // TIDSortedElemSet emptySet, avoidSet;
4764 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
4766 // cout << "WRONG 2nd 1" << endl;
4767 // n0->Print( cout );
4768 // n1->Print( cout );
4770 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
4772 // cout << "WRONG 2nd 2" << endl;
4773 // n3->Print( cout );
4774 // n4->Print( cout );
4777 if ( !isBordToBord )
4779 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
4780 n2 = 0; // and n2 is not used
4782 // 1st border moves to 2nd
4783 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
4785 /*2ndIsFreeBorder=*/ isBordToBord,
4786 createPolygons, createPolyhedra);
4787 groupSewed = ( res == ok );
4789 isBordToBord = false;
4790 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
4791 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
4793 // cout << t << " ";
4794 // if ( t % 3 == 0 ) cout << "^ ";
4795 // tmp0Delems[t]->GetNode(0)->Print( cout );
4798 i0D += nodes.size();
4799 nbSewed += groupSewed;
4802 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
4803 << freeBorders << ", "
4804 << createPolygons << ", "
4805 << createPolyhedra << " )";
4807 SMESH_CATCH( SMESH::doNothing );
4809 declareMeshModified( /*isReComputeSafe=*/false );
4811 // remove tmp 0D elements
4813 set< const SMDS_MeshElement* > removed0D;
4814 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4816 if ( removed0D.insert( tmp0Delems[i] ).second )
4817 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
4819 SMESH_CATCH( SMESH::throwCorbaException );
4824 //=======================================================================
4825 //function : SewFreeBorders
4827 //=======================================================================
4829 SMESH::SMESH_MeshEditor::Sew_Error
4830 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4831 CORBA::Long SecondNodeID1,
4832 CORBA::Long LastNodeID1,
4833 CORBA::Long FirstNodeID2,
4834 CORBA::Long SecondNodeID2,
4835 CORBA::Long LastNodeID2,
4836 CORBA::Boolean CreatePolygons,
4837 CORBA::Boolean CreatePolyedrs)
4838 throw (SALOME::SALOME_Exception)
4843 SMESHDS_Mesh* aMesh = getMeshDS();
4845 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4846 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4847 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4848 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4849 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4850 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4852 if (!aBorderFirstNode ||
4853 !aBorderSecondNode||
4855 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4856 if (!aSide2FirstNode ||
4857 !aSide2SecondNode ||
4859 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4861 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4862 << FirstNodeID1 << ", "
4863 << SecondNodeID1 << ", "
4864 << LastNodeID1 << ", "
4865 << FirstNodeID2 << ", "
4866 << SecondNodeID2 << ", "
4867 << LastNodeID2 << ", "
4868 << CreatePolygons<< ", "
4869 << CreatePolyedrs<< " )";
4871 SMESH::SMESH_MeshEditor::Sew_Error error =
4872 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4883 declareMeshModified( /*isReComputeSafe=*/false );
4886 SMESH_CATCH( SMESH::throwCorbaException );
4887 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4891 //=======================================================================
4892 //function : SewConformFreeBorders
4894 //=======================================================================
4896 SMESH::SMESH_MeshEditor::Sew_Error
4897 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4898 CORBA::Long SecondNodeID1,
4899 CORBA::Long LastNodeID1,
4900 CORBA::Long FirstNodeID2,
4901 CORBA::Long SecondNodeID2)
4902 throw (SALOME::SALOME_Exception)
4907 SMESHDS_Mesh* aMesh = getMeshDS();
4909 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4910 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4911 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4912 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4913 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4914 const SMDS_MeshNode* aSide2ThirdNode = 0;
4916 if (!aBorderFirstNode ||
4917 !aBorderSecondNode||
4919 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4920 if (!aSide2FirstNode ||
4922 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4924 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4925 << FirstNodeID1 << ", "
4926 << SecondNodeID1 << ", "
4927 << LastNodeID1 << ", "
4928 << FirstNodeID2 << ", "
4929 << SecondNodeID2 << " )";
4931 SMESH::SMESH_MeshEditor::Sew_Error error =
4932 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4941 declareMeshModified( /*isReComputeSafe=*/false );
4944 SMESH_CATCH( SMESH::throwCorbaException );
4945 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4949 //=======================================================================
4950 //function : SewBorderToSide
4952 //=======================================================================
4954 SMESH::SMESH_MeshEditor::Sew_Error
4955 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4956 CORBA::Long SecondNodeIDOnFreeBorder,
4957 CORBA::Long LastNodeIDOnFreeBorder,
4958 CORBA::Long FirstNodeIDOnSide,
4959 CORBA::Long LastNodeIDOnSide,
4960 CORBA::Boolean CreatePolygons,
4961 CORBA::Boolean CreatePolyedrs)
4962 throw (SALOME::SALOME_Exception)
4967 SMESHDS_Mesh* aMesh = getMeshDS();
4969 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4970 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4971 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4972 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4973 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4974 const SMDS_MeshNode* aSide2ThirdNode = 0;
4976 if (!aBorderFirstNode ||
4977 !aBorderSecondNode||
4979 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4980 if (!aSide2FirstNode ||
4982 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4984 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4985 << FirstNodeIDOnFreeBorder << ", "
4986 << SecondNodeIDOnFreeBorder << ", "
4987 << LastNodeIDOnFreeBorder << ", "
4988 << FirstNodeIDOnSide << ", "
4989 << LastNodeIDOnSide << ", "
4990 << CreatePolygons << ", "
4991 << CreatePolyedrs << ") ";
4993 SMESH::SMESH_MeshEditor::Sew_Error error =
4994 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5004 declareMeshModified( /*isReComputeSafe=*/false );
5007 SMESH_CATCH( SMESH::throwCorbaException );
5008 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5012 //=======================================================================
5013 //function : SewSideElements
5015 //=======================================================================
5017 SMESH::SMESH_MeshEditor::Sew_Error
5018 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5019 const SMESH::long_array& IDsOfSide2Elements,
5020 CORBA::Long NodeID1OfSide1ToMerge,
5021 CORBA::Long NodeID1OfSide2ToMerge,
5022 CORBA::Long NodeID2OfSide1ToMerge,
5023 CORBA::Long NodeID2OfSide2ToMerge)
5024 throw (SALOME::SALOME_Exception)
5029 SMESHDS_Mesh* aMesh = getMeshDS();
5031 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5032 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5033 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5034 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5036 if (!aFirstNode1ToMerge ||
5037 !aFirstNode2ToMerge )
5038 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5039 if (!aSecondNode1ToMerge||
5040 !aSecondNode2ToMerge)
5041 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5043 TIDSortedElemSet aSide1Elems, aSide2Elems;
5044 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5045 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5047 TPythonDump() << "error = " << this << ".SewSideElements( "
5048 << IDsOfSide1Elements << ", "
5049 << IDsOfSide2Elements << ", "
5050 << NodeID1OfSide1ToMerge << ", "
5051 << NodeID1OfSide2ToMerge << ", "
5052 << NodeID2OfSide1ToMerge << ", "
5053 << NodeID2OfSide2ToMerge << ")";
5055 SMESH::SMESH_MeshEditor::Sew_Error error =
5056 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5059 aSecondNode1ToMerge,
5060 aSecondNode2ToMerge));
5062 declareMeshModified( /*isReComputeSafe=*/false );
5065 SMESH_CATCH( SMESH::throwCorbaException );
5066 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5069 //================================================================================
5071 * \brief Set new nodes for given element
5072 * \param ide - element id
5073 * \param newIDs - new node ids
5074 * \retval CORBA::Boolean - true if result is OK
5076 //================================================================================
5078 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5079 const SMESH::long_array& newIDs)
5080 throw (SALOME::SALOME_Exception)
5085 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5086 if(!elem) return false;
5088 int nbn = newIDs.length();
5090 vector<const SMDS_MeshNode*> aNodes(nbn);
5093 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5096 aNodes[nbn1] = aNode;
5099 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5100 << ide << ", " << newIDs << " )";
5102 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5104 declareMeshModified( /*isReComputeSafe=*/ !res );
5108 SMESH_CATCH( SMESH::throwCorbaException );
5112 //=======================================================================
5114 * \brief Makes a part of the mesh quadratic or bi-quadratic
5116 //=======================================================================
5118 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5119 CORBA::Boolean theToBiQuad,
5120 SMESH::SMESH_IDSource_ptr theObject)
5121 throw (SALOME::SALOME_Exception)
5126 TIDSortedElemSet elems;
5128 if ( !( elemsOK = CORBA::is_nil( theObject )))
5130 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5131 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5135 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5136 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5138 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5139 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5141 declareMeshModified( /*isReComputeSafe=*/false );
5144 SMESH_CATCH( SMESH::throwCorbaException );
5147 //=======================================================================
5148 //function : ConvertFromQuadratic
5150 //=======================================================================
5152 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5153 throw (SALOME::SALOME_Exception)
5158 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5159 TPythonDump() << this << ".ConvertFromQuadratic()";
5160 declareMeshModified( /*isReComputeSafe=*/!isDone );
5163 SMESH_CATCH( SMESH::throwCorbaException );
5167 //=======================================================================
5168 //function : ConvertToQuadratic
5170 //=======================================================================
5172 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5173 throw (SALOME::SALOME_Exception)
5175 convertToQuadratic( theForce3d, false );
5176 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5179 //================================================================================
5181 * \brief Makes a part of the mesh quadratic
5183 //================================================================================
5185 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5186 SMESH::SMESH_IDSource_ptr theObject)
5187 throw (SALOME::SALOME_Exception)
5189 convertToQuadratic( theForce3d, false, theObject );
5190 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5193 //================================================================================
5195 * \brief Makes a part of the mesh bi-quadratic
5197 //================================================================================
5199 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5200 SMESH::SMESH_IDSource_ptr theObject)
5201 throw (SALOME::SALOME_Exception)
5203 convertToQuadratic( theForce3d, true, theObject );
5204 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5207 //================================================================================
5209 * \brief Makes a part of the mesh linear
5211 //================================================================================
5213 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5214 throw (SALOME::SALOME_Exception)
5221 TIDSortedElemSet elems;
5222 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5224 if ( elems.empty() )
5226 ConvertFromQuadratic();
5228 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5230 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5234 getEditor().ConvertFromQuadratic(elems);
5237 declareMeshModified( /*isReComputeSafe=*/false );
5239 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5241 SMESH_CATCH( SMESH::throwCorbaException );
5244 //=======================================================================
5245 //function : makeMesh
5246 //purpose : create a named imported mesh
5247 //=======================================================================
5249 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5251 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5252 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5253 SALOMEDS::Study_var study = gen->GetCurrentStudy();
5254 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5255 gen->SetName( meshSO, theMeshName, "Mesh" );
5256 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5258 return mesh._retn();
5261 //=======================================================================
5262 //function : dumpGroupsList
5264 //=======================================================================
5266 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5267 const SMESH::ListOfGroups * theGroupList)
5269 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5270 if ( isDumpGroupList )
5271 theDumpPython << theGroupList << " = ";
5274 //================================================================================
5276 \brief Generates the unique group name.
5277 \param thePrefix name prefix
5280 //================================================================================
5282 std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix)
5284 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5285 set<std::string> groupNames;
5287 // Get existing group names
5288 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5289 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5290 if (CORBA::is_nil(aGroup))
5293 CORBA::String_var name = aGroup->GetName();
5294 groupNames.insert( name.in() );
5298 std::string name = thePrefix;
5301 while (!groupNames.insert(name).second)
5302 name = SMESH_Comment( thePrefix ) << "_" << index++;
5307 //================================================================================
5309 * \brief Prepare SMESH_IDSource for work
5311 //================================================================================
5313 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5315 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5317 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5318 filter->SetMesh( mesh );
5321 //================================================================================
5323 * \brief Retrieve elements of given type from SMESH_IDSource
5325 //================================================================================
5327 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5328 const SMESHDS_Mesh* theMeshDS,
5329 TIDSortedElemSet& theElemSet,
5330 const SMDSAbs_ElementType theType,
5331 const bool emptyIfIsMesh,
5332 IDSource_Error* error)
5335 if ( error ) *error = IDSource_OK;
5337 if ( CORBA::is_nil( theIDSource ))
5339 if ( error ) *error = IDSource_INVALID;
5342 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5344 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5345 *error = IDSource_EMPTY;
5348 prepareIdSource( theIDSource );
5349 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5350 if ( anIDs->length() == 0 )
5352 if ( error ) *error = IDSource_EMPTY;
5355 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5356 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5358 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5360 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5364 if ( error ) *error = IDSource_INVALID;
5370 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5371 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5373 if ( error ) *error = IDSource_INVALID;
5380 //================================================================================
5382 * \brief Duplicates given elements, i.e. creates new elements based on the
5383 * same nodes as the given ones.
5384 * \param theElements - container of elements to duplicate.
5385 * \param theGroupName - a name of group to contain the generated elements.
5386 * If a group with such a name already exists, the new elements
5387 * are added to the existng group, else a new group is created.
5388 * If \a theGroupName is empty, new elements are not added
5390 * \return a group where the new elements are added. NULL if theGroupName == "".
5393 //================================================================================
5395 SMESH::SMESH_Group_ptr
5396 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5397 const char* theGroupName)
5398 throw (SALOME::SALOME_Exception)
5400 SMESH::SMESH_Group_var newGroup;
5407 TIDSortedElemSet elems;
5408 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5410 getEditor().DoubleElements( elems );
5412 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5415 SMESH::ElementType type =
5416 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5417 // find existing group
5418 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5419 for ( size_t i = 0; i < groups->length(); ++i )
5420 if ( groups[i]->GetType() == type )
5422 CORBA::String_var name = groups[i]->GetName();
5423 if ( strcmp( name, theGroupName ) == 0 ) {
5424 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5428 // create a new group
5429 if ( newGroup->_is_nil() )
5430 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5432 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5434 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5435 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5436 for ( int i = 1; i <= aSeq.Length(); i++ )
5437 groupDS->SMDSGroup().Add( aSeq(i) );
5442 if ( !newGroup->_is_nil() )
5443 pyDump << newGroup << " = ";
5444 pyDump << this << ".DoubleElements( "
5445 << theElements << ", " << "'" << theGroupName <<"')";
5447 SMESH_CATCH( SMESH::throwCorbaException );
5449 return newGroup._retn();
5452 //================================================================================
5454 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5455 \param theNodes - identifiers of nodes to be doubled
5456 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5457 nodes. If list of element identifiers is empty then nodes are doubled but
5458 they not assigned to elements
5459 \return TRUE if operation has been completed successfully, FALSE otherwise
5460 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5462 //================================================================================
5464 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5465 const SMESH::long_array& theModifiedElems )
5466 throw (SALOME::SALOME_Exception)
5471 list< int > aListOfNodes;
5473 for ( i = 0, n = theNodes.length(); i < n; i++ )
5474 aListOfNodes.push_back( theNodes[ i ] );
5476 list< int > aListOfElems;
5477 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5478 aListOfElems.push_back( theModifiedElems[ i ] );
5480 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5482 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5484 // Update Python script
5485 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5489 SMESH_CATCH( SMESH::throwCorbaException );
5493 //================================================================================
5495 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5496 This method provided for convenience works as DoubleNodes() described above.
5497 \param theNodeId - identifier of node to be doubled.
5498 \param theModifiedElems - identifiers of elements to be updated.
5499 \return TRUE if operation has been completed successfully, FALSE otherwise
5500 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5502 //================================================================================
5504 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5505 const SMESH::long_array& theModifiedElems )
5506 throw (SALOME::SALOME_Exception)
5509 SMESH::long_array_var aNodes = new SMESH::long_array;
5510 aNodes->length( 1 );
5511 aNodes[ 0 ] = theNodeId;
5513 TPythonDump pyDump; // suppress dump by the next line
5515 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5517 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5521 SMESH_CATCH( SMESH::throwCorbaException );
5525 //================================================================================
5527 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5528 This method provided for convenience works as DoubleNodes() described above.
5529 \param theNodes - group of nodes to be doubled.
5530 \param theModifiedElems - group of elements to be updated.
5531 \return TRUE if operation has been completed successfully, FALSE otherwise
5532 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5534 //================================================================================
5536 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5537 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5538 throw (SALOME::SALOME_Exception)
5541 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5544 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5545 SMESH::long_array_var aModifiedElems;
5546 if ( !CORBA::is_nil( theModifiedElems ) )
5547 aModifiedElems = theModifiedElems->GetListOfID();
5549 aModifiedElems = new SMESH::long_array;
5551 TPythonDump pyDump; // suppress dump by the next line
5553 bool done = DoubleNodes( aNodes, aModifiedElems );
5555 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5559 SMESH_CATCH( SMESH::throwCorbaException );
5563 //================================================================================
5565 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5566 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5567 * \param theNodes - group of nodes to be doubled.
5568 * \param theModifiedElems - group of elements to be updated.
5569 * \return a new group with newly created nodes
5570 * \sa DoubleNodeGroup()
5572 //================================================================================
5574 SMESH::SMESH_Group_ptr
5575 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5576 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5577 throw (SALOME::SALOME_Exception)
5580 SMESH::SMESH_Group_var aNewGroup;
5582 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5583 return aNewGroup._retn();
5586 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5587 SMESH::long_array_var aModifiedElems;
5588 if ( !CORBA::is_nil( theModifiedElems ) )
5589 aModifiedElems = theModifiedElems->GetListOfID();
5591 aModifiedElems = new SMESH::long_array;
5592 aModifiedElems->length( 0 );
5595 TPythonDump pyDump; // suppress dump by the next line
5597 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5600 // Create group with newly created nodes
5601 SMESH::long_array_var anIds = GetLastCreatedNodes();
5602 if (anIds->length() > 0) {
5603 std::string anUnindexedName (theNodes->GetName());
5604 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5605 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5606 aNewGroup->Add(anIds);
5607 pyDump << aNewGroup << " = ";
5611 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5612 << theModifiedElems << " )";
5614 return aNewGroup._retn();
5616 SMESH_CATCH( SMESH::throwCorbaException );
5620 //================================================================================
5622 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5623 This method provided for convenience works as DoubleNodes() described above.
5624 \param theNodes - list of groups of nodes to be doubled
5625 \param theModifiedElems - list of groups of elements to be updated.
5626 \return TRUE if operation has been completed successfully, FALSE otherwise
5627 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5629 //================================================================================
5631 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5632 const SMESH::ListOfGroups& theModifiedElems )
5633 throw (SALOME::SALOME_Exception)
5638 std::list< int > aNodes;
5640 for ( i = 0, n = theNodes.length(); i < n; i++ )
5642 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5643 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5645 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5646 for ( j = 0, m = aCurr->length(); j < m; j++ )
5647 aNodes.push_back( aCurr[ j ] );
5651 std::list< int > anElems;
5652 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5654 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5655 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5657 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5658 for ( j = 0, m = aCurr->length(); j < m; j++ )
5659 anElems.push_back( aCurr[ j ] );
5663 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5665 declareMeshModified( /*isReComputeSafe=*/false );
5667 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5671 SMESH_CATCH( SMESH::throwCorbaException );
5675 //================================================================================
5677 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5678 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5679 * \param theNodes - group of nodes to be doubled.
5680 * \param theModifiedElems - group of elements to be updated.
5681 * \return a new group with newly created nodes
5682 * \sa DoubleNodeGroups()
5684 //================================================================================
5686 SMESH::SMESH_Group_ptr
5687 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5688 const SMESH::ListOfGroups& theModifiedElems )
5689 throw (SALOME::SALOME_Exception)
5691 SMESH::SMESH_Group_var aNewGroup;
5693 TPythonDump pyDump; // suppress dump by the next line
5695 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5699 // Create group with newly created nodes
5700 SMESH::long_array_var anIds = GetLastCreatedNodes();
5701 if (anIds->length() > 0) {
5702 std::string anUnindexedName (theNodes[0]->GetName());
5703 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5704 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5705 aNewGroup->Add(anIds);
5706 pyDump << aNewGroup << " = ";
5710 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5711 << theModifiedElems << " )";
5713 return aNewGroup._retn();
5717 //================================================================================
5719 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5720 \param theElems - the list of elements (edges or faces) to be replicated
5721 The nodes for duplication could be found from these elements
5722 \param theNodesNot - list of nodes to NOT replicate
5723 \param theAffectedElems - the list of elements (cells and edges) to which the
5724 replicated nodes should be associated to.
5725 \return TRUE if operation has been completed successfully, FALSE otherwise
5726 \sa DoubleNodeGroup(), DoubleNodeGroups()
5728 //================================================================================
5730 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5731 const SMESH::long_array& theNodesNot,
5732 const SMESH::long_array& theAffectedElems )
5733 throw (SALOME::SALOME_Exception)
5738 SMESHDS_Mesh* aMeshDS = getMeshDS();
5739 TIDSortedElemSet anElems, aNodes, anAffected;
5740 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5741 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5742 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5744 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5746 // Update Python script
5747 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5748 << theNodesNot << ", " << theAffectedElems << " )";
5750 declareMeshModified( /*isReComputeSafe=*/false );
5753 SMESH_CATCH( SMESH::throwCorbaException );
5757 //================================================================================
5759 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5760 \param theElems - the list of elements (edges or faces) to be replicated
5761 The nodes for duplication could be found from these elements
5762 \param theNodesNot - list of nodes to NOT replicate
5763 \param theShape - shape to detect affected elements (element which geometric center
5764 located on or inside shape).
5765 The replicated nodes should be associated to affected elements.
5766 \return TRUE if operation has been completed successfully, FALSE otherwise
5767 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5769 //================================================================================
5771 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5772 const SMESH::long_array& theNodesNot,
5773 GEOM::GEOM_Object_ptr theShape )
5774 throw (SALOME::SALOME_Exception)
5780 SMESHDS_Mesh* aMeshDS = getMeshDS();
5781 TIDSortedElemSet anElems, aNodes;
5782 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5783 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5785 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5786 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5788 // Update Python script
5789 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5790 << theNodesNot << ", " << theShape << " )";
5792 declareMeshModified( /*isReComputeSafe=*/false );
5795 SMESH_CATCH( SMESH::throwCorbaException );
5799 //================================================================================
5801 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5802 \param theElems - group of of elements (edges or faces) to be replicated
5803 \param theNodesNot - group of nodes not to replicated
5804 \param theAffectedElems - group of elements to which the replicated nodes
5805 should be associated to.
5806 \return TRUE if operation has been completed successfully, FALSE otherwise
5807 \sa DoubleNodes(), DoubleNodeGroups()
5809 //================================================================================
5812 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5813 SMESH::SMESH_GroupBase_ptr theNodesNot,
5814 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5815 throw (SALOME::SALOME_Exception)
5818 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5824 SMESHDS_Mesh* aMeshDS = getMeshDS();
5825 TIDSortedElemSet anElems, aNodes, anAffected;
5826 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5827 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5828 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5830 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5832 // Update Python script
5833 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5834 << theNodesNot << ", " << theAffectedElems << " )";
5836 declareMeshModified( /*isReComputeSafe=*/false );
5839 SMESH_CATCH( SMESH::throwCorbaException );
5843 //================================================================================
5845 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5846 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5847 * \param theElems - group of of elements (edges or faces) to be replicated
5848 * \param theNodesNot - group of nodes not to replicated
5849 * \param theAffectedElems - group of elements to which the replicated nodes
5850 * should be associated to.
5851 * \return a new group with newly created elements
5852 * \sa DoubleNodeElemGroup()
5854 //================================================================================
5856 SMESH::SMESH_Group_ptr
5857 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5858 SMESH::SMESH_GroupBase_ptr theNodesNot,
5859 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5860 throw (SALOME::SALOME_Exception)
5863 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5867 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5868 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5870 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5872 << theNodesNot << ", "
5873 << theAffectedElems << " )";
5875 return elemGroup._retn();
5878 //================================================================================
5880 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5881 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5882 * \param theElems - group of of elements (edges or faces) to be replicated
5883 * \param theNodesNot - group of nodes not to replicated
5884 * \param theAffectedElems - group of elements to which the replicated nodes
5885 * should be associated to.
5886 * \return a new group with newly created elements
5887 * \sa DoubleNodeElemGroup()
5889 //================================================================================
5891 SMESH::ListOfGroups*
5892 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5893 SMESH::SMESH_GroupBase_ptr theNodesNot,
5894 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5895 CORBA::Boolean theElemGroupNeeded,
5896 CORBA::Boolean theNodeGroupNeeded)
5897 throw (SALOME::SALOME_Exception)
5900 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5901 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5902 aTwoGroups->length( 2 );
5904 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5905 return aTwoGroups._retn();
5910 SMESHDS_Mesh* aMeshDS = getMeshDS();
5911 TIDSortedElemSet anElems, aNodes, anAffected;
5912 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5913 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5914 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5917 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5919 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5925 // Create group with newly created elements
5926 CORBA::String_var elemGroupName = theElems->GetName();
5927 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
5928 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5930 SMESH::long_array_var anIds = GetLastCreatedElems();
5931 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5932 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5933 aNewElemGroup->Add(anIds);
5935 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5937 SMESH::long_array_var anIds = GetLastCreatedNodes();
5938 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5939 aNewNodeGroup->Add(anIds);
5943 // Update Python script
5946 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5947 else pyDump << aNewElemGroup << ", ";
5948 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5949 else pyDump << aNewNodeGroup << " ] = ";
5951 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5952 << theNodesNot << ", "
5953 << theAffectedElems << ", "
5954 << theElemGroupNeeded << ", "
5955 << theNodeGroupNeeded <<" )";
5957 aTwoGroups[0] = aNewElemGroup._retn();
5958 aTwoGroups[1] = aNewNodeGroup._retn();
5959 return aTwoGroups._retn();
5961 SMESH_CATCH( SMESH::throwCorbaException );
5965 //================================================================================
5967 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5968 \param theElems - group of of elements (edges or faces) to be replicated
5969 \param theNodesNot - group of nodes not to replicated
5970 \param theShape - shape to detect affected elements (element which geometric center
5971 located on or inside shape).
5972 The replicated nodes should be associated to affected elements.
5973 \return TRUE if operation has been completed successfully, FALSE otherwise
5974 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5976 //================================================================================
5979 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5980 SMESH::SMESH_GroupBase_ptr theNodesNot,
5981 GEOM::GEOM_Object_ptr theShape )
5982 throw (SALOME::SALOME_Exception)
5985 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5991 SMESHDS_Mesh* aMeshDS = getMeshDS();
5992 TIDSortedElemSet anElems, aNodes, anAffected;
5993 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5994 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5996 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5997 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6000 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6002 // Update Python script
6003 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6004 << theNodesNot << ", " << theShape << " )";
6007 SMESH_CATCH( SMESH::throwCorbaException );
6011 //================================================================================
6013 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6014 * \param [in] theGrpList - groups
6015 * \param [in] theMeshDS - mesh
6016 * \param [out] theElemSet - set of elements
6017 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6019 //================================================================================
6021 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6022 SMESHDS_Mesh* theMeshDS,
6023 TIDSortedElemSet& theElemSet,
6024 const bool theIsNodeGrp)
6026 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6028 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6029 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6030 : aGrp->GetType() != SMESH::NODE ) )
6032 SMESH::long_array_var anIDs = aGrp->GetIDs();
6033 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6038 //================================================================================
6040 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6041 This method provided for convenience works as DoubleNodes() described above.
6042 \param theElems - list of groups of elements (edges or faces) to be replicated
6043 \param theNodesNot - list of groups of nodes not to replicated
6044 \param theAffectedElems - group of elements to which the replicated nodes
6045 should be associated to.
6046 \return TRUE if operation has been completed successfully, FALSE otherwise
6047 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6049 //================================================================================
6052 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6053 const SMESH::ListOfGroups& theNodesNot,
6054 const SMESH::ListOfGroups& theAffectedElems)
6055 throw (SALOME::SALOME_Exception)
6061 SMESHDS_Mesh* aMeshDS = getMeshDS();
6062 TIDSortedElemSet anElems, aNodes, anAffected;
6063 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6064 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6065 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6067 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6069 // Update Python script
6070 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6071 << &theNodesNot << ", " << &theAffectedElems << " )";
6073 declareMeshModified( /*isReComputeSafe=*/false );
6076 SMESH_CATCH( SMESH::throwCorbaException );
6080 //================================================================================
6082 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6083 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6084 \param theElems - list of groups of elements (edges or faces) to be replicated
6085 \param theNodesNot - list of groups of nodes not to replicated
6086 \param theAffectedElems - group of elements to which the replicated nodes
6087 should be associated to.
6088 * \return a new group with newly created elements
6089 * \sa DoubleNodeElemGroups()
6091 //================================================================================
6093 SMESH::SMESH_Group_ptr
6094 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6095 const SMESH::ListOfGroups& theNodesNot,
6096 const SMESH::ListOfGroups& theAffectedElems)
6097 throw (SALOME::SALOME_Exception)
6100 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6104 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6105 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6107 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6109 << theNodesNot << ", "
6110 << theAffectedElems << " )";
6112 return elemGroup._retn();
6115 //================================================================================
6117 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6118 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6119 \param theElems - list of groups of elements (edges or faces) to be replicated
6120 \param theNodesNot - list of groups of nodes not to replicated
6121 \param theAffectedElems - group of elements to which the replicated nodes
6122 should be associated to.
6123 * \return a new group with newly created elements
6124 * \sa DoubleNodeElemGroups()
6126 //================================================================================
6128 SMESH::ListOfGroups*
6129 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6130 const SMESH::ListOfGroups& theNodesNot,
6131 const SMESH::ListOfGroups& theAffectedElems,
6132 CORBA::Boolean theElemGroupNeeded,
6133 CORBA::Boolean theNodeGroupNeeded)
6134 throw (SALOME::SALOME_Exception)
6137 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6138 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6139 aTwoGroups->length( 2 );
6144 SMESHDS_Mesh* aMeshDS = getMeshDS();
6145 TIDSortedElemSet anElems, aNodes, anAffected;
6146 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6147 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6148 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6150 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6152 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6157 // Create group with newly created elements
6158 CORBA::String_var elemGroupName = theElems[0]->GetName();
6159 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6160 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6162 SMESH::long_array_var anIds = GetLastCreatedElems();
6163 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6164 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6165 aNewElemGroup->Add(anIds);
6167 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6169 SMESH::long_array_var anIds = GetLastCreatedNodes();
6170 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6171 aNewNodeGroup->Add(anIds);
6175 // Update Python script
6178 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6179 else pyDump << aNewElemGroup << ", ";
6180 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6181 else pyDump << aNewNodeGroup << " ] = ";
6183 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6184 << &theNodesNot << ", "
6185 << &theAffectedElems << ", "
6186 << theElemGroupNeeded << ", "
6187 << theNodeGroupNeeded << " )";
6189 aTwoGroups[0] = aNewElemGroup._retn();
6190 aTwoGroups[1] = aNewNodeGroup._retn();
6191 return aTwoGroups._retn();
6193 SMESH_CATCH( SMESH::throwCorbaException );
6197 //================================================================================
6199 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6200 This method provided for convenience works as DoubleNodes() described above.
6201 \param theElems - list of groups of elements (edges or faces) to be replicated
6202 \param theNodesNot - list of groups of nodes not to replicated
6203 \param theShape - shape to detect affected elements (element which geometric center
6204 located on or inside shape).
6205 The replicated nodes should be associated to affected elements.
6206 \return TRUE if operation has been completed successfully, FALSE otherwise
6207 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6209 //================================================================================
6212 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6213 const SMESH::ListOfGroups& theNodesNot,
6214 GEOM::GEOM_Object_ptr theShape )
6215 throw (SALOME::SALOME_Exception)
6221 SMESHDS_Mesh* aMeshDS = getMeshDS();
6222 TIDSortedElemSet anElems, aNodes;
6223 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6224 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6226 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6227 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6229 // Update Python script
6230 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6231 << &theNodesNot << ", " << theShape << " )";
6233 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6236 SMESH_CATCH( SMESH::throwCorbaException );
6240 //================================================================================
6242 \brief Identify the elements that will be affected by node duplication (actual
6243 duplication is not performed.
6244 This method is the first step of DoubleNodeElemGroupsInRegion.
6245 \param theElems - list of groups of elements (edges or faces) to be replicated
6246 \param theNodesNot - list of groups of nodes not to replicated
6247 \param theShape - shape to detect affected elements (element which geometric center
6248 located on or inside shape).
6249 The replicated nodes should be associated to affected elements.
6250 \return groups of affected elements
6251 \sa DoubleNodeElemGroupsInRegion()
6253 //================================================================================
6254 SMESH::ListOfGroups*
6255 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6256 const SMESH::ListOfGroups& theNodesNot,
6257 GEOM::GEOM_Object_ptr theShape )
6258 throw (SALOME::SALOME_Exception)
6261 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6262 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6263 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6264 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6268 ::SMESH_MeshEditor aMeshEditor(myMesh);
6270 SMESHDS_Mesh* aMeshDS = getMeshDS();
6271 TIDSortedElemSet anElems, aNodes;
6272 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6273 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6274 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6276 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6277 TIDSortedElemSet anAffected;
6278 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6280 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6283 if ( aResult && anAffected.size() > 0 )
6285 SMESH::long_array_var volumeIds = new SMESH::long_array;
6286 SMESH::long_array_var faceIds = new SMESH::long_array;
6287 SMESH::long_array_var edgeIds = new SMESH::long_array;
6288 volumeIds->length( anAffected.size() );
6289 faceIds ->length( anAffected.size() );
6290 edgeIds ->length( anAffected.size() );
6295 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6296 for (; eIt != anAffected.end(); ++eIt)
6298 const SMDS_MeshElement* anElem = *eIt;
6299 int elemId = anElem->GetID();
6300 switch ( anElem->GetType() ) {
6301 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6302 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6303 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6307 volumeIds->length(ivol);
6308 faceIds->length(iface);
6309 edgeIds->length(iedge);
6314 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6315 generateGroupName("affectedVolumes").c_str());
6316 aNewVolumeGroup->Add(volumeIds);
6317 aListOfGroups->length( nbGroups+1 );
6318 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6322 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6323 generateGroupName("affectedFaces").c_str());
6324 aNewFaceGroup->Add(faceIds);
6325 aListOfGroups->length( nbGroups+1 );
6326 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6330 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6331 generateGroupName("affectedEdges").c_str());
6332 aNewEdgeGroup->Add(edgeIds);
6333 aListOfGroups->length( nbGroups+1 );
6334 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6338 // Update Python script
6340 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6341 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6343 return aListOfGroups._retn();
6345 SMESH_CATCH( SMESH::throwCorbaException );
6349 //================================================================================
6351 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6352 The created 2D mesh elements based on nodes of free faces of boundary volumes
6353 \return TRUE if operation has been completed successfully, FALSE otherwise
6355 //================================================================================
6357 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6358 throw (SALOME::SALOME_Exception)
6363 bool aResult = getEditor().Make2DMeshFrom3D();
6365 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6367 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6370 SMESH_CATCH( SMESH::throwCorbaException );
6374 //================================================================================
6376 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6377 * The list of groups must contain at least two groups. The groups have to be disjoint:
6378 * no common element into two different groups.
6379 * The nodes of the internal faces at the boundaries of the groups are doubled.
6380 * Optionally, the internal faces are replaced by flat elements.
6381 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6382 * The flat elements are stored in groups of volumes.
6383 * These groups are named according to the position of the group in the list:
6384 * 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.
6385 * 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.
6386 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6387 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6388 * \param theDomains - list of groups of volumes
6389 * \param createJointElems - if TRUE, create the elements
6390 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6391 * the boundary between \a theDomains and the rest mesh
6392 * \return TRUE if operation has been completed successfully, FALSE otherwise
6394 //================================================================================
6397 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6398 CORBA::Boolean createJointElems,
6399 CORBA::Boolean onAllBoundaries )
6400 throw (SALOME::SALOME_Exception)
6407 SMESHDS_Mesh* aMeshDS = getMeshDS();
6409 // MESSAGE("theDomains.length = "<<theDomains.length());
6410 if ( theDomains.length() <= 1 && !onAllBoundaries )
6411 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6413 vector<TIDSortedElemSet> domains;
6414 domains.resize( theDomains.length() );
6416 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6418 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6419 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6421 // if ( aGrp->GetType() != SMESH::VOLUME )
6422 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6423 SMESH::long_array_var anIDs = aGrp->GetIDs();
6424 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6428 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6429 // TODO publish the groups of flat elements in study
6431 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6433 // Update Python script
6434 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6435 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6437 SMESH_CATCH( SMESH::throwCorbaException );
6439 myMesh_i->CreateGroupServants(); // publish created groups if any
6444 //================================================================================
6446 * \brief Double nodes on some external faces and create flat elements.
6447 * Flat elements are mainly used by some types of mechanic calculations.
6449 * Each group of the list must be constituted of faces.
6450 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6451 * @param theGroupsOfFaces - list of groups of faces
6452 * @return TRUE if operation has been completed successfully, FALSE otherwise
6454 //================================================================================
6457 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6458 throw (SALOME::SALOME_Exception)
6463 SMESHDS_Mesh* aMeshDS = getMeshDS();
6465 vector<TIDSortedElemSet> faceGroups;
6468 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6470 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6471 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6473 TIDSortedElemSet faceGroup;
6475 faceGroups.push_back(faceGroup);
6476 SMESH::long_array_var anIDs = aGrp->GetIDs();
6477 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6481 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6482 // TODO publish the groups of flat elements in study
6484 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6486 // Update Python script
6487 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6490 SMESH_CATCH( SMESH::throwCorbaException );
6494 //================================================================================
6496 * \brief Identify all the elements around a geom shape, get the faces delimiting
6499 * Build groups of volume to remove, groups of faces to replace on the skin of the
6500 * object, groups of faces to remove inside the object, (idem edges).
6501 * Build ordered list of nodes at the border of each group of faces to replace
6502 * (to be used to build a geom subshape).
6504 //================================================================================
6506 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6507 GEOM::GEOM_Object_ptr theShape,
6508 const char* groupName,
6509 const SMESH::double_array& theNodesCoords,
6510 SMESH::array_of_long_array_out GroupsOfNodes)
6511 throw (SALOME::SALOME_Exception)
6516 std::vector<std::vector<int> > aListOfListOfNodes;
6517 ::SMESH_MeshEditor aMeshEditor( myMesh );
6519 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6520 if ( !theNodeSearcher )
6521 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6523 vector<double> nodesCoords;
6524 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6526 nodesCoords.push_back( theNodesCoords[i] );
6529 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6530 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6531 nodesCoords, aListOfListOfNodes);
6533 GroupsOfNodes = new SMESH::array_of_long_array;
6534 GroupsOfNodes->length( aListOfListOfNodes.size() );
6535 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6536 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6538 vector<int>& aListOfNodes = *llIt;
6539 vector<int>::iterator lIt = aListOfNodes.begin();;
6540 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6541 aGroup.length( aListOfNodes.size() );
6542 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6543 aGroup[ j ] = (*lIt);
6545 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6548 << ", '" << groupName << "', "
6549 << theNodesCoords << " )";
6551 SMESH_CATCH( SMESH::throwCorbaException );
6554 // issue 20749 ===================================================================
6556 * \brief Creates missing boundary elements
6557 * \param elements - elements whose boundary is to be checked
6558 * \param dimension - defines type of boundary elements to create
6559 * \param groupName - a name of group to store created boundary elements in,
6560 * "" means not to create the group
6561 * \param meshName - a name of new mesh to store created boundary elements in,
6562 * "" means not to create the new mesh
6563 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6564 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6565 * boundary elements will be copied into the new mesh
6566 * \param group - returns the create group, if any
6567 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6569 // ================================================================================
6571 SMESH::SMESH_Mesh_ptr
6572 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6573 SMESH::Bnd_Dimension dim,
6574 const char* groupName,
6575 const char* meshName,
6576 CORBA::Boolean toCopyElements,
6577 CORBA::Boolean toCopyExistingBondary,
6578 SMESH::SMESH_Group_out group)
6579 throw (SALOME::SALOME_Exception)
6584 if ( dim > SMESH::BND_1DFROM2D )
6585 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6587 SMESHDS_Mesh* aMeshDS = getMeshDS();
6589 SMESH::SMESH_Mesh_var mesh_var;
6590 SMESH::SMESH_Group_var group_var;
6594 TIDSortedElemSet elements;
6595 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6596 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6600 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6601 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6603 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6605 // group of new boundary elements
6606 SMESH_Group* smesh_group = 0;
6607 if ( strlen(groupName) )
6609 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6610 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6611 smesh_group = group_i->GetSmeshGroup();
6615 getEditor().MakeBoundaryMesh( elements,
6616 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6620 toCopyExistingBondary);
6623 smesh_mesh->GetMeshDS()->Modified();
6626 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6628 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6629 if ( mesh_var->_is_nil() )
6630 pyDump << myMesh_i->_this() << ", ";
6632 pyDump << mesh_var << ", ";
6633 if ( group_var->_is_nil() )
6634 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6636 pyDump << group_var << " = ";
6637 pyDump << this << ".MakeBoundaryMesh( "
6639 << "SMESH." << dimName[int(dim)] << ", "
6640 << "'" << groupName << "', "
6641 << "'" << meshName<< "', "
6642 << toCopyElements << ", "
6643 << toCopyExistingBondary << ")";
6645 group = group_var._retn();
6646 return mesh_var._retn();
6648 SMESH_CATCH( SMESH::throwCorbaException );
6649 return SMESH::SMESH_Mesh::_nil();
6652 //================================================================================
6654 * \brief Creates missing boundary elements
6655 * \param dimension - defines type of boundary elements to create
6656 * \param groupName - a name of group to store all boundary elements in,
6657 * "" means not to create the group
6658 * \param meshName - a name of a new mesh, which is a copy of the initial
6659 * mesh + created boundary elements; "" means not to create the new mesh
6660 * \param toCopyAll - if true, the whole initial mesh will be copied into
6661 * the new mesh else only boundary elements will be copied into the new mesh
6662 * \param groups - optional groups of elements to make boundary around
6663 * \param mesh - returns the mesh where elements were added to
6664 * \param group - returns the created group, if any
6665 * \retval long - number of added boundary elements
6667 //================================================================================
6669 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6670 const char* groupName,
6671 const char* meshName,
6672 CORBA::Boolean toCopyAll,
6673 const SMESH::ListOfIDSources& groups,
6674 SMESH::SMESH_Mesh_out mesh,
6675 SMESH::SMESH_Group_out group)
6676 throw (SALOME::SALOME_Exception)
6681 if ( dim > SMESH::BND_1DFROM2D )
6682 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6684 // separate groups belonging to this and other mesh
6685 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6686 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6687 groupsOfThisMesh ->length( groups.length() );
6688 groupsOfOtherMesh->length( groups.length() );
6689 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6690 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
6692 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6693 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6694 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6696 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6697 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6698 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
6700 groupsOfThisMesh->length( nbGroups );
6701 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6706 if ( nbGroupsOfOtherMesh > 0 )
6708 // process groups belonging to another mesh
6709 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6710 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6711 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6712 groupsOfOtherMesh, mesh, group );
6715 SMESH::SMESH_Mesh_var mesh_var;
6716 SMESH::SMESH_Group_var group_var;
6719 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6720 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6724 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6726 /*toCopyGroups=*/false,
6727 /*toKeepIDs=*/true);
6729 mesh_var = makeMesh(meshName);
6731 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6732 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6735 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6736 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6738 // group of boundary elements
6739 SMESH_Group* smesh_group = 0;
6740 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6741 if ( strlen(groupName) )
6743 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6744 group_var = mesh_i->CreateGroup( groupType, groupName );
6745 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6746 smesh_group = group_i->GetSmeshGroup();
6749 TIDSortedElemSet elements;
6751 if ( groups.length() > 0 )
6753 for ( int i = 0; i < nbGroups; ++i )
6756 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6758 SMESH::Bnd_Dimension bdim =
6759 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6760 nbAdded += getEditor().MakeBoundaryMesh( elements,
6761 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6764 /*toCopyElements=*/false,
6765 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6766 /*toAddExistingBondary=*/true,
6767 /*aroundElements=*/true);
6773 nbAdded += getEditor().MakeBoundaryMesh( elements,
6774 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6777 /*toCopyElements=*/false,
6778 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6779 /*toAddExistingBondary=*/true);
6781 tgtMesh->GetMeshDS()->Modified();
6783 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6785 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6786 pyDump << "nbAdded, ";
6787 if ( mesh_var->_is_nil() )
6788 pyDump << myMesh_i->_this() << ", ";
6790 pyDump << mesh_var << ", ";
6791 if ( group_var->_is_nil() )
6792 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6794 pyDump << group_var << " = ";
6795 pyDump << this << ".MakeBoundaryElements( "
6796 << "SMESH." << dimName[int(dim)] << ", "
6797 << "'" << groupName << "', "
6798 << "'" << meshName<< "', "
6799 << toCopyAll << ", "
6802 mesh = mesh_var._retn();
6803 group = group_var._retn();
6806 SMESH_CATCH( SMESH::throwCorbaException );