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 split.
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 : IsManifold
4582 //purpose : Check if a 2D mesh is manifold
4583 //=======================================================================
4585 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4586 throw (SALOME::SALOME_Exception)
4588 bool isManifold = true;
4591 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4592 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4594 /*closedOnly=*/true,
4596 SMESH_CATCH( SMESH::throwCorbaException );
4601 //=======================================================================
4602 //function : IsCoherentOrientation2D
4603 //purpose : Check if orientation of 2D elements is coherent
4604 //=======================================================================
4606 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4607 throw (SALOME::SALOME_Exception)
4609 bool isGoodOri = true;
4612 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4613 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4615 /*closedOnly=*/true,
4618 SMESH_CATCH( SMESH::throwCorbaException );
4623 //=======================================================================
4624 //function : FindFreeBorders
4625 //purpose : Returns all or only closed FreeBorder's.
4626 //=======================================================================
4628 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4629 throw (SALOME::SALOME_Exception)
4631 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4634 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4635 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4637 resBorders->length( foundFreeBordes.size() );
4638 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
4640 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
4641 SMESH::FreeBorder& bordOut = resBorders[i];
4642 bordOut.nodeIDs.length( bordNodes.size() );
4643 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
4644 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
4647 SMESH_CATCH( SMESH::throwCorbaException );
4649 return resBorders._retn();
4652 //=======================================================================
4653 //function : FillHole
4654 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
4655 //=======================================================================
4657 void SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole)
4658 throw (SALOME::SALOME_Exception)
4662 if ( theHole.nodeIDs.length() < 4 )
4663 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
4664 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
4665 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
4666 "First and last nodes must be same", SALOME::BAD_PARAM);
4668 SMESH_MeshAlgos::TFreeBorder bordNodes;
4669 bordNodes.resize( theHole.nodeIDs.length() );
4670 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
4672 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
4673 if ( !bordNodes[ iN ] )
4674 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
4675 << " does not exist", SALOME::BAD_PARAM);
4680 MeshEditor_I::TPreviewMesh* previewMesh = 0;
4681 SMDS_Mesh* meshDS = getMeshDS();
4682 if ( myIsPreviewMode )
4684 // copy faces sharing nodes of theHole
4685 TIDSortedElemSet holeFaces;
4686 previewMesh = getPreviewMesh( SMDSAbs_Face );
4687 for ( size_t i = 0; i < bordNodes.size(); ++i )
4689 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
4690 while ( fIt->more() )
4692 const SMDS_MeshElement* face = fIt->next();
4693 if ( holeFaces.insert( face ).second )
4694 previewMesh->Copy( face );
4696 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
4697 ASSERT( bordNodes[i] );
4699 meshDS = previewMesh->GetMeshDS();
4702 std::vector<const SMDS_MeshElement*> newFaces;
4703 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
4705 if ( myIsPreviewMode )
4707 previewMesh->Clear();
4708 for ( size_t i = 0; i < newFaces.size(); ++i )
4709 previewMesh->Copy( newFaces[i] );
4713 getEditor().ClearLastCreated();
4714 SMESH_SequenceOfElemPtr& aSeq =
4715 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
4716 for ( size_t i = 0; i < newFaces.size(); ++i )
4717 aSeq.Append( newFaces[i] );
4719 TPythonDump() << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
4722 SMESH_CATCH( SMESH::throwCorbaException );
4725 //=======================================================================
4726 //function : convError
4728 //=======================================================================
4730 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4732 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4736 RETCASE( SEW_BORDER1_NOT_FOUND );
4737 RETCASE( SEW_BORDER2_NOT_FOUND );
4738 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4739 RETCASE( SEW_BAD_SIDE_NODES );
4740 RETCASE( SEW_VOLUMES_TO_SPLIT );
4741 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4742 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4743 RETCASE( SEW_BAD_SIDE1_NODES );
4744 RETCASE( SEW_BAD_SIDE2_NODES );
4745 RETCASE( SEW_INTERNAL_ERROR );
4747 return SMESH::SMESH_MeshEditor::SEW_OK;
4750 //=======================================================================
4752 * Returns groups of FreeBorder's coincident within the given tolerance.
4753 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
4754 * to free borders being compared is used.
4756 //=======================================================================
4758 SMESH::CoincidentFreeBorders*
4759 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
4761 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
4765 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
4766 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
4768 // copy free borders
4769 aCFB->borders.length( cfb._borders.size() );
4770 for ( size_t i = 0; i < cfb._borders.size(); ++i )
4772 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
4773 SMESH::FreeBorder& aBRD = aCFB->borders[i];
4774 aBRD.nodeIDs.length( nodes.size() );
4775 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4776 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
4779 // copy coincident parts
4780 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
4781 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
4783 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
4784 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
4785 aGRP.length( grp.size() );
4786 for ( size_t iP = 0; iP < grp.size(); ++iP )
4788 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
4789 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4790 aPART.border = part._border;
4791 aPART.node1 = part._node1;
4792 aPART.node2 = part._node2;
4793 aPART.nodeLast = part._nodeLast;
4796 SMESH_CATCH( SMESH::doNothing );
4798 TPythonDump() << "CoincidentFreeBorders = "
4799 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
4801 return aCFB._retn();
4804 //=======================================================================
4806 * Sew FreeBorder's of each group
4808 //=======================================================================
4810 CORBA::Short SMESH_MeshEditor_i::
4811 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
4812 CORBA::Boolean createPolygons,
4813 CORBA::Boolean createPolyhedra)
4814 throw (SALOME::SALOME_Exception)
4816 CORBA::Short nbSewed = 0;
4818 SMESH_MeshAlgos::TFreeBorderVec groups;
4819 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
4821 // check the input and collect nodes
4822 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
4824 borderNodes.clear();
4825 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
4826 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
4828 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4829 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
4830 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
4832 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
4834 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
4835 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
4836 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
4837 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
4838 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
4839 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4841 // do not keep these nodes for further sewing as nodes can be removed by the sewing
4842 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
4843 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
4844 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
4846 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
4848 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
4850 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4852 borderNodes.push_back( n1 );
4853 borderNodes.push_back( n2 );
4854 borderNodes.push_back( n3 );
4856 groups.push_back( borderNodes );
4859 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
4860 // to get nodes that replace other nodes during merge we create 0D elements
4861 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
4864 vector< const SMDS_MeshElement* > tmp0Delems;
4865 for ( size_t i = 0; i < groups.size(); ++i )
4867 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4868 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4870 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
4872 tmp0Delems.push_back( it0D->next() );
4874 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
4878 // cout << endl << "INIT" << endl;
4879 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4881 // cout << i << " ";
4882 // if ( i % 3 == 0 ) cout << "^ ";
4883 // tmp0Delems[i]->GetNode(0)->Print( cout );
4888 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
4890 for ( size_t i = 0; i < groups.size(); ++i )
4892 bool isBordToBord = true;
4893 bool groupSewed = false;
4894 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4895 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
4897 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
4898 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
4899 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
4901 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
4902 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
4903 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
4905 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
4908 // TIDSortedElemSet emptySet, avoidSet;
4909 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
4911 // cout << "WRONG 2nd 1" << endl;
4912 // n0->Print( cout );
4913 // n1->Print( cout );
4915 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
4917 // cout << "WRONG 2nd 2" << endl;
4918 // n3->Print( cout );
4919 // n4->Print( cout );
4922 if ( !isBordToBord )
4924 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
4925 n2 = 0; // and n2 is not used
4927 // 1st border moves to 2nd
4928 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
4930 /*2ndIsFreeBorder=*/ isBordToBord,
4931 createPolygons, createPolyhedra);
4932 groupSewed = ( res == ok );
4934 isBordToBord = false;
4935 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
4936 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
4938 // cout << t << " ";
4939 // if ( t % 3 == 0 ) cout << "^ ";
4940 // tmp0Delems[t]->GetNode(0)->Print( cout );
4943 i0D += nodes.size();
4944 nbSewed += groupSewed;
4947 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
4948 << freeBorders << ", "
4949 << createPolygons << ", "
4950 << createPolyhedra << " )";
4952 SMESH_CATCH( SMESH::doNothing );
4954 declareMeshModified( /*isReComputeSafe=*/false );
4956 // remove tmp 0D elements
4958 set< const SMDS_MeshElement* > removed0D;
4959 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4961 if ( removed0D.insert( tmp0Delems[i] ).second )
4962 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
4964 SMESH_CATCH( SMESH::throwCorbaException );
4969 //=======================================================================
4970 //function : SewFreeBorders
4972 //=======================================================================
4974 SMESH::SMESH_MeshEditor::Sew_Error
4975 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4976 CORBA::Long SecondNodeID1,
4977 CORBA::Long LastNodeID1,
4978 CORBA::Long FirstNodeID2,
4979 CORBA::Long SecondNodeID2,
4980 CORBA::Long LastNodeID2,
4981 CORBA::Boolean CreatePolygons,
4982 CORBA::Boolean CreatePolyedrs)
4983 throw (SALOME::SALOME_Exception)
4988 SMESHDS_Mesh* aMesh = getMeshDS();
4990 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4991 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4992 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4993 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4994 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4995 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4997 if (!aBorderFirstNode ||
4998 !aBorderSecondNode||
5000 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5001 if (!aSide2FirstNode ||
5002 !aSide2SecondNode ||
5004 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5006 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5007 << FirstNodeID1 << ", "
5008 << SecondNodeID1 << ", "
5009 << LastNodeID1 << ", "
5010 << FirstNodeID2 << ", "
5011 << SecondNodeID2 << ", "
5012 << LastNodeID2 << ", "
5013 << CreatePolygons<< ", "
5014 << CreatePolyedrs<< " )";
5016 SMESH::SMESH_MeshEditor::Sew_Error error =
5017 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5028 declareMeshModified( /*isReComputeSafe=*/false );
5031 SMESH_CATCH( SMESH::throwCorbaException );
5032 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5036 //=======================================================================
5037 //function : SewConformFreeBorders
5039 //=======================================================================
5041 SMESH::SMESH_MeshEditor::Sew_Error
5042 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5043 CORBA::Long SecondNodeID1,
5044 CORBA::Long LastNodeID1,
5045 CORBA::Long FirstNodeID2,
5046 CORBA::Long SecondNodeID2)
5047 throw (SALOME::SALOME_Exception)
5052 SMESHDS_Mesh* aMesh = getMeshDS();
5054 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5055 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5056 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5057 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5058 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5059 const SMDS_MeshNode* aSide2ThirdNode = 0;
5061 if (!aBorderFirstNode ||
5062 !aBorderSecondNode||
5064 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5065 if (!aSide2FirstNode ||
5067 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5069 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5070 << FirstNodeID1 << ", "
5071 << SecondNodeID1 << ", "
5072 << LastNodeID1 << ", "
5073 << FirstNodeID2 << ", "
5074 << SecondNodeID2 << " )";
5076 SMESH::SMESH_MeshEditor::Sew_Error error =
5077 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5086 declareMeshModified( /*isReComputeSafe=*/false );
5089 SMESH_CATCH( SMESH::throwCorbaException );
5090 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5094 //=======================================================================
5095 //function : SewBorderToSide
5097 //=======================================================================
5099 SMESH::SMESH_MeshEditor::Sew_Error
5100 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5101 CORBA::Long SecondNodeIDOnFreeBorder,
5102 CORBA::Long LastNodeIDOnFreeBorder,
5103 CORBA::Long FirstNodeIDOnSide,
5104 CORBA::Long LastNodeIDOnSide,
5105 CORBA::Boolean CreatePolygons,
5106 CORBA::Boolean CreatePolyedrs)
5107 throw (SALOME::SALOME_Exception)
5112 SMESHDS_Mesh* aMesh = getMeshDS();
5114 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5115 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5116 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5117 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5118 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5119 const SMDS_MeshNode* aSide2ThirdNode = 0;
5121 if (!aBorderFirstNode ||
5122 !aBorderSecondNode||
5124 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5125 if (!aSide2FirstNode ||
5127 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5129 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5130 << FirstNodeIDOnFreeBorder << ", "
5131 << SecondNodeIDOnFreeBorder << ", "
5132 << LastNodeIDOnFreeBorder << ", "
5133 << FirstNodeIDOnSide << ", "
5134 << LastNodeIDOnSide << ", "
5135 << CreatePolygons << ", "
5136 << CreatePolyedrs << ") ";
5138 SMESH::SMESH_MeshEditor::Sew_Error error =
5139 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5149 declareMeshModified( /*isReComputeSafe=*/false );
5152 SMESH_CATCH( SMESH::throwCorbaException );
5153 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5157 //=======================================================================
5158 //function : SewSideElements
5160 //=======================================================================
5162 SMESH::SMESH_MeshEditor::Sew_Error
5163 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5164 const SMESH::long_array& IDsOfSide2Elements,
5165 CORBA::Long NodeID1OfSide1ToMerge,
5166 CORBA::Long NodeID1OfSide2ToMerge,
5167 CORBA::Long NodeID2OfSide1ToMerge,
5168 CORBA::Long NodeID2OfSide2ToMerge)
5169 throw (SALOME::SALOME_Exception)
5174 SMESHDS_Mesh* aMesh = getMeshDS();
5176 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5177 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5178 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5179 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5181 if (!aFirstNode1ToMerge ||
5182 !aFirstNode2ToMerge )
5183 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5184 if (!aSecondNode1ToMerge||
5185 !aSecondNode2ToMerge)
5186 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5188 TIDSortedElemSet aSide1Elems, aSide2Elems;
5189 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5190 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5192 TPythonDump() << "error = " << this << ".SewSideElements( "
5193 << IDsOfSide1Elements << ", "
5194 << IDsOfSide2Elements << ", "
5195 << NodeID1OfSide1ToMerge << ", "
5196 << NodeID1OfSide2ToMerge << ", "
5197 << NodeID2OfSide1ToMerge << ", "
5198 << NodeID2OfSide2ToMerge << ")";
5200 SMESH::SMESH_MeshEditor::Sew_Error error =
5201 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5204 aSecondNode1ToMerge,
5205 aSecondNode2ToMerge));
5207 declareMeshModified( /*isReComputeSafe=*/false );
5210 SMESH_CATCH( SMESH::throwCorbaException );
5211 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5214 //================================================================================
5216 * \brief Set new nodes for given element
5217 * \param ide - element id
5218 * \param newIDs - new node ids
5219 * \retval CORBA::Boolean - true if result is OK
5221 //================================================================================
5223 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5224 const SMESH::long_array& newIDs)
5225 throw (SALOME::SALOME_Exception)
5230 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5231 if(!elem) return false;
5233 int nbn = newIDs.length();
5235 vector<const SMDS_MeshNode*> aNodes(nbn);
5238 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5241 aNodes[nbn1] = aNode;
5244 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5245 << ide << ", " << newIDs << " )";
5247 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5249 declareMeshModified( /*isReComputeSafe=*/ !res );
5253 SMESH_CATCH( SMESH::throwCorbaException );
5257 //=======================================================================
5259 * \brief Makes a part of the mesh quadratic or bi-quadratic
5261 //=======================================================================
5263 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5264 CORBA::Boolean theToBiQuad,
5265 SMESH::SMESH_IDSource_ptr theObject)
5266 throw (SALOME::SALOME_Exception)
5271 TIDSortedElemSet elems;
5273 if ( !( elemsOK = CORBA::is_nil( theObject )))
5275 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5276 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5280 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5281 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5283 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5284 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5286 declareMeshModified( /*isReComputeSafe=*/false );
5289 SMESH_CATCH( SMESH::throwCorbaException );
5292 //=======================================================================
5293 //function : ConvertFromQuadratic
5295 //=======================================================================
5297 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5298 throw (SALOME::SALOME_Exception)
5303 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5304 TPythonDump() << this << ".ConvertFromQuadratic()";
5305 declareMeshModified( /*isReComputeSafe=*/!isDone );
5308 SMESH_CATCH( SMESH::throwCorbaException );
5312 //=======================================================================
5313 //function : ConvertToQuadratic
5315 //=======================================================================
5317 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5318 throw (SALOME::SALOME_Exception)
5320 convertToQuadratic( theForce3d, false );
5321 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5324 //================================================================================
5326 * \brief Makes a part of the mesh quadratic
5328 //================================================================================
5330 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5331 SMESH::SMESH_IDSource_ptr theObject)
5332 throw (SALOME::SALOME_Exception)
5334 convertToQuadratic( theForce3d, false, theObject );
5335 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5338 //================================================================================
5340 * \brief Makes a part of the mesh bi-quadratic
5342 //================================================================================
5344 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5345 SMESH::SMESH_IDSource_ptr theObject)
5346 throw (SALOME::SALOME_Exception)
5348 convertToQuadratic( theForce3d, true, theObject );
5349 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5352 //================================================================================
5354 * \brief Makes a part of the mesh linear
5356 //================================================================================
5358 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5359 throw (SALOME::SALOME_Exception)
5366 TIDSortedElemSet elems;
5367 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5369 if ( elems.empty() )
5371 ConvertFromQuadratic();
5373 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5375 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5379 getEditor().ConvertFromQuadratic(elems);
5382 declareMeshModified( /*isReComputeSafe=*/false );
5384 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5386 SMESH_CATCH( SMESH::throwCorbaException );
5389 //=======================================================================
5390 //function : makeMesh
5391 //purpose : create a named imported mesh
5392 //=======================================================================
5394 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5396 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5397 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5398 SALOMEDS::Study_var study = gen->GetCurrentStudy();
5399 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5400 gen->SetName( meshSO, theMeshName, "Mesh" );
5401 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5403 return mesh._retn();
5406 //=======================================================================
5407 //function : dumpGroupsList
5409 //=======================================================================
5411 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5412 const SMESH::ListOfGroups * theGroupList)
5414 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5415 if ( isDumpGroupList )
5416 theDumpPython << theGroupList << " = ";
5419 //================================================================================
5421 \brief Generates the unique group name.
5422 \param thePrefix name prefix
5425 //================================================================================
5427 std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix)
5429 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5430 set<std::string> groupNames;
5432 // Get existing group names
5433 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5434 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5435 if (CORBA::is_nil(aGroup))
5438 CORBA::String_var name = aGroup->GetName();
5439 groupNames.insert( name.in() );
5443 std::string name = thePrefix;
5446 while (!groupNames.insert(name).second)
5447 name = SMESH_Comment( thePrefix ) << "_" << index++;
5452 //================================================================================
5454 * \brief Prepare SMESH_IDSource for work
5456 //================================================================================
5458 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5460 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5462 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5463 filter->SetMesh( mesh );
5466 //================================================================================
5468 * \brief Retrieve elements of given type from SMESH_IDSource
5470 //================================================================================
5472 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5473 const SMESHDS_Mesh* theMeshDS,
5474 TIDSortedElemSet& theElemSet,
5475 const SMDSAbs_ElementType theType,
5476 const bool emptyIfIsMesh,
5477 IDSource_Error* error)
5480 if ( error ) *error = IDSource_OK;
5482 if ( CORBA::is_nil( theIDSource ))
5484 if ( error ) *error = IDSource_INVALID;
5487 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5489 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5490 *error = IDSource_EMPTY;
5493 prepareIdSource( theIDSource );
5494 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5495 if ( anIDs->length() == 0 )
5497 if ( error ) *error = IDSource_EMPTY;
5500 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5501 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5503 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5505 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5509 if ( error ) *error = IDSource_INVALID;
5515 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5516 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5518 if ( error ) *error = IDSource_INVALID;
5525 //================================================================================
5527 * \brief Duplicates given elements, i.e. creates new elements based on the
5528 * same nodes as the given ones.
5529 * \param theElements - container of elements to duplicate.
5530 * \param theGroupName - a name of group to contain the generated elements.
5531 * If a group with such a name already exists, the new elements
5532 * are added to the existng group, else a new group is created.
5533 * If \a theGroupName is empty, new elements are not added
5535 * \return a group where the new elements are added. NULL if theGroupName == "".
5538 //================================================================================
5540 SMESH::SMESH_Group_ptr
5541 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5542 const char* theGroupName)
5543 throw (SALOME::SALOME_Exception)
5545 SMESH::SMESH_Group_var newGroup;
5552 TIDSortedElemSet elems;
5553 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5555 getEditor().DoubleElements( elems );
5557 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5560 SMESH::ElementType type =
5561 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5562 // find existing group
5563 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5564 for ( size_t i = 0; i < groups->length(); ++i )
5565 if ( groups[i]->GetType() == type )
5567 CORBA::String_var name = groups[i]->GetName();
5568 if ( strcmp( name, theGroupName ) == 0 ) {
5569 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5573 // create a new group
5574 if ( newGroup->_is_nil() )
5575 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5577 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5579 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5580 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5581 for ( int i = 1; i <= aSeq.Length(); i++ )
5582 groupDS->SMDSGroup().Add( aSeq(i) );
5587 if ( !newGroup->_is_nil() )
5588 pyDump << newGroup << " = ";
5589 pyDump << this << ".DoubleElements( "
5590 << theElements << ", " << "'" << theGroupName <<"')";
5592 SMESH_CATCH( SMESH::throwCorbaException );
5594 return newGroup._retn();
5597 //================================================================================
5599 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5600 \param theNodes - identifiers of nodes to be doubled
5601 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5602 nodes. If list of element identifiers is empty then nodes are doubled but
5603 they not assigned to elements
5604 \return TRUE if operation has been completed successfully, FALSE otherwise
5605 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5607 //================================================================================
5609 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5610 const SMESH::long_array& theModifiedElems )
5611 throw (SALOME::SALOME_Exception)
5616 list< int > aListOfNodes;
5618 for ( i = 0, n = theNodes.length(); i < n; i++ )
5619 aListOfNodes.push_back( theNodes[ i ] );
5621 list< int > aListOfElems;
5622 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5623 aListOfElems.push_back( theModifiedElems[ i ] );
5625 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5627 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5629 // Update Python script
5630 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5634 SMESH_CATCH( SMESH::throwCorbaException );
5638 //================================================================================
5640 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5641 This method provided for convenience works as DoubleNodes() described above.
5642 \param theNodeId - identifier of node to be doubled.
5643 \param theModifiedElems - identifiers of elements to be updated.
5644 \return TRUE if operation has been completed successfully, FALSE otherwise
5645 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5647 //================================================================================
5649 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5650 const SMESH::long_array& theModifiedElems )
5651 throw (SALOME::SALOME_Exception)
5654 SMESH::long_array_var aNodes = new SMESH::long_array;
5655 aNodes->length( 1 );
5656 aNodes[ 0 ] = theNodeId;
5658 TPythonDump pyDump; // suppress dump by the next line
5660 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5662 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5666 SMESH_CATCH( SMESH::throwCorbaException );
5670 //================================================================================
5672 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5673 This method provided for convenience works as DoubleNodes() described above.
5674 \param theNodes - group of nodes to be doubled.
5675 \param theModifiedElems - group of elements to be updated.
5676 \return TRUE if operation has been completed successfully, FALSE otherwise
5677 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5679 //================================================================================
5681 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5682 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5683 throw (SALOME::SALOME_Exception)
5686 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5689 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5690 SMESH::long_array_var aModifiedElems;
5691 if ( !CORBA::is_nil( theModifiedElems ) )
5692 aModifiedElems = theModifiedElems->GetListOfID();
5695 aModifiedElems = new SMESH::long_array;
5696 aModifiedElems->length( 0 );
5699 TPythonDump pyDump; // suppress dump by the next line
5701 bool done = DoubleNodes( aNodes, aModifiedElems );
5703 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5707 SMESH_CATCH( SMESH::throwCorbaException );
5711 //================================================================================
5713 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5714 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5715 * \param theNodes - group of nodes to be doubled.
5716 * \param theModifiedElems - group of elements to be updated.
5717 * \return a new group with newly created nodes
5718 * \sa DoubleNodeGroup()
5720 //================================================================================
5722 SMESH::SMESH_Group_ptr
5723 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5724 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5725 throw (SALOME::SALOME_Exception)
5728 SMESH::SMESH_Group_var aNewGroup;
5730 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5731 return aNewGroup._retn();
5734 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5735 SMESH::long_array_var aModifiedElems;
5736 if ( !CORBA::is_nil( theModifiedElems ) )
5737 aModifiedElems = theModifiedElems->GetListOfID();
5739 aModifiedElems = new SMESH::long_array;
5740 aModifiedElems->length( 0 );
5743 TPythonDump pyDump; // suppress dump by the next line
5745 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5748 // Create group with newly created nodes
5749 SMESH::long_array_var anIds = GetLastCreatedNodes();
5750 if (anIds->length() > 0) {
5751 std::string anUnindexedName (theNodes->GetName());
5752 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5753 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5754 aNewGroup->Add(anIds);
5755 pyDump << aNewGroup << " = ";
5759 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5760 << theModifiedElems << " )";
5762 return aNewGroup._retn();
5764 SMESH_CATCH( SMESH::throwCorbaException );
5768 //================================================================================
5770 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5771 This method provided for convenience works as DoubleNodes() described above.
5772 \param theNodes - list of groups of nodes to be doubled
5773 \param theModifiedElems - list of groups of elements to be updated.
5774 \return TRUE if operation has been completed successfully, FALSE otherwise
5775 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5777 //================================================================================
5779 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5780 const SMESH::ListOfGroups& theModifiedElems )
5781 throw (SALOME::SALOME_Exception)
5786 std::list< int > aNodes;
5788 for ( i = 0, n = theNodes.length(); i < n; i++ )
5790 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5791 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5793 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5794 for ( j = 0, m = aCurr->length(); j < m; j++ )
5795 aNodes.push_back( aCurr[ j ] );
5799 std::list< int > anElems;
5800 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5802 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5803 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5805 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5806 for ( j = 0, m = aCurr->length(); j < m; j++ )
5807 anElems.push_back( aCurr[ j ] );
5811 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5813 declareMeshModified( /*isReComputeSafe=*/false );
5815 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5819 SMESH_CATCH( SMESH::throwCorbaException );
5823 //================================================================================
5825 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5826 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5827 * \param theNodes - group of nodes to be doubled.
5828 * \param theModifiedElems - group of elements to be updated.
5829 * \return a new group with newly created nodes
5830 * \sa DoubleNodeGroups()
5832 //================================================================================
5834 SMESH::SMESH_Group_ptr
5835 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5836 const SMESH::ListOfGroups& theModifiedElems )
5837 throw (SALOME::SALOME_Exception)
5839 SMESH::SMESH_Group_var aNewGroup;
5841 TPythonDump pyDump; // suppress dump by the next line
5843 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5847 // Create group with newly created nodes
5848 SMESH::long_array_var anIds = GetLastCreatedNodes();
5849 if (anIds->length() > 0) {
5850 std::string anUnindexedName (theNodes[0]->GetName());
5851 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5852 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5853 aNewGroup->Add(anIds);
5854 pyDump << aNewGroup << " = ";
5858 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5859 << theModifiedElems << " )";
5861 return aNewGroup._retn();
5865 //================================================================================
5867 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5868 \param theElems - the list of elements (edges or faces) to be replicated
5869 The nodes for duplication could be found from these elements
5870 \param theNodesNot - list of nodes to NOT replicate
5871 \param theAffectedElems - the list of elements (cells and edges) to which the
5872 replicated nodes should be associated to.
5873 \return TRUE if operation has been completed successfully, FALSE otherwise
5874 \sa DoubleNodeGroup(), DoubleNodeGroups()
5876 //================================================================================
5878 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5879 const SMESH::long_array& theNodesNot,
5880 const SMESH::long_array& theAffectedElems )
5881 throw (SALOME::SALOME_Exception)
5886 SMESHDS_Mesh* aMeshDS = getMeshDS();
5887 TIDSortedElemSet anElems, aNodes, anAffected;
5888 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5889 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5890 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5892 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5894 // Update Python script
5895 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5896 << theNodesNot << ", " << theAffectedElems << " )";
5898 declareMeshModified( /*isReComputeSafe=*/false );
5901 SMESH_CATCH( SMESH::throwCorbaException );
5905 //================================================================================
5907 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5908 \param theElems - the list of elements (edges or faces) to be replicated
5909 The nodes for duplication could be found from these elements
5910 \param theNodesNot - list of nodes to NOT replicate
5911 \param theShape - shape to detect affected elements (element which geometric center
5912 located on or inside shape).
5913 The replicated nodes should be associated to affected elements.
5914 \return TRUE if operation has been completed successfully, FALSE otherwise
5915 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5917 //================================================================================
5919 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5920 const SMESH::long_array& theNodesNot,
5921 GEOM::GEOM_Object_ptr theShape )
5922 throw (SALOME::SALOME_Exception)
5928 SMESHDS_Mesh* aMeshDS = getMeshDS();
5929 TIDSortedElemSet anElems, aNodes;
5930 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5931 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5933 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5934 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5936 // Update Python script
5937 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5938 << theNodesNot << ", " << theShape << " )";
5940 declareMeshModified( /*isReComputeSafe=*/false );
5943 SMESH_CATCH( SMESH::throwCorbaException );
5947 //================================================================================
5949 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5950 \param theElems - group of of elements (edges or faces) to be replicated
5951 \param theNodesNot - group of nodes not to replicated
5952 \param theAffectedElems - group of elements to which the replicated nodes
5953 should be associated to.
5954 \return TRUE if operation has been completed successfully, FALSE otherwise
5955 \sa DoubleNodes(), DoubleNodeGroups()
5957 //================================================================================
5960 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5961 SMESH::SMESH_GroupBase_ptr theNodesNot,
5962 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5963 throw (SALOME::SALOME_Exception)
5966 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5972 SMESHDS_Mesh* aMeshDS = getMeshDS();
5973 TIDSortedElemSet anElems, aNodes, anAffected;
5974 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5975 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5976 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5978 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5980 // Update Python script
5981 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5982 << theNodesNot << ", " << theAffectedElems << " )";
5984 declareMeshModified( /*isReComputeSafe=*/false );
5987 SMESH_CATCH( SMESH::throwCorbaException );
5991 //================================================================================
5993 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5994 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5995 * \param theElems - group of of elements (edges or faces) to be replicated
5996 * \param theNodesNot - group of nodes not to replicated
5997 * \param theAffectedElems - group of elements to which the replicated nodes
5998 * should be associated to.
5999 * \return a new group with newly created elements
6000 * \sa DoubleNodeElemGroup()
6002 //================================================================================
6004 SMESH::SMESH_Group_ptr
6005 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6006 SMESH::SMESH_GroupBase_ptr theNodesNot,
6007 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6008 throw (SALOME::SALOME_Exception)
6011 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6015 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6016 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6018 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6020 << theNodesNot << ", "
6021 << theAffectedElems << " )";
6023 return elemGroup._retn();
6026 //================================================================================
6028 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6029 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6030 * \param theElems - group of of elements (edges or faces) to be replicated
6031 * \param theNodesNot - group of nodes not to replicated
6032 * \param theAffectedElems - group of elements to which the replicated nodes
6033 * should be associated to.
6034 * \return a new group with newly created elements
6035 * \sa DoubleNodeElemGroup()
6037 //================================================================================
6039 SMESH::ListOfGroups*
6040 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6041 SMESH::SMESH_GroupBase_ptr theNodesNot,
6042 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6043 CORBA::Boolean theElemGroupNeeded,
6044 CORBA::Boolean theNodeGroupNeeded)
6045 throw (SALOME::SALOME_Exception)
6048 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6049 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6050 aTwoGroups->length( 2 );
6052 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6053 return aTwoGroups._retn();
6058 SMESHDS_Mesh* aMeshDS = getMeshDS();
6059 TIDSortedElemSet anElems, aNodes, anAffected;
6060 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6061 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6062 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6065 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6067 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6073 // Create group with newly created elements
6074 CORBA::String_var elemGroupName = theElems->GetName();
6075 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6076 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6078 SMESH::long_array_var anIds = GetLastCreatedElems();
6079 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6080 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6081 aNewElemGroup->Add(anIds);
6083 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6085 SMESH::long_array_var anIds = GetLastCreatedNodes();
6086 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6087 aNewNodeGroup->Add(anIds);
6091 // Update Python script
6094 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6095 else pyDump << aNewElemGroup << ", ";
6096 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6097 else pyDump << aNewNodeGroup << " ] = ";
6099 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6100 << theNodesNot << ", "
6101 << theAffectedElems << ", "
6102 << theElemGroupNeeded << ", "
6103 << theNodeGroupNeeded <<" )";
6105 aTwoGroups[0] = aNewElemGroup._retn();
6106 aTwoGroups[1] = aNewNodeGroup._retn();
6107 return aTwoGroups._retn();
6109 SMESH_CATCH( SMESH::throwCorbaException );
6113 //================================================================================
6115 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6116 \param theElems - group of of elements (edges or faces) to be replicated
6117 \param theNodesNot - group of nodes not to replicated
6118 \param theShape - shape to detect affected elements (element which geometric center
6119 located on or inside shape).
6120 The replicated nodes should be associated to affected elements.
6121 \return TRUE if operation has been completed successfully, FALSE otherwise
6122 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6124 //================================================================================
6127 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6128 SMESH::SMESH_GroupBase_ptr theNodesNot,
6129 GEOM::GEOM_Object_ptr theShape )
6130 throw (SALOME::SALOME_Exception)
6133 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6139 SMESHDS_Mesh* aMeshDS = getMeshDS();
6140 TIDSortedElemSet anElems, aNodes, anAffected;
6141 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6142 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6144 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6145 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6148 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6150 // Update Python script
6151 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6152 << theNodesNot << ", " << theShape << " )";
6155 SMESH_CATCH( SMESH::throwCorbaException );
6159 //================================================================================
6161 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6162 * \param [in] theGrpList - groups
6163 * \param [in] theMeshDS - mesh
6164 * \param [out] theElemSet - set of elements
6165 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6167 //================================================================================
6169 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6170 SMESHDS_Mesh* theMeshDS,
6171 TIDSortedElemSet& theElemSet,
6172 const bool theIsNodeGrp)
6174 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6176 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6177 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6178 : aGrp->GetType() != SMESH::NODE ) )
6180 SMESH::long_array_var anIDs = aGrp->GetIDs();
6181 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6186 //================================================================================
6188 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6189 This method provided for convenience works as DoubleNodes() described above.
6190 \param theElems - list of groups of elements (edges or faces) to be replicated
6191 \param theNodesNot - list of groups of nodes not to replicated
6192 \param theAffectedElems - group of elements to which the replicated nodes
6193 should be associated to.
6194 \return TRUE if operation has been completed successfully, FALSE otherwise
6195 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6197 //================================================================================
6200 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6201 const SMESH::ListOfGroups& theNodesNot,
6202 const SMESH::ListOfGroups& theAffectedElems)
6203 throw (SALOME::SALOME_Exception)
6209 SMESHDS_Mesh* aMeshDS = getMeshDS();
6210 TIDSortedElemSet anElems, aNodes, anAffected;
6211 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6212 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6213 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6215 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6217 // Update Python script
6218 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6219 << &theNodesNot << ", " << &theAffectedElems << " )";
6221 declareMeshModified( /*isReComputeSafe=*/false );
6224 SMESH_CATCH( SMESH::throwCorbaException );
6228 //================================================================================
6230 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6231 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6232 \param theElems - list of groups of elements (edges or faces) to be replicated
6233 \param theNodesNot - list of groups of nodes not to replicated
6234 \param theAffectedElems - group of elements to which the replicated nodes
6235 should be associated to.
6236 * \return a new group with newly created elements
6237 * \sa DoubleNodeElemGroups()
6239 //================================================================================
6241 SMESH::SMESH_Group_ptr
6242 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6243 const SMESH::ListOfGroups& theNodesNot,
6244 const SMESH::ListOfGroups& theAffectedElems)
6245 throw (SALOME::SALOME_Exception)
6248 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6252 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6253 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6255 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6257 << theNodesNot << ", "
6258 << theAffectedElems << " )";
6260 return elemGroup._retn();
6263 //================================================================================
6265 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6266 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6267 \param theElems - list of groups of elements (edges or faces) to be replicated
6268 \param theNodesNot - list of groups of nodes not to replicated
6269 \param theAffectedElems - group of elements to which the replicated nodes
6270 should be associated to.
6271 * \return a new group with newly created elements
6272 * \sa DoubleNodeElemGroups()
6274 //================================================================================
6276 SMESH::ListOfGroups*
6277 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6278 const SMESH::ListOfGroups& theNodesNot,
6279 const SMESH::ListOfGroups& theAffectedElems,
6280 CORBA::Boolean theElemGroupNeeded,
6281 CORBA::Boolean theNodeGroupNeeded)
6282 throw (SALOME::SALOME_Exception)
6285 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6286 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6287 aTwoGroups->length( 2 );
6292 SMESHDS_Mesh* aMeshDS = getMeshDS();
6293 TIDSortedElemSet anElems, aNodes, anAffected;
6294 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6295 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6296 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6298 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6300 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6305 // Create group with newly created elements
6306 CORBA::String_var elemGroupName = theElems[0]->GetName();
6307 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6308 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6310 SMESH::long_array_var anIds = GetLastCreatedElems();
6311 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6312 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6313 aNewElemGroup->Add(anIds);
6315 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6317 SMESH::long_array_var anIds = GetLastCreatedNodes();
6318 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6319 aNewNodeGroup->Add(anIds);
6323 // Update Python script
6326 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6327 else pyDump << aNewElemGroup << ", ";
6328 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6329 else pyDump << aNewNodeGroup << " ] = ";
6331 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6332 << &theNodesNot << ", "
6333 << &theAffectedElems << ", "
6334 << theElemGroupNeeded << ", "
6335 << theNodeGroupNeeded << " )";
6337 aTwoGroups[0] = aNewElemGroup._retn();
6338 aTwoGroups[1] = aNewNodeGroup._retn();
6339 return aTwoGroups._retn();
6341 SMESH_CATCH( SMESH::throwCorbaException );
6345 //================================================================================
6347 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6348 This method provided for convenience works as DoubleNodes() described above.
6349 \param theElems - list of groups of elements (edges or faces) to be replicated
6350 \param theNodesNot - list of groups of nodes not to replicated
6351 \param theShape - shape to detect affected elements (element which geometric center
6352 located on or inside shape).
6353 The replicated nodes should be associated to affected elements.
6354 \return TRUE if operation has been completed successfully, FALSE otherwise
6355 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6357 //================================================================================
6360 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6361 const SMESH::ListOfGroups& theNodesNot,
6362 GEOM::GEOM_Object_ptr theShape )
6363 throw (SALOME::SALOME_Exception)
6369 SMESHDS_Mesh* aMeshDS = getMeshDS();
6370 TIDSortedElemSet anElems, aNodes;
6371 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6372 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6374 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6375 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6377 // Update Python script
6378 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6379 << &theNodesNot << ", " << theShape << " )";
6381 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6384 SMESH_CATCH( SMESH::throwCorbaException );
6388 //================================================================================
6390 \brief Identify the elements that will be affected by node duplication (actual
6391 duplication is not performed.
6392 This method is the first step of DoubleNodeElemGroupsInRegion.
6393 \param theElems - list of groups of elements (edges or faces) to be replicated
6394 \param theNodesNot - list of groups of nodes not to replicated
6395 \param theShape - shape to detect affected elements (element which geometric center
6396 located on or inside shape).
6397 The replicated nodes should be associated to affected elements.
6398 \return groups of affected elements
6399 \sa DoubleNodeElemGroupsInRegion()
6401 //================================================================================
6402 SMESH::ListOfGroups*
6403 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6404 const SMESH::ListOfGroups& theNodesNot,
6405 GEOM::GEOM_Object_ptr theShape )
6406 throw (SALOME::SALOME_Exception)
6409 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6410 bool isEdgeGroup = false;
6411 bool isFaceGroup = false;
6412 bool isVolumeGroup = false;
6413 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6414 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6415 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6419 ::SMESH_MeshEditor aMeshEditor(myMesh);
6421 SMESHDS_Mesh* aMeshDS = getMeshDS();
6422 TIDSortedElemSet anElems, aNodes;
6423 listOfGroupToSet(theElems, aMeshDS, anElems, false);
6424 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6426 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6427 TIDSortedElemSet anAffected;
6428 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6431 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6436 int lg = anAffected.size();
6437 SMESH::long_array_var volumeIds = new SMESH::long_array;
6438 volumeIds->length(lg);
6439 SMESH::long_array_var faceIds = new SMESH::long_array;
6440 faceIds->length(lg);
6441 SMESH::long_array_var edgeIds = new SMESH::long_array;
6442 edgeIds->length(lg);
6447 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6448 for (; eIt != anAffected.end(); ++eIt)
6450 const SMDS_MeshElement* anElem = *eIt;
6453 int elemId = anElem->GetID();
6454 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6455 volumeIds[ivol++] = elemId;
6456 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6457 faceIds[iface++] = elemId;
6458 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6459 edgeIds[iedge++] = elemId;
6461 volumeIds->length(ivol);
6462 faceIds->length(iface);
6463 edgeIds->length(iedge);
6465 aNewVolumeGroup->Add(volumeIds);
6466 aNewFaceGroup->Add(faceIds);
6467 aNewEdgeGroup->Add(edgeIds);
6468 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6469 isFaceGroup = (aNewFaceGroup->Size() > 0);
6470 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6474 if (isEdgeGroup) nbGroups++;
6475 if (isFaceGroup) nbGroups++;
6476 if (isVolumeGroup) nbGroups++;
6477 aListOfGroups->length(nbGroups);
6480 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6481 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6482 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6484 // Update Python script
6487 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6488 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6489 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6491 pyDump << this << ".AffectedElemGroupsInRegion( "
6492 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6494 return aListOfGroups._retn();
6496 SMESH_CATCH( SMESH::throwCorbaException );
6500 //================================================================================
6502 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6503 The created 2D mesh elements based on nodes of free faces of boundary volumes
6504 \return TRUE if operation has been completed successfully, FALSE otherwise
6506 //================================================================================
6508 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6509 throw (SALOME::SALOME_Exception)
6514 bool aResult = getEditor().Make2DMeshFrom3D();
6516 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6518 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6521 SMESH_CATCH( SMESH::throwCorbaException );
6525 //================================================================================
6527 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6528 * The list of groups must contain at least two groups. The groups have to be disjoint:
6529 * no common element into two different groups.
6530 * The nodes of the internal faces at the boundaries of the groups are doubled.
6531 * Optionally, the internal faces are replaced by flat elements.
6532 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6533 * The flat elements are stored in groups of volumes.
6534 * These groups are named according to the position of the group in the list:
6535 * 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.
6536 * 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.
6537 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6538 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6539 * \param theDomains - list of groups of volumes
6540 * \param createJointElems - if TRUE, create the elements
6541 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6542 * the boundary between \a theDomains and the rest mesh
6543 * \return TRUE if operation has been completed successfully, FALSE otherwise
6545 //================================================================================
6548 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6549 CORBA::Boolean createJointElems,
6550 CORBA::Boolean onAllBoundaries )
6551 throw (SALOME::SALOME_Exception)
6558 SMESHDS_Mesh* aMeshDS = getMeshDS();
6560 // MESSAGE("theDomains.length = "<<theDomains.length());
6561 if ( theDomains.length() <= 1 && !onAllBoundaries )
6562 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6564 vector<TIDSortedElemSet> domains;
6565 domains.resize( theDomains.length() );
6567 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6569 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6570 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6572 // if ( aGrp->GetType() != SMESH::VOLUME )
6573 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6574 SMESH::long_array_var anIDs = aGrp->GetIDs();
6575 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6579 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6580 // TODO publish the groups of flat elements in study
6582 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6584 // Update Python script
6585 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6586 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6588 SMESH_CATCH( SMESH::throwCorbaException );
6590 myMesh_i->CreateGroupServants(); // publish created groups if any
6595 //================================================================================
6597 * \brief Double nodes on some external faces and create flat elements.
6598 * Flat elements are mainly used by some types of mechanic calculations.
6600 * Each group of the list must be constituted of faces.
6601 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6602 * @param theGroupsOfFaces - list of groups of faces
6603 * @return TRUE if operation has been completed successfully, FALSE otherwise
6605 //================================================================================
6608 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6609 throw (SALOME::SALOME_Exception)
6614 SMESHDS_Mesh* aMeshDS = getMeshDS();
6616 vector<TIDSortedElemSet> faceGroups;
6619 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6621 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6622 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6624 TIDSortedElemSet faceGroup;
6626 faceGroups.push_back(faceGroup);
6627 SMESH::long_array_var anIDs = aGrp->GetIDs();
6628 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6632 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6633 // TODO publish the groups of flat elements in study
6635 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6637 // Update Python script
6638 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6641 SMESH_CATCH( SMESH::throwCorbaException );
6645 //================================================================================
6647 * \brief Identify all the elements around a geom shape, get the faces delimiting
6650 * Build groups of volume to remove, groups of faces to replace on the skin of the
6651 * object, groups of faces to remove inside the object, (idem edges).
6652 * Build ordered list of nodes at the border of each group of faces to replace
6653 * (to be used to build a geom subshape).
6655 //================================================================================
6657 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6658 GEOM::GEOM_Object_ptr theShape,
6659 const char* groupName,
6660 const SMESH::double_array& theNodesCoords,
6661 SMESH::array_of_long_array_out GroupsOfNodes)
6662 throw (SALOME::SALOME_Exception)
6667 std::vector<std::vector<int> > aListOfListOfNodes;
6668 ::SMESH_MeshEditor aMeshEditor( myMesh );
6670 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6671 if ( !theNodeSearcher )
6672 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6674 vector<double> nodesCoords;
6675 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6677 nodesCoords.push_back( theNodesCoords[i] );
6680 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6681 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6682 nodesCoords, aListOfListOfNodes);
6684 GroupsOfNodes = new SMESH::array_of_long_array;
6685 GroupsOfNodes->length( aListOfListOfNodes.size() );
6686 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6687 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6689 vector<int>& aListOfNodes = *llIt;
6690 vector<int>::iterator lIt = aListOfNodes.begin();;
6691 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6692 aGroup.length( aListOfNodes.size() );
6693 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6694 aGroup[ j ] = (*lIt);
6696 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6699 << ", '" << groupName << "', "
6700 << theNodesCoords << " )";
6702 SMESH_CATCH( SMESH::throwCorbaException );
6705 // issue 20749 ===================================================================
6707 * \brief Creates missing boundary elements
6708 * \param elements - elements whose boundary is to be checked
6709 * \param dimension - defines type of boundary elements to create
6710 * \param groupName - a name of group to store created boundary elements in,
6711 * "" means not to create the group
6712 * \param meshName - a name of new mesh to store created boundary elements in,
6713 * "" means not to create the new mesh
6714 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6715 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6716 * boundary elements will be copied into the new mesh
6717 * \param group - returns the create group, if any
6718 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6720 // ================================================================================
6722 SMESH::SMESH_Mesh_ptr
6723 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6724 SMESH::Bnd_Dimension dim,
6725 const char* groupName,
6726 const char* meshName,
6727 CORBA::Boolean toCopyElements,
6728 CORBA::Boolean toCopyExistingBondary,
6729 SMESH::SMESH_Group_out group)
6730 throw (SALOME::SALOME_Exception)
6735 if ( dim > SMESH::BND_1DFROM2D )
6736 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6738 SMESHDS_Mesh* aMeshDS = getMeshDS();
6740 SMESH::SMESH_Mesh_var mesh_var;
6741 SMESH::SMESH_Group_var group_var;
6745 TIDSortedElemSet elements;
6746 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6747 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6751 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6752 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6754 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6756 // group of new boundary elements
6757 SMESH_Group* smesh_group = 0;
6758 if ( strlen(groupName) )
6760 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6761 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6762 smesh_group = group_i->GetSmeshGroup();
6766 getEditor().MakeBoundaryMesh( elements,
6767 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6771 toCopyExistingBondary);
6774 smesh_mesh->GetMeshDS()->Modified();
6777 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6779 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6780 if ( mesh_var->_is_nil() )
6781 pyDump << myMesh_i->_this() << ", ";
6783 pyDump << mesh_var << ", ";
6784 if ( group_var->_is_nil() )
6785 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6787 pyDump << group_var << " = ";
6788 pyDump << this << ".MakeBoundaryMesh( "
6790 << "SMESH." << dimName[int(dim)] << ", "
6791 << "'" << groupName << "', "
6792 << "'" << meshName<< "', "
6793 << toCopyElements << ", "
6794 << toCopyExistingBondary << ")";
6796 group = group_var._retn();
6797 return mesh_var._retn();
6799 SMESH_CATCH( SMESH::throwCorbaException );
6800 return SMESH::SMESH_Mesh::_nil();
6803 //================================================================================
6805 * \brief Creates missing boundary elements
6806 * \param dimension - defines type of boundary elements to create
6807 * \param groupName - a name of group to store all boundary elements in,
6808 * "" means not to create the group
6809 * \param meshName - a name of a new mesh, which is a copy of the initial
6810 * mesh + created boundary elements; "" means not to create the new mesh
6811 * \param toCopyAll - if true, the whole initial mesh will be copied into
6812 * the new mesh else only boundary elements will be copied into the new mesh
6813 * \param groups - optional groups of elements to make boundary around
6814 * \param mesh - returns the mesh where elements were added to
6815 * \param group - returns the created group, if any
6816 * \retval long - number of added boundary elements
6818 //================================================================================
6820 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6821 const char* groupName,
6822 const char* meshName,
6823 CORBA::Boolean toCopyAll,
6824 const SMESH::ListOfIDSources& groups,
6825 SMESH::SMESH_Mesh_out mesh,
6826 SMESH::SMESH_Group_out group)
6827 throw (SALOME::SALOME_Exception)
6832 if ( dim > SMESH::BND_1DFROM2D )
6833 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6835 // separate groups belonging to this and other mesh
6836 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6837 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6838 groupsOfThisMesh ->length( groups.length() );
6839 groupsOfOtherMesh->length( groups.length() );
6840 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6841 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
6843 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6844 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6845 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6847 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6848 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6849 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
6851 groupsOfThisMesh->length( nbGroups );
6852 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6857 if ( nbGroupsOfOtherMesh > 0 )
6859 // process groups belonging to another mesh
6860 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6861 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6862 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6863 groupsOfOtherMesh, mesh, group );
6866 SMESH::SMESH_Mesh_var mesh_var;
6867 SMESH::SMESH_Group_var group_var;
6870 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6871 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6875 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6877 /*toCopyGroups=*/false,
6878 /*toKeepIDs=*/true);
6880 mesh_var = makeMesh(meshName);
6882 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6883 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6886 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6887 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6889 // group of boundary elements
6890 SMESH_Group* smesh_group = 0;
6891 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6892 if ( strlen(groupName) )
6894 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6895 group_var = mesh_i->CreateGroup( groupType, groupName );
6896 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6897 smesh_group = group_i->GetSmeshGroup();
6900 TIDSortedElemSet elements;
6902 if ( groups.length() > 0 )
6904 for ( int i = 0; i < nbGroups; ++i )
6907 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6909 SMESH::Bnd_Dimension bdim =
6910 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6911 nbAdded += getEditor().MakeBoundaryMesh( elements,
6912 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6915 /*toCopyElements=*/false,
6916 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6917 /*toAddExistingBondary=*/true,
6918 /*aroundElements=*/true);
6924 nbAdded += getEditor().MakeBoundaryMesh( elements,
6925 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6928 /*toCopyElements=*/false,
6929 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6930 /*toAddExistingBondary=*/true);
6932 tgtMesh->GetMeshDS()->Modified();
6934 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6936 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6937 pyDump << "nbAdded, ";
6938 if ( mesh_var->_is_nil() )
6939 pyDump << myMesh_i->_this() << ", ";
6941 pyDump << mesh_var << ", ";
6942 if ( group_var->_is_nil() )
6943 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6945 pyDump << group_var << " = ";
6946 pyDump << this << ".MakeBoundaryElements( "
6947 << "SMESH." << dimName[int(dim)] << ", "
6948 << "'" << groupName << "', "
6949 << "'" << meshName<< "', "
6950 << toCopyAll << ", "
6953 mesh = mesh_var._retn();
6954 group = group_var._retn();
6957 SMESH_CATCH( SMESH::throwCorbaException );
6961 //================================================================================
6963 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
6964 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
6965 * plane passing through pairs of points specified by each PolySegment structure.
6966 * If there are several paths connecting a pair of points, the shortest path is
6967 * selected by the module. Position of the cutting plane is defined by the two
6968 * points and an optional vector lying on the plane specified by a PolySegment.
6969 * By default the vector is defined by Mesh module as following. A middle point
6970 * of the two given points is computed. The middle point is projected to the mesh.
6971 * The vector goes from the middle point to the projection point. In case of planar
6972 * mesh, the vector is normal to the mesh.
6973 * \param [inout] segments - PolySegment's defining positions of cutting planes.
6974 * Return the used vector and position of the middle point.
6975 * \param [in] groupName - optional name of a group where created mesh segments will
6978 //================================================================================
6980 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
6981 const char* theGroupName)
6982 throw (SALOME::SALOME_Exception)
6984 if ( theSegments.length() == 0 )
6985 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
6986 if ( myMesh->NbFaces() == 0 )
6987 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
6990 initData(/*deleteSearchers=*/false);
6992 SMESHDS_Group* groupDS = 0;
6993 SMESHDS_Mesh* meshDS = getMeshDS();
6994 if ( myIsPreviewMode ) // copy faces to the tmp mesh
6996 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
6997 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
6998 while ( faceIt->more() )
6999 tmpMesh->Copy( faceIt->next() );
7000 meshDS = tmpMesh->GetMeshDS();
7002 else if ( theGroupName[0] ) // find/create a group of segments
7004 SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7005 while ( !groupDS && grpIt->more() )
7007 SMESH_Group* group = grpIt->next();
7008 if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7009 strcmp( group->GetName(), theGroupName ) == 0 )
7011 groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7016 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7018 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7019 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7023 // convert input polySegments
7024 ::SMESH_MeshEditor::TListOfPolySegments segments( theSegments.length() );
7025 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7027 SMESH::PolySegment& segIn = theSegments[ i ];
7028 ::SMESH_MeshEditor::PolySegment& segOut = segments[ i ];
7029 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7030 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7031 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7032 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7033 segOut.myVector.SetCoord( segIn.vector.PS.x,
7035 segIn.vector.PS.z );
7036 if ( !segOut.myNode1[0] )
7037 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node1ID1,
7038 SALOME::BAD_PARAM );
7039 if ( !segOut.myNode1[1] )
7040 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node2ID1,
7041 SALOME::BAD_PARAM );
7044 // get a static ElementSearcher
7045 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7046 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7047 if ( !theElementSearcher )
7048 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7051 getEditor().MakePolyLine( segments, groupDS, theElementSearcher );
7054 if ( myIsPreviewMode )
7056 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7058 SMESH::PolySegment& segOut = theSegments[ i ];
7059 ::SMESH_MeshEditor::PolySegment& segIn = segments[ i ];
7060 segOut.vector.PS.x = segIn.myVector.X();
7061 segOut.vector.PS.y = segIn.myVector.Y();
7062 segOut.vector.PS.z = segIn.myVector.Z();
7067 TPythonDump() << "_segments = []";
7068 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7070 SMESH::PolySegment& segIn = theSegments[ i ];
7071 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7072 << segIn.node1ID1 << ", "
7073 << segIn.node1ID2 << ", "
7074 << segIn.node2ID1 << ", "
7075 << segIn.node2ID2 << ", "
7076 << "smeshBuilder.MakeDirStruct( "
7077 << segIn.vector.PS.x << ", "
7078 << segIn.vector.PS.y << ", "
7079 << segIn.vector.PS.z << ")))";
7081 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7084 SMESH_CATCH( SMESH::throwCorbaException );