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();
5694 aModifiedElems = new SMESH::long_array;
5696 TPythonDump pyDump; // suppress dump by the next line
5698 bool done = DoubleNodes( aNodes, aModifiedElems );
5700 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5704 SMESH_CATCH( SMESH::throwCorbaException );
5708 //================================================================================
5710 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5711 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5712 * \param theNodes - group of nodes to be doubled.
5713 * \param theModifiedElems - group of elements to be updated.
5714 * \return a new group with newly created nodes
5715 * \sa DoubleNodeGroup()
5717 //================================================================================
5719 SMESH::SMESH_Group_ptr
5720 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5721 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5722 throw (SALOME::SALOME_Exception)
5725 SMESH::SMESH_Group_var aNewGroup;
5727 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5728 return aNewGroup._retn();
5731 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5732 SMESH::long_array_var aModifiedElems;
5733 if ( !CORBA::is_nil( theModifiedElems ) )
5734 aModifiedElems = theModifiedElems->GetListOfID();
5736 aModifiedElems = new SMESH::long_array;
5737 aModifiedElems->length( 0 );
5740 TPythonDump pyDump; // suppress dump by the next line
5742 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5745 // Create group with newly created nodes
5746 SMESH::long_array_var anIds = GetLastCreatedNodes();
5747 if (anIds->length() > 0) {
5748 std::string anUnindexedName (theNodes->GetName());
5749 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5750 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5751 aNewGroup->Add(anIds);
5752 pyDump << aNewGroup << " = ";
5756 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5757 << theModifiedElems << " )";
5759 return aNewGroup._retn();
5761 SMESH_CATCH( SMESH::throwCorbaException );
5765 //================================================================================
5767 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5768 This method provided for convenience works as DoubleNodes() described above.
5769 \param theNodes - list of groups of nodes to be doubled
5770 \param theModifiedElems - list of groups of elements to be updated.
5771 \return TRUE if operation has been completed successfully, FALSE otherwise
5772 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5774 //================================================================================
5776 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5777 const SMESH::ListOfGroups& theModifiedElems )
5778 throw (SALOME::SALOME_Exception)
5783 std::list< int > aNodes;
5785 for ( i = 0, n = theNodes.length(); i < n; i++ )
5787 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5788 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5790 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5791 for ( j = 0, m = aCurr->length(); j < m; j++ )
5792 aNodes.push_back( aCurr[ j ] );
5796 std::list< int > anElems;
5797 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5799 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5800 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5802 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5803 for ( j = 0, m = aCurr->length(); j < m; j++ )
5804 anElems.push_back( aCurr[ j ] );
5808 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5810 declareMeshModified( /*isReComputeSafe=*/false );
5812 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5816 SMESH_CATCH( SMESH::throwCorbaException );
5820 //================================================================================
5822 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5823 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5824 * \param theNodes - group of nodes to be doubled.
5825 * \param theModifiedElems - group of elements to be updated.
5826 * \return a new group with newly created nodes
5827 * \sa DoubleNodeGroups()
5829 //================================================================================
5831 SMESH::SMESH_Group_ptr
5832 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5833 const SMESH::ListOfGroups& theModifiedElems )
5834 throw (SALOME::SALOME_Exception)
5836 SMESH::SMESH_Group_var aNewGroup;
5838 TPythonDump pyDump; // suppress dump by the next line
5840 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5844 // Create group with newly created nodes
5845 SMESH::long_array_var anIds = GetLastCreatedNodes();
5846 if (anIds->length() > 0) {
5847 std::string anUnindexedName (theNodes[0]->GetName());
5848 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5849 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5850 aNewGroup->Add(anIds);
5851 pyDump << aNewGroup << " = ";
5855 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5856 << theModifiedElems << " )";
5858 return aNewGroup._retn();
5862 //================================================================================
5864 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5865 \param theElems - the list of elements (edges or faces) to be replicated
5866 The nodes for duplication could be found from these elements
5867 \param theNodesNot - list of nodes to NOT replicate
5868 \param theAffectedElems - the list of elements (cells and edges) to which the
5869 replicated nodes should be associated to.
5870 \return TRUE if operation has been completed successfully, FALSE otherwise
5871 \sa DoubleNodeGroup(), DoubleNodeGroups()
5873 //================================================================================
5875 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5876 const SMESH::long_array& theNodesNot,
5877 const SMESH::long_array& theAffectedElems )
5878 throw (SALOME::SALOME_Exception)
5883 SMESHDS_Mesh* aMeshDS = getMeshDS();
5884 TIDSortedElemSet anElems, aNodes, anAffected;
5885 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5886 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5887 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5889 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5891 // Update Python script
5892 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5893 << theNodesNot << ", " << theAffectedElems << " )";
5895 declareMeshModified( /*isReComputeSafe=*/false );
5898 SMESH_CATCH( SMESH::throwCorbaException );
5902 //================================================================================
5904 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5905 \param theElems - the list of elements (edges or faces) to be replicated
5906 The nodes for duplication could be found from these elements
5907 \param theNodesNot - list of nodes to NOT replicate
5908 \param theShape - shape to detect affected elements (element which geometric center
5909 located on or inside shape).
5910 The replicated nodes should be associated to affected elements.
5911 \return TRUE if operation has been completed successfully, FALSE otherwise
5912 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5914 //================================================================================
5916 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5917 const SMESH::long_array& theNodesNot,
5918 GEOM::GEOM_Object_ptr theShape )
5919 throw (SALOME::SALOME_Exception)
5925 SMESHDS_Mesh* aMeshDS = getMeshDS();
5926 TIDSortedElemSet anElems, aNodes;
5927 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5928 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5930 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5931 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5933 // Update Python script
5934 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5935 << theNodesNot << ", " << theShape << " )";
5937 declareMeshModified( /*isReComputeSafe=*/false );
5940 SMESH_CATCH( SMESH::throwCorbaException );
5944 //================================================================================
5946 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5947 \param theElems - group of of elements (edges or faces) to be replicated
5948 \param theNodesNot - group of nodes not to replicated
5949 \param theAffectedElems - group of elements to which the replicated nodes
5950 should be associated to.
5951 \return TRUE if operation has been completed successfully, FALSE otherwise
5952 \sa DoubleNodes(), DoubleNodeGroups()
5954 //================================================================================
5957 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5958 SMESH::SMESH_GroupBase_ptr theNodesNot,
5959 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5960 throw (SALOME::SALOME_Exception)
5963 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5969 SMESHDS_Mesh* aMeshDS = getMeshDS();
5970 TIDSortedElemSet anElems, aNodes, anAffected;
5971 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5972 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5973 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5975 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5977 // Update Python script
5978 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5979 << theNodesNot << ", " << theAffectedElems << " )";
5981 declareMeshModified( /*isReComputeSafe=*/false );
5984 SMESH_CATCH( SMESH::throwCorbaException );
5988 //================================================================================
5990 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5991 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5992 * \param theElems - group of of elements (edges or faces) to be replicated
5993 * \param theNodesNot - group of nodes not to replicated
5994 * \param theAffectedElems - group of elements to which the replicated nodes
5995 * should be associated to.
5996 * \return a new group with newly created elements
5997 * \sa DoubleNodeElemGroup()
5999 //================================================================================
6001 SMESH::SMESH_Group_ptr
6002 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6003 SMESH::SMESH_GroupBase_ptr theNodesNot,
6004 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6005 throw (SALOME::SALOME_Exception)
6008 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6012 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6013 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6015 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6017 << theNodesNot << ", "
6018 << theAffectedElems << " )";
6020 return elemGroup._retn();
6023 //================================================================================
6025 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6026 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6027 * \param theElems - group of of elements (edges or faces) to be replicated
6028 * \param theNodesNot - group of nodes not to replicated
6029 * \param theAffectedElems - group of elements to which the replicated nodes
6030 * should be associated to.
6031 * \return a new group with newly created elements
6032 * \sa DoubleNodeElemGroup()
6034 //================================================================================
6036 SMESH::ListOfGroups*
6037 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6038 SMESH::SMESH_GroupBase_ptr theNodesNot,
6039 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6040 CORBA::Boolean theElemGroupNeeded,
6041 CORBA::Boolean theNodeGroupNeeded)
6042 throw (SALOME::SALOME_Exception)
6045 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6046 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6047 aTwoGroups->length( 2 );
6049 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6050 return aTwoGroups._retn();
6055 SMESHDS_Mesh* aMeshDS = getMeshDS();
6056 TIDSortedElemSet anElems, aNodes, anAffected;
6057 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6058 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6059 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6062 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6064 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6070 // Create group with newly created elements
6071 CORBA::String_var elemGroupName = theElems->GetName();
6072 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6073 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6075 SMESH::long_array_var anIds = GetLastCreatedElems();
6076 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6077 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6078 aNewElemGroup->Add(anIds);
6080 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6082 SMESH::long_array_var anIds = GetLastCreatedNodes();
6083 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6084 aNewNodeGroup->Add(anIds);
6088 // Update Python script
6091 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6092 else pyDump << aNewElemGroup << ", ";
6093 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6094 else pyDump << aNewNodeGroup << " ] = ";
6096 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6097 << theNodesNot << ", "
6098 << theAffectedElems << ", "
6099 << theElemGroupNeeded << ", "
6100 << theNodeGroupNeeded <<" )";
6102 aTwoGroups[0] = aNewElemGroup._retn();
6103 aTwoGroups[1] = aNewNodeGroup._retn();
6104 return aTwoGroups._retn();
6106 SMESH_CATCH( SMESH::throwCorbaException );
6110 //================================================================================
6112 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6113 \param theElems - group of of elements (edges or faces) to be replicated
6114 \param theNodesNot - group of nodes not to replicated
6115 \param theShape - shape to detect affected elements (element which geometric center
6116 located on or inside shape).
6117 The replicated nodes should be associated to affected elements.
6118 \return TRUE if operation has been completed successfully, FALSE otherwise
6119 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6121 //================================================================================
6124 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6125 SMESH::SMESH_GroupBase_ptr theNodesNot,
6126 GEOM::GEOM_Object_ptr theShape )
6127 throw (SALOME::SALOME_Exception)
6130 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6136 SMESHDS_Mesh* aMeshDS = getMeshDS();
6137 TIDSortedElemSet anElems, aNodes, anAffected;
6138 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6139 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6141 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6142 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6145 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6147 // Update Python script
6148 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6149 << theNodesNot << ", " << theShape << " )";
6152 SMESH_CATCH( SMESH::throwCorbaException );
6156 //================================================================================
6158 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6159 * \param [in] theGrpList - groups
6160 * \param [in] theMeshDS - mesh
6161 * \param [out] theElemSet - set of elements
6162 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6164 //================================================================================
6166 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6167 SMESHDS_Mesh* theMeshDS,
6168 TIDSortedElemSet& theElemSet,
6169 const bool theIsNodeGrp)
6171 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6173 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6174 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6175 : aGrp->GetType() != SMESH::NODE ) )
6177 SMESH::long_array_var anIDs = aGrp->GetIDs();
6178 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6183 //================================================================================
6185 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6186 This method provided for convenience works as DoubleNodes() described above.
6187 \param theElems - list of groups of elements (edges or faces) to be replicated
6188 \param theNodesNot - list of groups of nodes not to replicated
6189 \param theAffectedElems - group of elements to which the replicated nodes
6190 should be associated to.
6191 \return TRUE if operation has been completed successfully, FALSE otherwise
6192 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6194 //================================================================================
6197 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6198 const SMESH::ListOfGroups& theNodesNot,
6199 const SMESH::ListOfGroups& theAffectedElems)
6200 throw (SALOME::SALOME_Exception)
6206 SMESHDS_Mesh* aMeshDS = getMeshDS();
6207 TIDSortedElemSet anElems, aNodes, anAffected;
6208 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6209 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6210 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6212 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6214 // Update Python script
6215 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6216 << &theNodesNot << ", " << &theAffectedElems << " )";
6218 declareMeshModified( /*isReComputeSafe=*/false );
6221 SMESH_CATCH( SMESH::throwCorbaException );
6225 //================================================================================
6227 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6228 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6229 \param theElems - list of groups of elements (edges or faces) to be replicated
6230 \param theNodesNot - list of groups of nodes not to replicated
6231 \param theAffectedElems - group of elements to which the replicated nodes
6232 should be associated to.
6233 * \return a new group with newly created elements
6234 * \sa DoubleNodeElemGroups()
6236 //================================================================================
6238 SMESH::SMESH_Group_ptr
6239 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6240 const SMESH::ListOfGroups& theNodesNot,
6241 const SMESH::ListOfGroups& theAffectedElems)
6242 throw (SALOME::SALOME_Exception)
6245 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6249 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6250 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6252 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6254 << theNodesNot << ", "
6255 << theAffectedElems << " )";
6257 return elemGroup._retn();
6260 //================================================================================
6262 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6263 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6264 \param theElems - list of groups of elements (edges or faces) to be replicated
6265 \param theNodesNot - list of groups of nodes not to replicated
6266 \param theAffectedElems - group of elements to which the replicated nodes
6267 should be associated to.
6268 * \return a new group with newly created elements
6269 * \sa DoubleNodeElemGroups()
6271 //================================================================================
6273 SMESH::ListOfGroups*
6274 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6275 const SMESH::ListOfGroups& theNodesNot,
6276 const SMESH::ListOfGroups& theAffectedElems,
6277 CORBA::Boolean theElemGroupNeeded,
6278 CORBA::Boolean theNodeGroupNeeded)
6279 throw (SALOME::SALOME_Exception)
6282 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6283 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6284 aTwoGroups->length( 2 );
6289 SMESHDS_Mesh* aMeshDS = getMeshDS();
6290 TIDSortedElemSet anElems, aNodes, anAffected;
6291 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6292 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6293 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6295 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6297 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6302 // Create group with newly created elements
6303 CORBA::String_var elemGroupName = theElems[0]->GetName();
6304 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6305 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6307 SMESH::long_array_var anIds = GetLastCreatedElems();
6308 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6309 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6310 aNewElemGroup->Add(anIds);
6312 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6314 SMESH::long_array_var anIds = GetLastCreatedNodes();
6315 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6316 aNewNodeGroup->Add(anIds);
6320 // Update Python script
6323 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6324 else pyDump << aNewElemGroup << ", ";
6325 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6326 else pyDump << aNewNodeGroup << " ] = ";
6328 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6329 << &theNodesNot << ", "
6330 << &theAffectedElems << ", "
6331 << theElemGroupNeeded << ", "
6332 << theNodeGroupNeeded << " )";
6334 aTwoGroups[0] = aNewElemGroup._retn();
6335 aTwoGroups[1] = aNewNodeGroup._retn();
6336 return aTwoGroups._retn();
6338 SMESH_CATCH( SMESH::throwCorbaException );
6342 //================================================================================
6344 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6345 This method provided for convenience works as DoubleNodes() described above.
6346 \param theElems - list of groups of elements (edges or faces) to be replicated
6347 \param theNodesNot - list of groups of nodes not to replicated
6348 \param theShape - shape to detect affected elements (element which geometric center
6349 located on or inside shape).
6350 The replicated nodes should be associated to affected elements.
6351 \return TRUE if operation has been completed successfully, FALSE otherwise
6352 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6354 //================================================================================
6357 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6358 const SMESH::ListOfGroups& theNodesNot,
6359 GEOM::GEOM_Object_ptr theShape )
6360 throw (SALOME::SALOME_Exception)
6366 SMESHDS_Mesh* aMeshDS = getMeshDS();
6367 TIDSortedElemSet anElems, aNodes;
6368 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6369 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6371 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6372 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6374 // Update Python script
6375 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6376 << &theNodesNot << ", " << theShape << " )";
6378 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6381 SMESH_CATCH( SMESH::throwCorbaException );
6385 //================================================================================
6387 \brief Identify the elements that will be affected by node duplication (actual
6388 duplication is not performed.
6389 This method is the first step of DoubleNodeElemGroupsInRegion.
6390 \param theElems - list of groups of elements (edges or faces) to be replicated
6391 \param theNodesNot - list of groups of nodes not to replicated
6392 \param theShape - shape to detect affected elements (element which geometric center
6393 located on or inside shape).
6394 The replicated nodes should be associated to affected elements.
6395 \return groups of affected elements
6396 \sa DoubleNodeElemGroupsInRegion()
6398 //================================================================================
6399 SMESH::ListOfGroups*
6400 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6401 const SMESH::ListOfGroups& theNodesNot,
6402 GEOM::GEOM_Object_ptr theShape )
6403 throw (SALOME::SALOME_Exception)
6406 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6407 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6408 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6409 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6413 ::SMESH_MeshEditor aMeshEditor(myMesh);
6415 SMESHDS_Mesh* aMeshDS = getMeshDS();
6416 TIDSortedElemSet anElems, aNodes;
6417 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6418 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6419 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6421 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6422 TIDSortedElemSet anAffected;
6423 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6425 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6428 if ( aResult && anAffected.size() > 0 )
6430 SMESH::long_array_var volumeIds = new SMESH::long_array;
6431 SMESH::long_array_var faceIds = new SMESH::long_array;
6432 SMESH::long_array_var edgeIds = new SMESH::long_array;
6433 volumeIds->length( anAffected.size() );
6434 faceIds ->length( anAffected.size() );
6435 edgeIds ->length( anAffected.size() );
6440 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6441 for (; eIt != anAffected.end(); ++eIt)
6443 const SMDS_MeshElement* anElem = *eIt;
6444 int elemId = anElem->GetID();
6445 switch ( anElem->GetType() ) {
6446 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6447 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6448 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6452 volumeIds->length(ivol);
6453 faceIds->length(iface);
6454 edgeIds->length(iedge);
6459 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6460 generateGroupName("affectedVolumes").c_str());
6461 aNewVolumeGroup->Add(volumeIds);
6462 aListOfGroups->length( nbGroups+1 );
6463 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6467 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6468 generateGroupName("affectedFaces").c_str());
6469 aNewFaceGroup->Add(faceIds);
6470 aListOfGroups->length( nbGroups+1 );
6471 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6475 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6476 generateGroupName("affectedEdges").c_str());
6477 aNewEdgeGroup->Add(edgeIds);
6478 aListOfGroups->length( nbGroups+1 );
6479 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6483 // Update Python script
6485 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6486 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6488 return aListOfGroups._retn();
6490 SMESH_CATCH( SMESH::throwCorbaException );
6494 //================================================================================
6496 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6497 The created 2D mesh elements based on nodes of free faces of boundary volumes
6498 \return TRUE if operation has been completed successfully, FALSE otherwise
6500 //================================================================================
6502 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6503 throw (SALOME::SALOME_Exception)
6508 bool aResult = getEditor().Make2DMeshFrom3D();
6510 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6512 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6515 SMESH_CATCH( SMESH::throwCorbaException );
6519 //================================================================================
6521 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6522 * The list of groups must contain at least two groups. The groups have to be disjoint:
6523 * no common element into two different groups.
6524 * The nodes of the internal faces at the boundaries of the groups are doubled.
6525 * Optionally, the internal faces are replaced by flat elements.
6526 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6527 * The flat elements are stored in groups of volumes.
6528 * These groups are named according to the position of the group in the list:
6529 * 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.
6530 * 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.
6531 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6532 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6533 * \param theDomains - list of groups of volumes
6534 * \param createJointElems - if TRUE, create the elements
6535 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6536 * the boundary between \a theDomains and the rest mesh
6537 * \return TRUE if operation has been completed successfully, FALSE otherwise
6539 //================================================================================
6542 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6543 CORBA::Boolean createJointElems,
6544 CORBA::Boolean onAllBoundaries )
6545 throw (SALOME::SALOME_Exception)
6552 SMESHDS_Mesh* aMeshDS = getMeshDS();
6554 // MESSAGE("theDomains.length = "<<theDomains.length());
6555 if ( theDomains.length() <= 1 && !onAllBoundaries )
6556 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6558 vector<TIDSortedElemSet> domains;
6559 domains.resize( theDomains.length() );
6561 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6563 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6564 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6566 // if ( aGrp->GetType() != SMESH::VOLUME )
6567 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6568 SMESH::long_array_var anIDs = aGrp->GetIDs();
6569 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6573 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6574 // TODO publish the groups of flat elements in study
6576 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6578 // Update Python script
6579 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6580 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6582 SMESH_CATCH( SMESH::throwCorbaException );
6584 myMesh_i->CreateGroupServants(); // publish created groups if any
6589 //================================================================================
6591 * \brief Double nodes on some external faces and create flat elements.
6592 * Flat elements are mainly used by some types of mechanic calculations.
6594 * Each group of the list must be constituted of faces.
6595 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6596 * @param theGroupsOfFaces - list of groups of faces
6597 * @return TRUE if operation has been completed successfully, FALSE otherwise
6599 //================================================================================
6602 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6603 throw (SALOME::SALOME_Exception)
6608 SMESHDS_Mesh* aMeshDS = getMeshDS();
6610 vector<TIDSortedElemSet> faceGroups;
6613 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6615 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6616 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6618 TIDSortedElemSet faceGroup;
6620 faceGroups.push_back(faceGroup);
6621 SMESH::long_array_var anIDs = aGrp->GetIDs();
6622 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6626 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6627 // TODO publish the groups of flat elements in study
6629 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6631 // Update Python script
6632 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6635 SMESH_CATCH( SMESH::throwCorbaException );
6639 //================================================================================
6641 * \brief Identify all the elements around a geom shape, get the faces delimiting
6644 * Build groups of volume to remove, groups of faces to replace on the skin of the
6645 * object, groups of faces to remove inside the object, (idem edges).
6646 * Build ordered list of nodes at the border of each group of faces to replace
6647 * (to be used to build a geom subshape).
6649 //================================================================================
6651 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6652 GEOM::GEOM_Object_ptr theShape,
6653 const char* groupName,
6654 const SMESH::double_array& theNodesCoords,
6655 SMESH::array_of_long_array_out GroupsOfNodes)
6656 throw (SALOME::SALOME_Exception)
6661 std::vector<std::vector<int> > aListOfListOfNodes;
6662 ::SMESH_MeshEditor aMeshEditor( myMesh );
6664 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6665 if ( !theNodeSearcher )
6666 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6668 vector<double> nodesCoords;
6669 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6671 nodesCoords.push_back( theNodesCoords[i] );
6674 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6675 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6676 nodesCoords, aListOfListOfNodes);
6678 GroupsOfNodes = new SMESH::array_of_long_array;
6679 GroupsOfNodes->length( aListOfListOfNodes.size() );
6680 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6681 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6683 vector<int>& aListOfNodes = *llIt;
6684 vector<int>::iterator lIt = aListOfNodes.begin();;
6685 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6686 aGroup.length( aListOfNodes.size() );
6687 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6688 aGroup[ j ] = (*lIt);
6690 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6693 << ", '" << groupName << "', "
6694 << theNodesCoords << " )";
6696 SMESH_CATCH( SMESH::throwCorbaException );
6699 // issue 20749 ===================================================================
6701 * \brief Creates missing boundary elements
6702 * \param elements - elements whose boundary is to be checked
6703 * \param dimension - defines type of boundary elements to create
6704 * \param groupName - a name of group to store created boundary elements in,
6705 * "" means not to create the group
6706 * \param meshName - a name of new mesh to store created boundary elements in,
6707 * "" means not to create the new mesh
6708 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6709 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6710 * boundary elements will be copied into the new mesh
6711 * \param group - returns the create group, if any
6712 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6714 // ================================================================================
6716 SMESH::SMESH_Mesh_ptr
6717 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6718 SMESH::Bnd_Dimension dim,
6719 const char* groupName,
6720 const char* meshName,
6721 CORBA::Boolean toCopyElements,
6722 CORBA::Boolean toCopyExistingBondary,
6723 SMESH::SMESH_Group_out group)
6724 throw (SALOME::SALOME_Exception)
6729 if ( dim > SMESH::BND_1DFROM2D )
6730 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6732 SMESHDS_Mesh* aMeshDS = getMeshDS();
6734 SMESH::SMESH_Mesh_var mesh_var;
6735 SMESH::SMESH_Group_var group_var;
6739 TIDSortedElemSet elements;
6740 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6741 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6745 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6746 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6748 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6750 // group of new boundary elements
6751 SMESH_Group* smesh_group = 0;
6752 if ( strlen(groupName) )
6754 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6755 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6756 smesh_group = group_i->GetSmeshGroup();
6760 getEditor().MakeBoundaryMesh( elements,
6761 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6765 toCopyExistingBondary);
6768 smesh_mesh->GetMeshDS()->Modified();
6771 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6773 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6774 if ( mesh_var->_is_nil() )
6775 pyDump << myMesh_i->_this() << ", ";
6777 pyDump << mesh_var << ", ";
6778 if ( group_var->_is_nil() )
6779 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6781 pyDump << group_var << " = ";
6782 pyDump << this << ".MakeBoundaryMesh( "
6784 << "SMESH." << dimName[int(dim)] << ", "
6785 << "'" << groupName << "', "
6786 << "'" << meshName<< "', "
6787 << toCopyElements << ", "
6788 << toCopyExistingBondary << ")";
6790 group = group_var._retn();
6791 return mesh_var._retn();
6793 SMESH_CATCH( SMESH::throwCorbaException );
6794 return SMESH::SMESH_Mesh::_nil();
6797 //================================================================================
6799 * \brief Creates missing boundary elements
6800 * \param dimension - defines type of boundary elements to create
6801 * \param groupName - a name of group to store all boundary elements in,
6802 * "" means not to create the group
6803 * \param meshName - a name of a new mesh, which is a copy of the initial
6804 * mesh + created boundary elements; "" means not to create the new mesh
6805 * \param toCopyAll - if true, the whole initial mesh will be copied into
6806 * the new mesh else only boundary elements will be copied into the new mesh
6807 * \param groups - optional groups of elements to make boundary around
6808 * \param mesh - returns the mesh where elements were added to
6809 * \param group - returns the created group, if any
6810 * \retval long - number of added boundary elements
6812 //================================================================================
6814 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6815 const char* groupName,
6816 const char* meshName,
6817 CORBA::Boolean toCopyAll,
6818 const SMESH::ListOfIDSources& groups,
6819 SMESH::SMESH_Mesh_out mesh,
6820 SMESH::SMESH_Group_out group)
6821 throw (SALOME::SALOME_Exception)
6826 if ( dim > SMESH::BND_1DFROM2D )
6827 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6829 // separate groups belonging to this and other mesh
6830 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6831 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6832 groupsOfThisMesh ->length( groups.length() );
6833 groupsOfOtherMesh->length( groups.length() );
6834 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6835 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
6837 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6838 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6839 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6841 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6842 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6843 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
6845 groupsOfThisMesh->length( nbGroups );
6846 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6851 if ( nbGroupsOfOtherMesh > 0 )
6853 // process groups belonging to another mesh
6854 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6855 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6856 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6857 groupsOfOtherMesh, mesh, group );
6860 SMESH::SMESH_Mesh_var mesh_var;
6861 SMESH::SMESH_Group_var group_var;
6864 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6865 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6869 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6871 /*toCopyGroups=*/false,
6872 /*toKeepIDs=*/true);
6874 mesh_var = makeMesh(meshName);
6876 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6877 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6880 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6881 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6883 // group of boundary elements
6884 SMESH_Group* smesh_group = 0;
6885 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6886 if ( strlen(groupName) )
6888 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6889 group_var = mesh_i->CreateGroup( groupType, groupName );
6890 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6891 smesh_group = group_i->GetSmeshGroup();
6894 TIDSortedElemSet elements;
6896 if ( groups.length() > 0 )
6898 for ( int i = 0; i < nbGroups; ++i )
6901 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6903 SMESH::Bnd_Dimension bdim =
6904 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6905 nbAdded += getEditor().MakeBoundaryMesh( elements,
6906 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6909 /*toCopyElements=*/false,
6910 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6911 /*toAddExistingBondary=*/true,
6912 /*aroundElements=*/true);
6918 nbAdded += getEditor().MakeBoundaryMesh( elements,
6919 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6922 /*toCopyElements=*/false,
6923 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6924 /*toAddExistingBondary=*/true);
6926 tgtMesh->GetMeshDS()->Modified();
6928 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6930 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6931 pyDump << "nbAdded, ";
6932 if ( mesh_var->_is_nil() )
6933 pyDump << myMesh_i->_this() << ", ";
6935 pyDump << mesh_var << ", ";
6936 if ( group_var->_is_nil() )
6937 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6939 pyDump << group_var << " = ";
6940 pyDump << this << ".MakeBoundaryElements( "
6941 << "SMESH." << dimName[int(dim)] << ", "
6942 << "'" << groupName << "', "
6943 << "'" << meshName<< "', "
6944 << toCopyAll << ", "
6947 mesh = mesh_var._retn();
6948 group = group_var._retn();
6951 SMESH_CATCH( SMESH::throwCorbaException );
6955 //================================================================================
6957 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
6958 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
6959 * plane passing through pairs of points specified by each PolySegment structure.
6960 * If there are several paths connecting a pair of points, the shortest path is
6961 * selected by the module. Position of the cutting plane is defined by the two
6962 * points and an optional vector lying on the plane specified by a PolySegment.
6963 * By default the vector is defined by Mesh module as following. A middle point
6964 * of the two given points is computed. The middle point is projected to the mesh.
6965 * The vector goes from the middle point to the projection point. In case of planar
6966 * mesh, the vector is normal to the mesh.
6967 * \param [inout] segments - PolySegment's defining positions of cutting planes.
6968 * Return the used vector and position of the middle point.
6969 * \param [in] groupName - optional name of a group where created mesh segments will
6972 //================================================================================
6974 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
6975 const char* theGroupName)
6976 throw (SALOME::SALOME_Exception)
6978 if ( theSegments.length() == 0 )
6979 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
6980 if ( myMesh->NbFaces() == 0 )
6981 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
6984 initData(/*deleteSearchers=*/false);
6986 SMESHDS_Group* groupDS = 0;
6987 SMESHDS_Mesh* meshDS = getMeshDS();
6988 if ( myIsPreviewMode ) // copy faces to the tmp mesh
6990 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
6991 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
6992 while ( faceIt->more() )
6993 tmpMesh->Copy( faceIt->next() );
6994 meshDS = tmpMesh->GetMeshDS();
6996 else if ( theGroupName[0] ) // find/create a group of segments
6998 SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
6999 while ( !groupDS && grpIt->more() )
7001 SMESH_Group* group = grpIt->next();
7002 if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7003 strcmp( group->GetName(), theGroupName ) == 0 )
7005 groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7010 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7012 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7013 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7017 // convert input polySegments
7018 ::SMESH_MeshEditor::TListOfPolySegments segments( theSegments.length() );
7019 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7021 SMESH::PolySegment& segIn = theSegments[ i ];
7022 ::SMESH_MeshEditor::PolySegment& segOut = segments[ i ];
7023 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7024 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7025 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7026 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7027 segOut.myVector.SetCoord( segIn.vector.PS.x,
7029 segIn.vector.PS.z );
7030 if ( !segOut.myNode1[0] )
7031 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node1ID1,
7032 SALOME::BAD_PARAM );
7033 if ( !segOut.myNode1[1] )
7034 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node2ID1,
7035 SALOME::BAD_PARAM );
7038 // get a static ElementSearcher
7039 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7040 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7041 if ( !theElementSearcher )
7042 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7045 getEditor().MakePolyLine( segments, groupDS, theElementSearcher );
7048 if ( myIsPreviewMode )
7050 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7052 SMESH::PolySegment& segOut = theSegments[ i ];
7053 ::SMESH_MeshEditor::PolySegment& segIn = segments[ i ];
7054 segOut.vector.PS.x = segIn.myVector.X();
7055 segOut.vector.PS.y = segIn.myVector.Y();
7056 segOut.vector.PS.z = segIn.myVector.Z();
7061 TPythonDump() << "_segments = []";
7062 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7064 SMESH::PolySegment& segIn = theSegments[ i ];
7065 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7066 << segIn.node1ID1 << ", "
7067 << segIn.node1ID2 << ", "
7068 << segIn.node2ID1 << ", "
7069 << segIn.node2ID2 << ", "
7070 << "smeshBuilder.MakeDirStruct( "
7071 << segIn.vector.PS.x << ", "
7072 << segIn.vector.PS.y << ", "
7073 << segIn.vector.PS.z << ")))";
7075 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7078 SMESH_CATCH( SMESH::throwCorbaException );