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_SetIterator.hxx"
46 #include "SMDS_VolumeTool.hxx"
47 #include "SMESHDS_Group.hxx"
48 #include "SMESHDS_GroupOnGeom.hxx"
49 #include "SMESH_ControlsDef.hxx"
50 #include "SMESH_Filter_i.hxx"
51 #include "SMESH_Gen_i.hxx"
52 #include "SMESH_Group.hxx"
53 #include "SMESH_Group_i.hxx"
54 #include "SMESH_MeshAlgos.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PythonDump.hxx"
58 #include "SMESH_subMeshEventListener.hxx"
59 #include "SMESH_subMesh_i.hxx"
61 #include <utilities.h>
62 #include <Utils_ExceptHandlers.hxx>
63 #include <Utils_CorbaException.hxx>
64 #include <SALOMEDS_wrap.hxx>
65 #include <SALOME_GenericObj_i.hh>
67 #include <BRepAdaptor_Surface.hxx>
68 #include <BRep_Tool.hxx>
69 #include <TopExp_Explorer.hxx>
71 #include <TopoDS_Edge.hxx>
72 #include <TopoDS_Face.hxx>
77 #include <Standard_Failure.hxx>
78 #include <Standard_ErrorHandler.hxx>
83 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
85 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
88 using SMESH::TPythonDump;
91 namespace MeshEditor_I {
93 //=============================================================================
95 * \brief Mesh to apply modifications for preview purposes
97 //=============================================================================
99 struct TPreviewMesh: public SMESH_Mesh
101 SMDSAbs_ElementType myPreviewType; // type to show
103 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
104 _isShapeToMesh = (_id = 0);
105 _myMeshDS = new SMESHDS_Mesh( _id, true );
106 myPreviewType = previewElements;
108 //!< Copy a set of elements
109 void Copy(const TIDSortedElemSet & theElements,
110 TIDSortedElemSet& theCopyElements,
111 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
112 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
114 // loop on theIDsOfElements
115 TIDSortedElemSet::const_iterator eIt = theElements.begin();
116 for ( ; eIt != theElements.end(); ++eIt )
118 const SMDS_MeshElement* anElem = *eIt;
119 if ( !anElem ) continue;
120 SMDSAbs_ElementType type = anElem->GetType();
121 if ( type == theAvoidType ||
122 ( theSelectType != SMDSAbs_All && type != theSelectType ))
124 const SMDS_MeshElement* anElemCopy;
125 if ( type == SMDSAbs_Node)
126 anElemCopy = Copy( cast2Node(anElem) );
128 anElemCopy = Copy( anElem );
130 theCopyElements.insert( theCopyElements.end(), anElemCopy );
134 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
136 // copy element nodes
137 int anElemNbNodes = anElem->NbNodes();
138 vector< int > anElemNodesID( anElemNbNodes ) ;
139 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
140 for ( int i = 0; itElemNodes->more(); i++)
142 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
144 anElemNodesID[i] = anElemNode->GetID();
147 // creates a corresponding element on copied nodes
148 ::SMESH_MeshEditor::ElemFeatures elemType;
149 elemType.Init( anElem, /*basicOnly=*/false );
150 elemType.SetID( anElem->GetID() );
151 SMDS_MeshElement* anElemCopy =
152 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
156 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
158 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
159 anElemNode->GetID());
163 GetMeshDS()->ClearMesh();
165 void Remove( SMDSAbs_ElementType type )
167 Remove( GetMeshDS()->elementsIterator( type ));
169 void Remove( SMDS_ElemIteratorPtr eIt )
171 while ( eIt->more() )
172 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
174 };// struct TPreviewMesh
176 static SMESH_NodeSearcher * theNodeSearcher = 0;
177 static SMESH_ElementSearcher * theElementSearcher = 0;
179 //=============================================================================
181 * \brief Deleter of theNodeSearcher and theElementSearcher at any compute event occurred
183 //=============================================================================
185 struct TSearchersDeleter : public SMESH_subMeshEventListener
188 string myMeshPartIOR;
190 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
191 "SMESH_MeshEditor_i::TSearchersDeleter"),
193 //!< Delete theNodeSearcher
196 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
197 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
199 typedef map < int, SMESH_subMesh * > TDependsOnMap;
200 //!< The meshod called by submesh: do my main job
201 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
202 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
204 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
206 Unset( sm->GetFather() );
209 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
210 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
212 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
219 myMeshPartIOR = meshPartIOR;
220 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
221 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
222 while ( smIt->more() )
225 sm->SetEventListener( this, 0, sm );
229 //!< delete self from all submeshes
230 void Unset(SMESH_Mesh* mesh)
232 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
233 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
234 while ( smIt->more() )
235 smIt->next()->DeleteEventListener( this );
240 } theSearchersDeleter;
242 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
244 TCollection_AsciiString typeStr;
245 switch ( theMirrorType ) {
246 case SMESH::SMESH_MeshEditor::POINT:
247 typeStr = "SMESH.SMESH_MeshEditor.POINT";
249 case SMESH::SMESH_MeshEditor::AXIS:
250 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
253 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
257 //================================================================================
259 * \brief function for conversion of long_array to TIDSortedElemSet
260 * \param IDs - array of IDs
261 * \param aMesh - mesh
262 * \param aMap - collection to fill
263 * \param aType - element type
265 //================================================================================
267 void arrayToSet(const SMESH::long_array & IDs,
268 const SMESHDS_Mesh* aMesh,
269 TIDSortedElemSet& aMap,
270 const SMDSAbs_ElementType aType = SMDSAbs_All,
271 SMDS_MeshElement::Filter* aFilter = NULL)
273 SMDS_MeshElement::NonNullFilter filter1;
274 SMDS_MeshElement::TypeFilter filter2( aType );
276 if ( aFilter == NULL )
277 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
279 SMDS_MeshElement::Filter & filter = *aFilter;
281 if ( aType == SMDSAbs_Node )
282 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
283 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
285 aMap.insert( aMap.end(), elem );
288 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
289 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
291 aMap.insert( aMap.end(), elem );
295 //================================================================================
297 * \brief Retrieve nodes from SMESH_IDSource
299 //================================================================================
301 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
302 const SMESHDS_Mesh* theMeshDS,
303 TIDSortedNodeSet& theNodeSet)
306 if ( CORBA::is_nil( theObject ) )
308 SMESH::array_of_ElementType_var types = theObject->GetTypes();
309 SMESH::long_array_var aElementsId = theObject->GetIDs();
310 if ( types->length() == 1 && types[0] == SMESH::NODE)
312 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
313 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
314 theNodeSet.insert( theNodeSet.end(), n);
316 else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
318 SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
319 while ( nIt->more( ))
320 if ( const SMDS_MeshElement * elem = nIt->next() )
321 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
325 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
326 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
327 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
331 //================================================================================
333 * \brief Returns elements connected to the given elements
335 //================================================================================
337 void getElementsAround(const TIDSortedElemSet& theElements,
338 const SMESHDS_Mesh* theMeshDS,
339 TIDSortedElemSet& theElementsAround)
341 if ( theElements.empty() ) return;
343 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
344 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
346 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
347 return; // all the elements are in theElements
350 elemType = SMDSAbs_All;
352 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
354 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
355 for ( ; elemIt != theElements.end(); ++elemIt )
357 const SMDS_MeshElement* e = *elemIt;
358 int i = e->NbCornerNodes();
361 const SMDS_MeshNode* n = e->GetNode( i );
362 if ( !isNodeChecked[ n->GetID() ])
364 isNodeChecked[ n->GetID() ] = true;
365 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
366 while ( invIt->more() )
368 const SMDS_MeshElement* elemAround = invIt->next();
369 if ( !theElements.count( elemAround ))
370 theElementsAround.insert( elemAround );
377 //================================================================================
379 * \brief Return a string used to detect change of mesh part on which theElementSearcher
380 * is going to be used
382 //================================================================================
384 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type = SMESH::ALL )
386 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
387 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
388 // take into account passible group modification
389 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
390 partIOR += SMESH_Comment( type );
394 } // namespace MeshEditor_I
396 using namespace MeshEditor_I;
398 //=============================================================================
402 //=============================================================================
404 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
406 myMesh( &theMesh->GetImpl() ),
408 myIsPreviewMode ( isPreview ),
414 //================================================================================
418 //================================================================================
420 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
422 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
423 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
424 poa->deactivate_object(anObjectId.in());
426 //deleteAuxIDSources();
427 delete myPreviewMesh; myPreviewMesh = 0;
428 delete myPreviewEditor; myPreviewEditor = 0;
431 //================================================================================
433 * \brief Returns the mesh
435 //================================================================================
437 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
439 return myMesh_i->_this();
442 //================================================================================
444 * \brief Clear members
446 //================================================================================
448 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
450 if ( myIsPreviewMode ) {
451 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
454 if ( deleteSearchers )
455 TSearchersDeleter::Delete();
457 getEditor().GetError().reset();
458 getEditor().ClearLastCreated();
461 //================================================================================
463 * \brief Increment mesh modif time and optionally record that the performed
464 * modification may influence further mesh re-compute.
465 * \param [in] isReComputeSafe - true if the modification does not influence
466 * further mesh re-compute
468 //================================================================================
470 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
472 myMesh->GetMeshDS()->Modified();
473 if ( !isReComputeSafe )
474 myMesh->SetIsModified( true );
477 //================================================================================
479 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
480 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
482 //================================================================================
484 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
486 if ( myIsPreviewMode && !myPreviewEditor ) {
487 if ( !myPreviewMesh ) getPreviewMesh();
488 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
490 return myIsPreviewMode ? *myPreviewEditor : myEditor;
493 //================================================================================
495 * \brief Initialize and return myPreviewMesh
496 * \param previewElements - type of elements to show in preview
498 * WARNING: call it once per method!
500 //================================================================================
502 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
504 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
506 delete myPreviewEditor;
508 delete myPreviewMesh;
509 myPreviewMesh = new TPreviewMesh( previewElements );
511 myPreviewMesh->Clear();
512 return myPreviewMesh;
515 //================================================================================
517 * Return data of mesh edition preview
519 //================================================================================
521 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
522 throw (SALOME::SALOME_Exception)
525 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
527 if ( myIsPreviewMode || hasBadElems )
529 list<int> aNodesConnectivity;
530 typedef map<int, int> TNodesMap;
533 SMESHDS_Mesh* aMeshDS;
534 std::unique_ptr< SMESH_MeshPartDS > aMeshPartDS;
536 const list<const SMDS_MeshElement*>& badElems =
537 static_cast<SMESH_BadInputElements*>( getEditor().GetError().get() )->myBadElements;
538 aMeshPartDS.reset( new SMESH_MeshPartDS( badElems ));
539 aMeshDS = aMeshPartDS.get();
542 aMeshDS = getEditor().GetMeshDS();
544 myPreviewData = new SMESH::MeshPreviewStruct();
545 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
548 SMDSAbs_ElementType previewType = SMDSAbs_All;
550 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
551 previewType = aPreviewMesh->myPreviewType;
552 switch ( previewType ) {
553 case SMDSAbs_Edge : break;
554 case SMDSAbs_Face : break;
555 case SMDSAbs_Volume: break;
557 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
561 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
563 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
565 while ( itMeshElems->more() ) {
566 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
567 SMDS_NodeIteratorPtr itElemNodes =
568 (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
569 aMeshElem->interlacedNodesIterator() :
570 aMeshElem->nodeIterator() );
571 while ( itElemNodes->more() ) {
572 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
573 int aNodeID = aMeshNode->GetID();
574 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
575 if ( anIter == nodesMap.end() ) {
576 // filling the nodes coordinates
577 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
578 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
579 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
580 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
583 aNodesConnectivity.push_back(anIter->second);
586 // filling the elements types
587 SMDSAbs_ElementType aType = aMeshElem->GetType();
588 bool isPoly = aMeshElem->IsPoly();
589 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
590 myPreviewData->elementTypes[i].isPoly = isPoly;
591 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
594 myPreviewData->nodesXYZ.length( j );
596 // filling the elements connectivities
597 list<int>::iterator aConnIter = aNodesConnectivity.begin();
598 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
599 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
600 myPreviewData->elementConnectivities[i] = *aConnIter;
602 return myPreviewData._retn();
604 SMESH_CATCH( SMESH::throwCorbaException );
608 //================================================================================
610 * \brief Returns list of it's IDs of created nodes
611 * \retval SMESH::long_array* - list of node ID
613 //================================================================================
615 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
616 throw (SALOME::SALOME_Exception)
619 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
621 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
622 myLastCreatedNodes->length( aSeq.size() );
623 for ( size_t i = 0; i < aSeq.size(); i++)
624 myLastCreatedNodes[i] = aSeq[i]->GetID();
626 return myLastCreatedNodes._retn();
627 SMESH_CATCH( SMESH::throwCorbaException );
631 //================================================================================
633 * \brief Returns list of it's IDs of created elements
634 * \retval SMESH::long_array* - list of elements' ID
636 //================================================================================
638 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
639 throw (SALOME::SALOME_Exception)
642 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
644 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
645 myLastCreatedElems->length( aSeq.size() );
646 for ( size_t i = 0; i < aSeq.size(); i++ )
647 myLastCreatedElems[i] = aSeq[i]->GetID();
649 return myLastCreatedElems._retn();
650 SMESH_CATCH( SMESH::throwCorbaException );
654 //=======================================================================
655 //function : ClearLastCreated
656 //purpose : Clears sequences of last created elements and nodes
657 //=======================================================================
659 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
662 getEditor().ClearLastCreated();
663 SMESH_CATCH( SMESH::throwCorbaException );
666 //=======================================================================
668 * Returns description of an error/warning occurred during the last operation
669 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
671 //=======================================================================
673 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
674 throw (SALOME::SALOME_Exception)
677 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
678 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
679 if ( errIn && !errIn->IsOK() )
681 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
682 errOut->comment = errIn->myComment.c_str();
683 errOut->subShapeID = -1;
684 errOut->hasBadMesh = errIn->HasBadElems();
689 errOut->subShapeID = -1;
690 errOut->hasBadMesh = false;
693 return errOut._retn();
694 SMESH_CATCH( SMESH::throwCorbaException );
698 //=======================================================================
699 //function : MakeIDSource
700 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
701 // Call UnRegister() as you fininsh using it!!
702 //=======================================================================
704 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
705 public virtual SALOME::GenericObj_i
707 SMESH::long_array _ids;
708 SMESH::ElementType _type;
709 SMESH::SMESH_Mesh_ptr _mesh;
710 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
711 SMESH::long_array* GetMeshInfo() { return 0; }
712 SMESH::long_array* GetNbElementsByType()
714 SMESH::long_array_var aRes = new SMESH::long_array();
715 aRes->length(SMESH::NB_ELEMENT_TYPES);
716 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
717 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
720 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
721 bool IsMeshInfoCorrect() { return true; }
722 SMESH::array_of_ElementType* GetTypes()
724 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
725 if ( _ids.length() > 0 ) {
729 return types._retn();
731 SALOMEDS::TMPFile* GetVtkUgStream()
733 SALOMEDS::TMPFile_var SeqFile;
734 return SeqFile._retn();
738 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
739 SMESH::ElementType type)
741 _IDSource* idSrc = new _IDSource;
742 idSrc->_mesh = myMesh_i->_this();
745 if ( type == SMESH::ALL && ids.length() > 0 )
746 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
748 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
750 return anIDSourceVar._retn();
753 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
755 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
758 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
761 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
763 nbIds = (int) tmpIdSource->_ids.length();
764 return & tmpIdSource->_ids[0];
770 // void SMESH_MeshEditor_i::deleteAuxIDSources()
772 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
773 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
775 // myAuxIDSources.clear();
778 //=============================================================================
782 //=============================================================================
785 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
786 throw (SALOME::SALOME_Exception)
793 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
794 IdList.push_back( IDsOfElements[i] );
796 // Update Python script
797 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
800 bool ret = getEditor().Remove( IdList, false );
802 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
805 SMESH_CATCH( SMESH::throwCorbaException );
809 //=============================================================================
813 //=============================================================================
815 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
816 throw (SALOME::SALOME_Exception)
822 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
823 IdList.push_back( IDsOfNodes[i] );
825 // Update Python script
826 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
828 bool ret = getEditor().Remove( IdList, true );
830 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
833 SMESH_CATCH( SMESH::throwCorbaException );
837 //=============================================================================
841 //=============================================================================
843 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
844 throw (SALOME::SALOME_Exception)
849 // Update Python script
850 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
852 // Create filter to find all orphan nodes
853 SMESH::Controls::Filter::TIdSequence seq;
854 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
855 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
857 // remove orphan nodes (if there are any)
858 list< int > IdList( seq.begin(), seq.end() );
860 int nbNodesBefore = myMesh->NbNodes();
861 getEditor().Remove( IdList, true );
862 int nbNodesAfter = myMesh->NbNodes();
864 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
865 return nbNodesBefore - nbNodesAfter;
867 SMESH_CATCH( SMESH::throwCorbaException );
871 //=============================================================================
875 //=============================================================================
877 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
878 throw (SALOME::SALOME_Exception)
883 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
885 // Update Python script
886 TPythonDump() << "nodeID = " << this << ".AddNode( "
887 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
889 declareMeshModified( /*isReComputeSafe=*/false );
892 SMESH_CATCH( SMESH::throwCorbaException );
896 //=============================================================================
898 * Create 0D element on the given node.
900 //=============================================================================
902 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode,
903 CORBA::Boolean DuplicateElements)
904 throw (SALOME::SALOME_Exception)
909 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
910 SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
912 SMDS_MeshElement* elem = 0;
913 if ( DuplicateElements || !it0D->more() )
914 elem = getMeshDS()->Add0DElement(aNode);
916 // Update Python script
917 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
919 declareMeshModified( /*isReComputeSafe=*/false );
921 return elem ? elem->GetID() : 0;
923 SMESH_CATCH( SMESH::throwCorbaException );
927 //=============================================================================
929 * Create a ball element on the given node.
931 //=============================================================================
933 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
934 throw (SALOME::SALOME_Exception)
939 if ( diameter < std::numeric_limits<double>::min() )
940 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
942 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
943 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
945 // Update Python script
946 TPythonDump() << "ballElem = "
947 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
949 declareMeshModified( /*isReComputeSafe=*/false );
950 return elem ? elem->GetID() : 0;
952 SMESH_CATCH( SMESH::throwCorbaException );
956 //=============================================================================
958 * Create an edge, either linear and quadratic (this is determed
959 * by number of given nodes, two or three)
961 //=============================================================================
963 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
964 throw (SALOME::SALOME_Exception)
969 int NbNodes = IDsOfNodes.length();
970 SMDS_MeshElement* elem = 0;
973 CORBA::Long index1 = IDsOfNodes[0];
974 CORBA::Long index2 = IDsOfNodes[1];
975 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
976 getMeshDS()->FindNode(index2));
978 // Update Python script
979 TPythonDump() << "edge = " << this << ".AddEdge([ "
980 << index1 << ", " << index2 <<" ])";
983 CORBA::Long n1 = IDsOfNodes[0];
984 CORBA::Long n2 = IDsOfNodes[1];
985 CORBA::Long n12 = IDsOfNodes[2];
986 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
987 getMeshDS()->FindNode(n2),
988 getMeshDS()->FindNode(n12));
989 // Update Python script
990 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
991 <<n1<<", "<<n2<<", "<<n12<<" ])";
994 declareMeshModified( /*isReComputeSafe=*/false );
995 return elem ? elem->GetID() : 0;
997 SMESH_CATCH( SMESH::throwCorbaException );
1001 //=============================================================================
1005 //=============================================================================
1007 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1008 throw (SALOME::SALOME_Exception)
1013 int NbNodes = IDsOfNodes.length();
1019 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1020 for (int i = 0; i < NbNodes; i++)
1021 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1023 SMDS_MeshElement* elem = 0;
1025 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1026 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1027 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1028 nodes[4], nodes[5]); break;
1029 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1030 nodes[4], nodes[5], nodes[6]); break;
1031 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1032 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1033 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1034 nodes[4], nodes[5], nodes[6], nodes[7],
1036 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1039 // Update Python script
1040 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1042 declareMeshModified( /*isReComputeSafe=*/false );
1044 return elem ? elem->GetID() : 0;
1046 SMESH_CATCH( SMESH::throwCorbaException );
1050 //=============================================================================
1054 //=============================================================================
1056 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1057 throw (SALOME::SALOME_Exception)
1062 int NbNodes = IDsOfNodes.length();
1063 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1064 for (int i = 0; i < NbNodes; i++)
1065 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1068 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1070 // Update Python script
1071 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1073 declareMeshModified( /*isReComputeSafe=*/false );
1074 return elem ? elem->GetID() : 0;
1076 SMESH_CATCH( SMESH::throwCorbaException );
1080 //=============================================================================
1082 * AddQuadPolygonalFace
1084 //=============================================================================
1086 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1087 throw (SALOME::SALOME_Exception)
1092 int NbNodes = IDsOfNodes.length();
1093 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1094 for (int i = 0; i < NbNodes; i++)
1095 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1097 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1099 // Update Python script
1100 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1102 declareMeshModified( /*isReComputeSafe=*/false );
1103 return elem ? elem->GetID() : 0;
1105 SMESH_CATCH( SMESH::throwCorbaException );
1109 //=============================================================================
1111 * Create volume, either linear and quadratic (this is determed
1112 * by number of given nodes)
1114 //=============================================================================
1116 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1117 throw (SALOME::SALOME_Exception)
1122 int NbNodes = IDsOfNodes.length();
1123 vector< const SMDS_MeshNode*> n(NbNodes);
1124 for(int i=0;i<NbNodes;i++)
1125 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1127 SMDS_MeshElement* elem = 0;
1130 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1131 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1132 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1133 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1134 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1135 n[6],n[7],n[8],n[9]);
1137 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1138 n[6],n[7],n[8],n[9],n[10],n[11]);
1140 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1141 n[7],n[8],n[9],n[10],n[11],n[12]);
1143 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1144 n[9],n[10],n[11],n[12],n[13],n[14]);
1146 case 20: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],
1148 n[15],n[16],n[17],n[18],n[19]);
1150 case 18: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],
1154 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1155 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1156 n[15],n[16],n[17],n[18],n[19],
1157 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1161 // Update Python script
1162 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1164 declareMeshModified( /*isReComputeSafe=*/false );
1165 return elem ? elem->GetID() : 0;
1167 SMESH_CATCH( SMESH::throwCorbaException );
1171 //=============================================================================
1173 * AddPolyhedralVolume
1175 //=============================================================================
1176 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1177 const SMESH::long_array & Quantities)
1178 throw (SALOME::SALOME_Exception)
1183 int NbNodes = IDsOfNodes.length();
1184 std::vector<const SMDS_MeshNode*> n (NbNodes);
1185 for (int i = 0; i < NbNodes; i++)
1187 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1188 if (!aNode) return 0;
1192 int NbFaces = Quantities.length();
1193 std::vector<int> q (NbFaces);
1194 for (int j = 0; j < NbFaces; j++)
1195 q[j] = Quantities[j];
1197 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1199 // Update Python script
1200 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1201 << IDsOfNodes << ", " << Quantities << " )";
1203 declareMeshModified( /*isReComputeSafe=*/false );
1204 return elem ? elem->GetID() : 0;
1206 SMESH_CATCH( SMESH::throwCorbaException );
1210 //=============================================================================
1212 * AddPolyhedralVolumeByFaces
1214 //=============================================================================
1216 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1217 throw (SALOME::SALOME_Exception)
1222 int NbFaces = IdsOfFaces.length();
1223 std::vector<const SMDS_MeshNode*> poly_nodes;
1224 std::vector<int> quantities (NbFaces);
1226 for (int i = 0; i < NbFaces; i++) {
1227 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1228 quantities[i] = aFace->NbNodes();
1230 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1231 while (It->more()) {
1232 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1236 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1238 // Update Python script
1239 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1240 << IdsOfFaces << " )";
1242 declareMeshModified( /*isReComputeSafe=*/false );
1243 return elem ? elem->GetID() : 0;
1245 SMESH_CATCH( SMESH::throwCorbaException );
1249 //=============================================================================
1251 // \brief Create 0D elements on all nodes of the given object.
1252 // \param theObject object on whose nodes 0D elements will be created.
1253 // \param theGroupName optional name of a group to add 0D elements created
1254 // and/or found on nodes of \a theObject.
1255 // \param DuplicateElements to add one more 0D element to a node or not.
1256 // \return an object (a new group or a temporary SMESH_IDSource) holding
1257 // ids of new and/or found 0D elements.
1259 //=============================================================================
1261 SMESH::SMESH_IDSource_ptr
1262 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1263 const char* theGroupName,
1264 CORBA::Boolean theDuplicateElements)
1265 throw (SALOME::SALOME_Exception)
1270 SMESH::SMESH_IDSource_var result;
1273 TIDSortedElemSet elements, elems0D;
1274 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1275 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1277 SMESH::long_array_var newElems = new SMESH::long_array;
1278 newElems->length( elems0D.size() );
1279 TIDSortedElemSet::iterator eIt = elems0D.begin();
1280 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1281 newElems[ i ] = (*eIt)->GetID();
1283 SMESH::SMESH_GroupBase_var groupToFill;
1284 if ( theGroupName && strlen( theGroupName ))
1286 // Get existing group named theGroupName
1287 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1288 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1289 SMESH::SMESH_GroupBase_var group = groups[i];
1290 if ( !group->_is_nil() ) {
1291 CORBA::String_var name = group->GetName();
1292 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1293 groupToFill = group;
1298 if ( groupToFill->_is_nil() )
1299 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1300 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1301 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1304 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1306 group_i->Add( newElems );
1307 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1308 pyDump << groupToFill;
1312 result = MakeIDSource( newElems, SMESH::ELEM0D );
1313 pyDump << "elem0DIDs";
1316 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1317 << theObject << ", '" << theGroupName << "' )";
1319 return result._retn();
1321 SMESH_CATCH( SMESH::throwCorbaException );
1325 //=============================================================================
1327 * \brief Bind a node to a vertex
1328 * \param NodeID - node ID
1329 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1330 * \retval boolean - false if NodeID or VertexID is invalid
1332 //=============================================================================
1334 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1335 throw (SALOME::SALOME_Exception)
1339 SMESHDS_Mesh * mesh = getMeshDS();
1340 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1342 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1344 if ( mesh->MaxShapeIndex() < VertexID )
1345 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1347 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1348 if ( shape.ShapeType() != TopAbs_VERTEX )
1349 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1351 mesh->SetNodeOnVertex( node, VertexID );
1353 myMesh->SetIsModified( true );
1355 SMESH_CATCH( SMESH::throwCorbaException );
1358 //=============================================================================
1360 * \brief Store node position on an edge
1361 * \param NodeID - node ID
1362 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1363 * \param paramOnEdge - parameter on edge where the node is located
1364 * \retval boolean - false if any parameter is invalid
1366 //=============================================================================
1368 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1369 CORBA::Double paramOnEdge)
1370 throw (SALOME::SALOME_Exception)
1374 SMESHDS_Mesh * mesh = getMeshDS();
1375 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1377 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1379 if ( mesh->MaxShapeIndex() < EdgeID )
1380 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1382 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1383 if ( shape.ShapeType() != TopAbs_EDGE )
1384 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1387 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1388 if ( paramOnEdge < f || paramOnEdge > l )
1389 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1391 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1393 myMesh->SetIsModified( true );
1395 SMESH_CATCH( SMESH::throwCorbaException );
1398 //=============================================================================
1400 * \brief Store node position on a face
1401 * \param NodeID - node ID
1402 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1403 * \param u - U parameter on face where the node is located
1404 * \param v - V parameter on face where the node is located
1405 * \retval boolean - false if any parameter is invalid
1407 //=============================================================================
1409 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1410 CORBA::Double u, CORBA::Double v)
1411 throw (SALOME::SALOME_Exception)
1414 SMESHDS_Mesh * mesh = getMeshDS();
1415 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1417 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1419 if ( mesh->MaxShapeIndex() < FaceID )
1420 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1422 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1423 if ( shape.ShapeType() != TopAbs_FACE )
1424 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1426 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1427 bool isOut = ( u < surf.FirstUParameter() ||
1428 u > surf.LastUParameter() ||
1429 v < surf.FirstVParameter() ||
1430 v > surf.LastVParameter() );
1434 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1435 << " u( " << surf.FirstUParameter()
1436 << "," << surf.LastUParameter()
1437 << ") v( " << surf.FirstVParameter()
1438 << "," << surf.LastVParameter() << ")" );
1440 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1443 mesh->SetNodeOnFace( node, FaceID, u, v );
1444 myMesh->SetIsModified( true );
1446 SMESH_CATCH( SMESH::throwCorbaException );
1449 //=============================================================================
1451 * \brief Bind a node to a solid
1452 * \param NodeID - node ID
1453 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1454 * \retval boolean - false if NodeID or SolidID is invalid
1456 //=============================================================================
1458 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1459 throw (SALOME::SALOME_Exception)
1462 SMESHDS_Mesh * mesh = getMeshDS();
1463 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1465 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1467 if ( mesh->MaxShapeIndex() < SolidID )
1468 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1470 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1471 if ( shape.ShapeType() != TopAbs_SOLID &&
1472 shape.ShapeType() != TopAbs_SHELL)
1473 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1475 mesh->SetNodeInVolume( node, SolidID );
1477 SMESH_CATCH( SMESH::throwCorbaException );
1480 //=============================================================================
1482 * \brief Bind an element to a shape
1483 * \param ElementID - element ID
1484 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1486 //=============================================================================
1488 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1489 CORBA::Long ShapeID)
1490 throw (SALOME::SALOME_Exception)
1493 SMESHDS_Mesh * mesh = getMeshDS();
1494 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1496 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1498 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1499 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1501 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1502 if ( shape.ShapeType() != TopAbs_EDGE &&
1503 shape.ShapeType() != TopAbs_FACE &&
1504 shape.ShapeType() != TopAbs_SOLID &&
1505 shape.ShapeType() != TopAbs_SHELL )
1506 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1508 mesh->SetMeshElementOnShape( elem, ShapeID );
1510 myMesh->SetIsModified( true );
1512 SMESH_CATCH( SMESH::throwCorbaException );
1515 //=============================================================================
1519 //=============================================================================
1521 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1522 CORBA::Long NodeID2)
1523 throw (SALOME::SALOME_Exception)
1528 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1529 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1533 // Update Python script
1534 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1535 << NodeID1 << ", " << NodeID2 << " )";
1537 int ret = getEditor().InverseDiag ( n1, n2 );
1539 declareMeshModified( /*isReComputeSafe=*/false );
1542 SMESH_CATCH( SMESH::throwCorbaException );
1546 //=============================================================================
1550 //=============================================================================
1552 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1553 CORBA::Long NodeID2)
1554 throw (SALOME::SALOME_Exception)
1559 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1560 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1564 // Update Python script
1565 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1566 << NodeID1 << ", " << NodeID2 << " )";
1569 bool stat = getEditor().DeleteDiag ( n1, n2 );
1571 declareMeshModified( /*isReComputeSafe=*/!stat );
1575 SMESH_CATCH( SMESH::throwCorbaException );
1579 //=============================================================================
1583 //=============================================================================
1585 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1586 throw (SALOME::SALOME_Exception)
1591 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1593 CORBA::Long index = IDsOfElements[i];
1594 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1596 getEditor().Reorient( elem );
1598 // Update Python script
1599 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1601 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1604 SMESH_CATCH( SMESH::throwCorbaException );
1608 //=============================================================================
1612 //=============================================================================
1614 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1615 throw (SALOME::SALOME_Exception)
1620 TPythonDump aTPythonDump; // suppress dump in Reorient()
1622 prepareIdSource( theObject );
1624 SMESH::long_array_var anElementsId = theObject->GetIDs();
1625 CORBA::Boolean isDone = Reorient(anElementsId);
1627 // Update Python script
1628 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1630 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1633 SMESH_CATCH( SMESH::throwCorbaException );
1637 //=======================================================================
1638 //function : Reorient2D
1639 //purpose : Reorient faces contained in \a the2Dgroup.
1640 // the2Dgroup - the mesh or its part to reorient
1641 // theDirection - desired direction of normal of \a theFace
1642 // theFace - ID of face whose orientation is checked.
1643 // It can be < 1 then \a thePoint is used to find a face.
1644 // thePoint - is used to find a face if \a theFace < 1.
1645 // return number of reoriented elements.
1646 //=======================================================================
1648 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1649 const SMESH::DirStruct& theDirection,
1650 CORBA::Long theFace,
1651 const SMESH::PointStruct& thePoint)
1652 throw (SALOME::SALOME_Exception)
1655 initData(/*deleteSearchers=*/false);
1657 TIDSortedElemSet elements;
1658 IDSource_Error error;
1659 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1660 if ( error == IDSource_EMPTY )
1662 if ( error == IDSource_INVALID )
1663 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1666 const SMDS_MeshElement* face = 0;
1669 face = getMeshDS()->FindElement( theFace );
1671 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1672 if ( face->GetType() != SMDSAbs_Face )
1673 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1677 // create theElementSearcher if needed
1678 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1679 if ( !theElementSearcher )
1681 if ( elements.empty() ) // search in the whole mesh
1683 if ( myMesh->NbFaces() == 0 )
1684 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1686 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1690 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1691 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1693 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1697 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1698 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1701 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1702 if ( !elements.empty() && !elements.count( face ))
1703 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1706 const SMESH::PointStruct * P = &theDirection.PS;
1707 gp_Vec dirVec( P->x, P->y, P->z );
1708 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1709 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1711 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1714 declareMeshModified( /*isReComputeSafe=*/false );
1716 TPythonDump() << this << ".Reorient2D( "
1717 << the2Dgroup << ", "
1718 << theDirection << ", "
1720 << thePoint << " )";
1724 SMESH_CATCH( SMESH::throwCorbaException );
1728 //=======================================================================
1729 //function : Reorient2DBy3D
1730 //purpose : Reorient faces basing on orientation of adjacent volumes.
1731 //=======================================================================
1733 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1734 SMESH::SMESH_IDSource_ptr volumeGroup,
1735 CORBA::Boolean outsideNormal)
1736 throw (SALOME::SALOME_Exception)
1741 TIDSortedElemSet volumes;
1742 IDSource_Error volsError;
1743 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1746 for ( size_t i = 0; i < faceGroups.length(); ++i )
1748 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1750 TIDSortedElemSet faces;
1751 IDSource_Error error;
1752 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1753 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1754 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1755 if ( error == IDSource_OK && volsError != IDSource_OK )
1756 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1758 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1760 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1765 declareMeshModified( /*isReComputeSafe=*/false );
1767 TPythonDump() << this << ".Reorient2DBy3D( "
1768 << faceGroups << ", "
1769 << volumeGroup << ", "
1770 << outsideNormal << " )";
1774 SMESH_CATCH( SMESH::throwCorbaException );
1778 //=============================================================================
1780 * \brief Fuse neighbour triangles into quadrangles.
1782 //=============================================================================
1784 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1785 SMESH::NumericalFunctor_ptr Criterion,
1786 CORBA::Double MaxAngle)
1787 throw (SALOME::SALOME_Exception)
1792 SMESHDS_Mesh* aMesh = getMeshDS();
1793 TIDSortedElemSet faces,copyFaces;
1794 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1795 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1796 TIDSortedElemSet* workElements = & faces;
1798 if ( myIsPreviewMode ) {
1799 SMDSAbs_ElementType select = SMDSAbs_Face;
1800 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1801 workElements = & copyFaces;
1804 SMESH::NumericalFunctor_i* aNumericalFunctor =
1805 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1806 SMESH::Controls::NumericalFunctorPtr aCrit;
1807 if ( !aNumericalFunctor )
1808 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1810 aCrit = aNumericalFunctor->GetNumericalFunctor();
1812 if ( !myIsPreviewMode ) {
1813 // Update Python script
1814 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1815 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1818 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1820 declareMeshModified( /*isReComputeSafe=*/!stat );
1823 SMESH_CATCH( SMESH::throwCorbaException );
1827 //=============================================================================
1829 * \brief Fuse neighbour triangles into quadrangles.
1831 //=============================================================================
1833 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1834 SMESH::NumericalFunctor_ptr Criterion,
1835 CORBA::Double MaxAngle)
1836 throw (SALOME::SALOME_Exception)
1841 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1843 prepareIdSource( theObject );
1844 SMESH::long_array_var anElementsId = theObject->GetIDs();
1845 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1847 if ( !myIsPreviewMode ) {
1848 SMESH::NumericalFunctor_i* aNumericalFunctor =
1849 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1851 // Update Python script
1852 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1853 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1858 SMESH_CATCH( SMESH::throwCorbaException );
1862 //=============================================================================
1864 * \brief Split quadrangles into triangles.
1866 //=============================================================================
1868 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1869 SMESH::NumericalFunctor_ptr Criterion)
1870 throw (SALOME::SALOME_Exception)
1875 SMESHDS_Mesh* aMesh = getMeshDS();
1876 TIDSortedElemSet faces;
1877 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1879 SMESH::NumericalFunctor_i* aNumericalFunctor =
1880 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1881 SMESH::Controls::NumericalFunctorPtr aCrit;
1882 if ( !aNumericalFunctor )
1883 aCrit.reset( new SMESH::Controls::AspectRatio() );
1885 aCrit = aNumericalFunctor->GetNumericalFunctor();
1888 // Update Python script
1889 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1891 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1893 declareMeshModified( /*isReComputeSafe=*/false );
1896 SMESH_CATCH( SMESH::throwCorbaException );
1900 //=============================================================================
1902 * \brief Split quadrangles into triangles.
1904 //=============================================================================
1906 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1907 SMESH::NumericalFunctor_ptr Criterion)
1908 throw (SALOME::SALOME_Exception)
1913 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1915 prepareIdSource( theObject );
1916 SMESH::long_array_var anElementsId = theObject->GetIDs();
1917 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1919 SMESH::NumericalFunctor_i* aNumericalFunctor =
1920 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1922 // Update Python script
1923 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1925 declareMeshModified( /*isReComputeSafe=*/false );
1928 SMESH_CATCH( SMESH::throwCorbaException );
1932 //================================================================================
1934 * \brief Split each of quadrangles into 4 triangles.
1935 * \param [in] theObject - theQuads Container of quadrangles to split.
1937 //================================================================================
1939 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1940 throw (SALOME::SALOME_Exception)
1945 TIDSortedElemSet faces;
1946 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1948 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1950 getEditor().QuadTo4Tri( faces );
1951 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1953 SMESH_CATCH( SMESH::throwCorbaException );
1956 //=============================================================================
1958 * \brief Split quadrangles into triangles.
1960 //=============================================================================
1962 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1963 CORBA::Boolean Diag13)
1964 throw (SALOME::SALOME_Exception)
1969 SMESHDS_Mesh* aMesh = getMeshDS();
1970 TIDSortedElemSet faces;
1971 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1973 // Update Python script
1974 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1975 << IDsOfElements << ", " << Diag13 << " )";
1977 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1979 declareMeshModified( /*isReComputeSafe=*/ !stat );
1982 SMESH_CATCH( SMESH::throwCorbaException );
1986 //=============================================================================
1988 * \brief Split quadrangles into triangles.
1990 //=============================================================================
1992 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1993 CORBA::Boolean Diag13)
1994 throw (SALOME::SALOME_Exception)
1999 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2001 prepareIdSource( theObject );
2002 SMESH::long_array_var anElementsId = theObject->GetIDs();
2003 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2005 // Update Python script
2006 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2007 << theObject << ", " << Diag13 << " )";
2009 declareMeshModified( /*isReComputeSafe=*/!isDone );
2012 SMESH_CATCH( SMESH::throwCorbaException );
2017 //=============================================================================
2019 * Find better splitting of the given quadrangle.
2020 * \param IDOfQuad ID of the quadrangle to be split.
2021 * \param Criterion A criterion to choose a diagonal for splitting.
2022 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2023 * diagonal is better, 0 if error occurs.
2025 //=============================================================================
2027 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2028 SMESH::NumericalFunctor_ptr Criterion)
2029 throw (SALOME::SALOME_Exception)
2034 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2035 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2037 SMESH::NumericalFunctor_i* aNumericalFunctor =
2038 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2039 SMESH::Controls::NumericalFunctorPtr aCrit;
2040 if (aNumericalFunctor)
2041 aCrit = aNumericalFunctor->GetNumericalFunctor();
2043 aCrit.reset(new SMESH::Controls::AspectRatio());
2045 int id = getEditor().BestSplit(quad, aCrit);
2046 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2050 SMESH_CATCH( SMESH::throwCorbaException );
2054 //================================================================================
2056 * \brief Split volumic elements into tetrahedrons
2058 //================================================================================
2060 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2061 CORBA::Short methodFlags)
2062 throw (SALOME::SALOME_Exception)
2067 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2068 const int noneFacet = -1;
2069 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2070 while( volIt->more() )
2071 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2073 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2074 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2076 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2077 << elems << ", " << methodFlags << " )";
2079 SMESH_CATCH( SMESH::throwCorbaException );
2082 //================================================================================
2084 * \brief Split hexahedra into triangular prisms
2085 * \param elems - elements to split
2086 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2087 * to split into triangles
2088 * \param methodFlags - flags passing splitting method:
2089 * 1 - split the hexahedron into 2 prisms
2090 * 2 - split the hexahedron into 4 prisms
2092 //================================================================================
2094 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2095 const SMESH::PointStruct & startHexPoint,
2096 const SMESH::DirStruct& facetToSplitNormal,
2097 CORBA::Short methodFlags,
2098 CORBA::Boolean allDomains)
2099 throw (SALOME::SALOME_Exception)
2103 prepareIdSource( elems );
2105 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2108 gp_Dir( facetToSplitNormal.PS.x,
2109 facetToSplitNormal.PS.y,
2110 facetToSplitNormal.PS.z ));
2111 TIDSortedElemSet elemSet;
2112 SMESH::long_array_var anElementsId = elems->GetIDs();
2113 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2114 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2116 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2117 while ( !elemSet.empty() )
2119 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2123 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2124 for ( ; ef != elemFacets.end(); ++ef )
2125 elemSet.erase( ef->first );
2128 if ( methodFlags == 2 )
2129 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2131 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2133 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2134 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2136 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2138 << startHexPoint << ", "
2139 << facetToSplitNormal<< ", "
2140 << methodFlags<< ", "
2141 << allDomains << " )";
2143 SMESH_CATCH( SMESH::throwCorbaException );
2146 //================================================================================
2148 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2149 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2150 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2151 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2152 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2153 * will be split in order to keep the mesh conformal.
2154 * \param elems - elements to split
2156 //================================================================================
2158 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2159 throw (SALOME::SALOME_Exception)
2164 TIDSortedElemSet elemSet;
2165 for ( size_t i = 0; i < theElems.length(); ++i )
2167 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2168 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2169 if ( mesh->GetId() != myMesh_i->GetId() )
2170 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2172 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2174 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2176 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2178 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2179 << theElems << " )";
2181 SMESH_CATCH( SMESH::throwCorbaException );
2184 //=======================================================================
2187 //=======================================================================
2190 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2191 const SMESH::long_array & IDsOfFixedNodes,
2192 CORBA::Long MaxNbOfIterations,
2193 CORBA::Double MaxAspectRatio,
2194 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2195 throw (SALOME::SALOME_Exception)
2197 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2198 MaxAspectRatio, Method, false );
2202 //=======================================================================
2203 //function : SmoothParametric
2205 //=======================================================================
2208 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2209 const SMESH::long_array & IDsOfFixedNodes,
2210 CORBA::Long MaxNbOfIterations,
2211 CORBA::Double MaxAspectRatio,
2212 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2213 throw (SALOME::SALOME_Exception)
2215 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2216 MaxAspectRatio, Method, true );
2220 //=======================================================================
2221 //function : SmoothObject
2223 //=======================================================================
2226 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2227 const SMESH::long_array & IDsOfFixedNodes,
2228 CORBA::Long MaxNbOfIterations,
2229 CORBA::Double MaxAspectRatio,
2230 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2231 throw (SALOME::SALOME_Exception)
2233 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2234 MaxAspectRatio, Method, false);
2238 //=======================================================================
2239 //function : SmoothParametricObject
2241 //=======================================================================
2244 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2245 const SMESH::long_array & IDsOfFixedNodes,
2246 CORBA::Long MaxNbOfIterations,
2247 CORBA::Double MaxAspectRatio,
2248 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2249 throw (SALOME::SALOME_Exception)
2251 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2252 MaxAspectRatio, Method, true);
2256 //=============================================================================
2260 //=============================================================================
2263 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2264 const SMESH::long_array & IDsOfFixedNodes,
2265 CORBA::Long MaxNbOfIterations,
2266 CORBA::Double MaxAspectRatio,
2267 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2269 throw (SALOME::SALOME_Exception)
2274 SMESHDS_Mesh* aMesh = getMeshDS();
2276 TIDSortedElemSet elements;
2277 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2279 set<const SMDS_MeshNode*> fixedNodes;
2280 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2281 CORBA::Long index = IDsOfFixedNodes[i];
2282 const SMDS_MeshNode * node = aMesh->FindNode(index);
2284 fixedNodes.insert( node );
2286 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2287 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2288 method = ::SMESH_MeshEditor::CENTROIDAL;
2290 getEditor().Smooth(elements, fixedNodes, method,
2291 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2293 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2295 // Update Python script
2296 TPythonDump() << "isDone = " << this << "."
2297 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2298 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2299 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2300 << "SMESH.SMESH_MeshEditor."
2301 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2302 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2306 SMESH_CATCH( SMESH::throwCorbaException );
2310 //=============================================================================
2314 //=============================================================================
2317 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2318 const SMESH::long_array & IDsOfFixedNodes,
2319 CORBA::Long MaxNbOfIterations,
2320 CORBA::Double MaxAspectRatio,
2321 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2323 throw (SALOME::SALOME_Exception)
2328 TPythonDump aTPythonDump; // suppress dump in smooth()
2330 prepareIdSource( theObject );
2331 SMESH::long_array_var anElementsId = theObject->GetIDs();
2332 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2333 MaxAspectRatio, Method, IsParametric);
2335 // Update Python script
2336 aTPythonDump << "isDone = " << this << "."
2337 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2338 << theObject << ", " << IDsOfFixedNodes << ", "
2339 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2340 << "SMESH.SMESH_MeshEditor."
2341 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2342 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2346 SMESH_CATCH( SMESH::throwCorbaException );
2350 //=============================================================================
2354 //=============================================================================
2356 void SMESH_MeshEditor_i::RenumberNodes()
2357 throw (SALOME::SALOME_Exception)
2360 // Update Python script
2361 TPythonDump() << this << ".RenumberNodes()";
2363 getMeshDS()->Renumber( true );
2365 SMESH_CATCH( SMESH::throwCorbaException );
2368 //=============================================================================
2372 //=============================================================================
2374 void SMESH_MeshEditor_i::RenumberElements()
2375 throw (SALOME::SALOME_Exception)
2378 // Update Python script
2379 TPythonDump() << this << ".RenumberElements()";
2381 getMeshDS()->Renumber( false );
2383 SMESH_CATCH( SMESH::throwCorbaException );
2386 //=======================================================================
2388 * \brief Return groups by their IDs
2390 //=======================================================================
2392 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2393 throw (SALOME::SALOME_Exception)
2398 myMesh_i->CreateGroupServants();
2399 return myMesh_i->GetGroups( *groupIDs );
2401 SMESH_CATCH( SMESH::throwCorbaException );
2405 //=======================================================================
2406 //function : RotationSweepObjects
2408 //=======================================================================
2410 SMESH::ListOfGroups*
2411 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2412 const SMESH::ListOfIDSources & theEdges,
2413 const SMESH::ListOfIDSources & theFaces,
2414 const SMESH::AxisStruct & theAxis,
2415 CORBA::Double theAngleInRadians,
2416 CORBA::Long theNbOfSteps,
2417 CORBA::Double theTolerance,
2418 const bool theMakeGroups)
2419 throw (SALOME::SALOME_Exception)
2424 TIDSortedElemSet elemsNodes[2];
2425 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2426 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2427 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2429 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2430 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2431 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2432 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2434 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2435 bool makeWalls=true;
2436 if ( myIsPreviewMode )
2438 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2439 TPreviewMesh * tmpMesh = getPreviewMesh();
2440 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2441 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2442 workElements = & copyElements[0];
2443 //makeWalls = false; -- faces are needed for preview
2446 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2448 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2449 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2451 ::SMESH_MeshEditor::PGroupIDs groupIds =
2452 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2453 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2455 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2457 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2459 if ( !myIsPreviewMode )
2461 dumpGroupsList( aPythonDump, aGroups );
2462 aPythonDump << this<< ".RotationSweepObjects( "
2467 << TVar( theAngleInRadians ) << ", "
2468 << TVar( theNbOfSteps ) << ", "
2469 << TVar( theTolerance ) << ", "
2470 << theMakeGroups << " )";
2474 getPreviewMesh()->Remove( SMDSAbs_Volume );
2477 return aGroups ? aGroups : new SMESH::ListOfGroups;
2479 SMESH_CATCH( SMESH::throwCorbaException );
2483 namespace MeshEditor_I
2486 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2488 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2490 bool myIsExtrusionByNormal;
2492 static int makeFlags( CORBA::Boolean MakeGroups,
2493 CORBA::Boolean LinearVariation = false,
2494 CORBA::Boolean ByAverageNormal = false,
2495 CORBA::Boolean UseInputElemsOnly = false,
2496 CORBA::Long Flags = 0,
2497 CORBA::Boolean MakeBoundary = true )
2499 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2500 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2501 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2502 if ( LinearVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2503 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2507 ExtrusionParams(const SMESH::DirStruct & theDir,
2508 CORBA::Long theNbOfSteps,
2509 const SMESH::double_array & theScaleFactors,
2510 CORBA::Boolean theLinearVariation,
2511 const SMESH::double_array & theBasePoint,
2512 CORBA::Boolean theMakeGroups):
2513 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2517 toList( theScaleFactors ),
2518 TBasePoint( theBasePoint ),
2519 makeFlags( theMakeGroups, theLinearVariation )),
2520 myIsExtrusionByNormal( false )
2524 ExtrusionParams(const SMESH::DirStruct & theDir,
2525 CORBA::Long theNbOfSteps,
2526 CORBA::Boolean theMakeGroups,
2527 CORBA::Long theExtrFlags,
2528 CORBA::Double theSewTolerance):
2529 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2533 std::list<double>(),
2535 makeFlags( theMakeGroups, false, false, false,
2536 theExtrFlags, false ),
2538 myIsExtrusionByNormal( false )
2541 // params for extrusion by normal
2542 ExtrusionParams(CORBA::Double theStepSize,
2543 CORBA::Long theNbOfSteps,
2544 CORBA::Short theDim,
2545 CORBA::Boolean theByAverageNormal,
2546 CORBA::Boolean theUseInputElemsOnly,
2547 CORBA::Boolean theMakeGroups ):
2548 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2550 makeFlags( theMakeGroups, false,
2551 theByAverageNormal, theUseInputElemsOnly ),
2553 myIsExtrusionByNormal( true )
2559 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2564 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2566 std::list<double> scales;
2567 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2568 scales.push_back( theScaleFactors[i] );
2572 // structure used to convert SMESH::double_array to gp_XYZ*
2576 TBasePoint( const SMESH::double_array & theBasePoint )
2579 if ( theBasePoint.length() == 3 )
2581 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2585 operator const gp_XYZ*() const { return pp; }
2590 //=======================================================================
2592 * \brief Generate dim+1 elements by extrusion of elements along vector
2593 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2594 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2595 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2596 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2597 * \param [in] nbOfSteps - number of elements to generate from one element
2598 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2599 * corresponding to groups the input elements included in.
2600 * \return ListOfGroups - new groups created if \a toMakeGroups is true
2602 //=======================================================================
2604 SMESH::ListOfGroups*
2605 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2606 const SMESH::ListOfIDSources & theEdges,
2607 const SMESH::ListOfIDSources & theFaces,
2608 const SMESH::DirStruct & theStepVector,
2609 CORBA::Long theNbOfSteps,
2610 const SMESH::double_array & theScaleFactors,
2611 CORBA::Boolean theLinearVariation,
2612 const SMESH::double_array & theBasePoint,
2613 CORBA::Boolean theToMakeGroups)
2614 throw (SALOME::SALOME_Exception)
2619 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
2620 theLinearVariation, theBasePoint, theToMakeGroups );
2622 TIDSortedElemSet elemsNodes[2];
2623 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2624 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2625 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2627 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2628 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2629 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2630 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2632 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2633 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2634 if ( myIsPreviewMode )
2636 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2637 // previewType = SMDSAbs_Edge;
2639 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2640 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2641 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2642 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2643 workElements = & copyElements[0];
2645 params.SetNoGroups();
2647 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2649 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2650 ::SMESH_MeshEditor::PGroupIDs groupIds =
2651 getEditor().ExtrusionSweep( workElements, params, aHistory );
2653 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2655 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2657 if ( !myIsPreviewMode )
2659 dumpGroupsList( aPythonDump, aGroups );
2660 aPythonDump << this<< ".ExtrusionSweepObjects( "
2664 << theStepVector << ", "
2665 << TVar( theNbOfSteps ) << ", "
2666 << theToMakeGroups << " )";
2670 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2673 return aGroups ? aGroups : new SMESH::ListOfGroups;
2675 SMESH_CATCH( SMESH::throwCorbaException );
2679 //=======================================================================
2680 //function : ExtrusionByNormal
2682 //=======================================================================
2684 SMESH::ListOfGroups*
2685 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2686 CORBA::Double stepSize,
2687 CORBA::Long nbOfSteps,
2688 CORBA::Boolean byAverageNormal,
2689 CORBA::Boolean useInputElemsOnly,
2690 CORBA::Boolean makeGroups,
2692 throw (SALOME::SALOME_Exception)
2697 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2699 ExtrusionParams params( stepSize, nbOfSteps, dim,
2700 byAverageNormal, useInputElemsOnly, makeGroups );
2702 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2703 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2705 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2706 if (( elemTypes->length() == 1 ) &&
2707 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2708 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2711 TIDSortedElemSet elemsNodes[2];
2712 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2713 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2715 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2716 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2717 if ( myIsPreviewMode )
2719 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2720 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2721 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2722 workElements = & copyElements[0];
2724 params.SetNoGroups();
2727 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2728 ::SMESH_MeshEditor::PGroupIDs groupIds =
2729 getEditor().ExtrusionSweep( workElements, params, aHistory );
2731 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2733 if (!myIsPreviewMode) {
2734 dumpGroupsList(aPythonDump, aGroups);
2735 aPythonDump << this << ".ExtrusionByNormal( " << objects
2736 << ", " << TVar( stepSize )
2737 << ", " << TVar( nbOfSteps )
2738 << ", " << byAverageNormal
2739 << ", " << useInputElemsOnly
2740 << ", " << makeGroups
2746 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2749 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2751 return aGroups ? aGroups : new SMESH::ListOfGroups;
2753 SMESH_CATCH( SMESH::throwCorbaException );
2757 //=======================================================================
2758 //function : AdvancedExtrusion
2760 //=======================================================================
2762 SMESH::ListOfGroups*
2763 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2764 const SMESH::DirStruct & theStepVector,
2765 CORBA::Long theNbOfSteps,
2766 CORBA::Long theExtrFlags,
2767 CORBA::Double theSewTolerance,
2768 CORBA::Boolean theMakeGroups)
2769 throw (SALOME::SALOME_Exception)
2774 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2776 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2777 theExtrFlags, theSewTolerance );
2779 TIDSortedElemSet elemsNodes[2];
2780 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2782 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2783 ::SMESH_MeshEditor::PGroupIDs groupIds =
2784 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2786 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2788 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2790 if ( !myIsPreviewMode ) {
2791 dumpGroupsList(aPythonDump, aGroups);
2792 aPythonDump << this << ".AdvancedExtrusion( "
2793 << theIDsOfElements << ", "
2794 << theStepVector << ", "
2795 << theNbOfSteps << ", "
2796 << theExtrFlags << ", "
2797 << theSewTolerance << ", "
2798 << theMakeGroups << " )";
2802 getPreviewMesh()->Remove( SMDSAbs_Volume );
2805 return aGroups ? aGroups : new SMESH::ListOfGroups;
2807 SMESH_CATCH( SMESH::throwCorbaException );
2811 //================================================================================
2813 * \brief Convert extrusion error to IDL enum
2815 //================================================================================
2819 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2821 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2825 RETCASE( EXTR_NO_ELEMENTS );
2826 RETCASE( EXTR_PATH_NOT_EDGE );
2827 RETCASE( EXTR_BAD_PATH_SHAPE );
2828 RETCASE( EXTR_BAD_STARTING_NODE );
2829 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2830 RETCASE( EXTR_CANT_GET_TANGENT );
2832 return SMESH::SMESH_MeshEditor::EXTR_OK;
2836 //=======================================================================
2837 //function : extrusionAlongPath
2839 //=======================================================================
2840 SMESH::ListOfGroups*
2841 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2842 const SMESH::ListOfIDSources & theEdges,
2843 const SMESH::ListOfIDSources & theFaces,
2844 SMESH::SMESH_IDSource_ptr thePathMesh,
2845 GEOM::GEOM_Object_ptr thePathShape,
2846 CORBA::Long theNodeStart,
2847 CORBA::Boolean theHasAngles,
2848 const SMESH::double_array & theAngles,
2849 CORBA::Boolean theLinearVariation,
2850 CORBA::Boolean theHasRefPoint,
2851 const SMESH::PointStruct & theRefPoint,
2853 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2854 throw (SALOME::SALOME_Exception)
2859 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2861 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2862 if ( thePathMesh->_is_nil() )
2863 return aGroups._retn();
2866 SMESH_subMesh* aSubMesh = 0;
2867 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2868 if ( thePathShape->_is_nil() )
2870 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2871 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2873 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2874 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2875 if ( !aMeshImp ) return aGroups._retn();
2876 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2877 if ( !aSubMesh ) return aGroups._retn();
2879 else if ( !aMeshImp ||
2880 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2882 return aGroups._retn();
2887 if ( !aMeshImp ) return aGroups._retn();
2888 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2889 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2890 if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
2891 return aGroups._retn();
2894 SMDS_MeshNode* nodeStart =
2895 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2897 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2898 return aGroups._retn();
2901 TIDSortedElemSet elemsNodes[2];
2902 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2903 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2904 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2906 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2907 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2908 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2909 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2911 list<double> angles;
2912 for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) {
2913 angles.push_back( theAngles[i] );
2916 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2918 int nbOldGroups = myMesh->NbGroup();
2920 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2921 if ( myIsPreviewMode )
2923 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2924 TPreviewMesh * tmpMesh = getPreviewMesh();
2925 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2926 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2927 workElements = & copyElements[0];
2928 theMakeGroups = false;
2931 ::SMESH_MeshEditor::Extrusion_Error error;
2933 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2934 theHasAngles, angles, theLinearVariation,
2935 theHasRefPoint, refPnt, theMakeGroups );
2937 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2938 theHasAngles, angles, theLinearVariation,
2939 theHasRefPoint, refPnt, theMakeGroups );
2941 declareMeshModified( /*isReComputeSafe=*/true );
2942 theError = convExtrError( error );
2944 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2945 if ( theMakeGroups ) {
2946 list<int> groupIDs = myMesh->GetGroupIds();
2947 list<int>::iterator newBegin = groupIDs.begin();
2948 std::advance( newBegin, nbOldGroups ); // skip old groups
2949 groupIDs.erase( groupIDs.begin(), newBegin );
2950 aGroups = getGroups( & groupIDs );
2951 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2954 if ( !myIsPreviewMode ) {
2955 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2956 else aPythonDump << "(_noGroups, error) = ";
2957 aPythonDump << this << ".ExtrusionAlongPathObjects( "
2961 << thePathMesh << ", "
2962 << thePathShape << ", "
2963 << theNodeStart << ", "
2964 << theHasAngles << ", "
2965 << TVar( theAngles ) << ", "
2966 << theLinearVariation << ", "
2967 << theHasRefPoint << ", "
2968 << "SMESH.PointStruct( "
2969 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2970 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2971 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2972 << theMakeGroups << " )";
2976 getPreviewMesh()->Remove( SMDSAbs_Volume );
2979 return aGroups._retn();
2981 SMESH_CATCH( SMESH::throwCorbaException );
2985 //================================================================================
2987 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2988 * of given angles along path steps
2989 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2990 * which proceeds the extrusion
2991 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2992 * is used to define the sub-mesh for the path
2994 //================================================================================
2996 SMESH::double_array*
2997 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2998 GEOM::GEOM_Object_ptr thePathShape,
2999 const SMESH::double_array & theAngles)
3001 SMESH::double_array_var aResult = new SMESH::double_array();
3002 int nbAngles = theAngles.length();
3003 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3005 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3006 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3007 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3008 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3009 return aResult._retn();
3010 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3011 if ( nbSteps == nbAngles )
3013 aResult.inout() = theAngles;
3017 aResult->length( nbSteps );
3018 double rAn2St = double( nbAngles ) / double( nbSteps );
3019 double angPrev = 0, angle;
3020 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3022 double angCur = rAn2St * ( iSt+1 );
3023 double angCurFloor = floor( angCur );
3024 double angPrevFloor = floor( angPrev );
3025 if ( angPrevFloor == angCurFloor )
3026 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3029 int iP = int( angPrevFloor );
3030 double angPrevCeil = ceil(angPrev);
3031 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3033 int iC = int( angCurFloor );
3034 if ( iC < nbAngles )
3035 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3037 iP = int( angPrevCeil );
3039 angle += theAngles[ iC ];
3041 aResult[ iSt ] = angle;
3046 // Update Python script
3047 TPythonDump() << "rotAngles = " << theAngles;
3048 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3049 << thePathMesh << ", "
3050 << thePathShape << ", "
3053 return aResult._retn();
3056 //=======================================================================
3059 //=======================================================================
3061 SMESH::ListOfGroups*
3062 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3063 const SMESH::AxisStruct & theAxis,
3064 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3065 CORBA::Boolean theCopy,
3067 ::SMESH_Mesh* theTargetMesh)
3068 throw (SALOME::SALOME_Exception)
3073 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3074 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3076 if ( theTargetMesh )
3080 switch ( theMirrorType ) {
3081 case SMESH::SMESH_MeshEditor::POINT:
3082 aTrsf.SetMirror( P );
3084 case SMESH::SMESH_MeshEditor::AXIS:
3085 aTrsf.SetMirror( gp_Ax1( P, V ));
3088 aTrsf.SetMirror( gp_Ax2( P, V ));
3091 TIDSortedElemSet copyElements;
3092 TIDSortedElemSet* workElements = & theElements;
3094 if ( myIsPreviewMode )
3096 TPreviewMesh * tmpMesh = getPreviewMesh();
3097 tmpMesh->Copy( theElements, copyElements);
3098 if ( !theCopy && !theTargetMesh )
3100 TIDSortedElemSet elemsAround, elemsAroundCopy;
3101 getElementsAround( theElements, getMeshDS(), elemsAround );
3102 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3104 workElements = & copyElements;
3105 theMakeGroups = false;
3108 ::SMESH_MeshEditor::PGroupIDs groupIds =
3109 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3111 if ( !myIsPreviewMode )
3113 if ( theTargetMesh )
3114 theTargetMesh->GetMeshDS()->Modified();
3116 declareMeshModified( /*isReComputeSafe=*/false );
3119 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3121 SMESH_CATCH( SMESH::throwCorbaException );
3125 //=======================================================================
3128 //=======================================================================
3130 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3131 const SMESH::AxisStruct & theAxis,
3132 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3133 CORBA::Boolean theCopy)
3134 throw (SALOME::SALOME_Exception)
3136 if ( !myIsPreviewMode ) {
3137 TPythonDump() << this << ".Mirror( "
3138 << theIDsOfElements << ", "
3140 << mirrorTypeName(theMirrorType) << ", "
3143 if ( theIDsOfElements.length() > 0 )
3145 TIDSortedElemSet elements;
3146 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3147 mirror(elements, theAxis, theMirrorType, theCopy, false);
3152 //=======================================================================
3153 //function : MirrorObject
3155 //=======================================================================
3157 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3158 const SMESH::AxisStruct & theAxis,
3159 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3160 CORBA::Boolean theCopy)
3161 throw (SALOME::SALOME_Exception)
3163 if ( !myIsPreviewMode ) {
3164 TPythonDump() << this << ".MirrorObject( "
3165 << theObject << ", "
3167 << mirrorTypeName(theMirrorType) << ", "
3170 TIDSortedElemSet elements;
3172 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3174 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3175 mirror(elements, theAxis, theMirrorType, theCopy, false);
3178 //=======================================================================
3179 //function : MirrorMakeGroups
3181 //=======================================================================
3183 SMESH::ListOfGroups*
3184 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3185 const SMESH::AxisStruct& theMirror,
3186 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3187 throw (SALOME::SALOME_Exception)
3189 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3191 SMESH::ListOfGroups * aGroups = 0;
3192 if ( theIDsOfElements.length() > 0 )
3194 TIDSortedElemSet elements;
3195 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3196 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3198 if (!myIsPreviewMode) {
3199 dumpGroupsList(aPythonDump, aGroups);
3200 aPythonDump << this << ".MirrorMakeGroups( "
3201 << theIDsOfElements << ", "
3202 << theMirror << ", "
3203 << mirrorTypeName(theMirrorType) << " )";
3208 //=======================================================================
3209 //function : MirrorObjectMakeGroups
3211 //=======================================================================
3213 SMESH::ListOfGroups*
3214 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3215 const SMESH::AxisStruct& theMirror,
3216 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3217 throw (SALOME::SALOME_Exception)
3219 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3221 SMESH::ListOfGroups * aGroups = 0;
3222 TIDSortedElemSet elements;
3223 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3224 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3226 if (!myIsPreviewMode)
3228 dumpGroupsList(aPythonDump,aGroups);
3229 aPythonDump << this << ".MirrorObjectMakeGroups( "
3230 << theObject << ", "
3231 << theMirror << ", "
3232 << mirrorTypeName(theMirrorType) << " )";
3237 //=======================================================================
3238 //function : MirrorMakeMesh
3240 //=======================================================================
3242 SMESH::SMESH_Mesh_ptr
3243 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3244 const SMESH::AxisStruct& theMirror,
3245 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3246 CORBA::Boolean theCopyGroups,
3247 const char* theMeshName)
3248 throw (SALOME::SALOME_Exception)
3250 SMESH_Mesh_i* mesh_i;
3251 SMESH::SMESH_Mesh_var mesh;
3252 { // open new scope to dump "MakeMesh" command
3253 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3255 TPythonDump pydump; // to prevent dump at mesh creation
3257 mesh = makeMesh( theMeshName );
3258 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3259 if (mesh_i && theIDsOfElements.length() > 0 )
3261 TIDSortedElemSet elements;
3262 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3263 mirror(elements, theMirror, theMirrorType,
3264 false, theCopyGroups, & mesh_i->GetImpl());
3265 mesh_i->CreateGroupServants();
3268 if (!myIsPreviewMode) {
3269 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3270 << theIDsOfElements << ", "
3271 << theMirror << ", "
3272 << mirrorTypeName(theMirrorType) << ", "
3273 << theCopyGroups << ", '"
3274 << theMeshName << "' )";
3279 if (!myIsPreviewMode && mesh_i)
3280 mesh_i->GetGroups();
3282 return mesh._retn();
3285 //=======================================================================
3286 //function : MirrorObjectMakeMesh
3288 //=======================================================================
3290 SMESH::SMESH_Mesh_ptr
3291 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3292 const SMESH::AxisStruct& theMirror,
3293 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3294 CORBA::Boolean theCopyGroups,
3295 const char* theMeshName)
3296 throw (SALOME::SALOME_Exception)
3298 SMESH_Mesh_i* mesh_i;
3299 SMESH::SMESH_Mesh_var mesh;
3300 { // open new scope to dump "MakeMesh" command
3301 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3303 TPythonDump pydump; // to prevent dump at mesh creation
3305 mesh = makeMesh( theMeshName );
3306 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3307 TIDSortedElemSet elements;
3309 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3311 mirror(elements, theMirror, theMirrorType,
3312 false, theCopyGroups, & mesh_i->GetImpl());
3313 mesh_i->CreateGroupServants();
3315 if (!myIsPreviewMode) {
3316 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3317 << theObject << ", "
3318 << theMirror << ", "
3319 << mirrorTypeName(theMirrorType) << ", "
3320 << theCopyGroups << ", '"
3321 << theMeshName << "' )";
3326 if (!myIsPreviewMode && mesh_i)
3327 mesh_i->GetGroups();
3329 return mesh._retn();
3332 //=======================================================================
3333 //function : translate
3335 //=======================================================================
3337 SMESH::ListOfGroups*
3338 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3339 const SMESH::DirStruct & theVector,
3340 CORBA::Boolean theCopy,
3342 ::SMESH_Mesh* theTargetMesh)
3343 throw (SALOME::SALOME_Exception)
3348 if ( theTargetMesh )
3352 const SMESH::PointStruct * P = &theVector.PS;
3353 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3355 TIDSortedElemSet copyElements;
3356 TIDSortedElemSet* workElements = &theElements;
3358 if ( myIsPreviewMode )
3360 TPreviewMesh * tmpMesh = getPreviewMesh();
3361 tmpMesh->Copy( theElements, copyElements);
3362 if ( !theCopy && !theTargetMesh )
3364 TIDSortedElemSet elemsAround, elemsAroundCopy;
3365 getElementsAround( theElements, getMeshDS(), elemsAround );
3366 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3368 workElements = & copyElements;
3369 theMakeGroups = false;
3372 ::SMESH_MeshEditor::PGroupIDs groupIds =
3373 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3375 if ( !myIsPreviewMode )
3377 if ( theTargetMesh )
3378 theTargetMesh->GetMeshDS()->Modified();
3380 declareMeshModified( /*isReComputeSafe=*/false );
3383 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3385 SMESH_CATCH( SMESH::throwCorbaException );
3389 //=======================================================================
3390 //function : Translate
3392 //=======================================================================
3394 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3395 const SMESH::DirStruct & theVector,
3396 CORBA::Boolean theCopy)
3397 throw (SALOME::SALOME_Exception)
3399 if (!myIsPreviewMode) {
3400 TPythonDump() << this << ".Translate( "
3401 << theIDsOfElements << ", "
3402 << theVector << ", "
3405 if (theIDsOfElements.length()) {
3406 TIDSortedElemSet elements;
3407 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3408 translate(elements, theVector, theCopy, false);
3412 //=======================================================================
3413 //function : TranslateObject
3415 //=======================================================================
3417 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3418 const SMESH::DirStruct & theVector,
3419 CORBA::Boolean theCopy)
3420 throw (SALOME::SALOME_Exception)
3422 if (!myIsPreviewMode) {
3423 TPythonDump() << this << ".TranslateObject( "
3424 << theObject << ", "
3425 << theVector << ", "
3428 TIDSortedElemSet elements;
3430 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3432 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3433 translate(elements, theVector, theCopy, false);
3436 //=======================================================================
3437 //function : TranslateMakeGroups
3439 //=======================================================================
3441 SMESH::ListOfGroups*
3442 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3443 const SMESH::DirStruct& theVector)
3444 throw (SALOME::SALOME_Exception)
3446 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3448 SMESH::ListOfGroups * aGroups = 0;
3449 if (theIDsOfElements.length()) {
3450 TIDSortedElemSet elements;
3451 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3452 aGroups = translate(elements,theVector,true,true);
3454 if (!myIsPreviewMode) {
3455 dumpGroupsList(aPythonDump, aGroups);
3456 aPythonDump << this << ".TranslateMakeGroups( "
3457 << theIDsOfElements << ", "
3458 << theVector << " )";
3463 //=======================================================================
3464 //function : TranslateObjectMakeGroups
3466 //=======================================================================
3468 SMESH::ListOfGroups*
3469 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3470 const SMESH::DirStruct& theVector)
3471 throw (SALOME::SALOME_Exception)
3473 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3475 SMESH::ListOfGroups * aGroups = 0;
3476 TIDSortedElemSet elements;
3477 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3478 aGroups = translate(elements, theVector, true, true);
3480 if (!myIsPreviewMode) {
3481 dumpGroupsList(aPythonDump, aGroups);
3482 aPythonDump << this << ".TranslateObjectMakeGroups( "
3483 << theObject << ", "
3484 << theVector << " )";
3489 //=======================================================================
3490 //function : TranslateMakeMesh
3492 //=======================================================================
3494 SMESH::SMESH_Mesh_ptr
3495 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3496 const SMESH::DirStruct& theVector,
3497 CORBA::Boolean theCopyGroups,
3498 const char* theMeshName)
3499 throw (SALOME::SALOME_Exception)
3501 SMESH_Mesh_i* mesh_i;
3502 SMESH::SMESH_Mesh_var mesh;
3504 { // open new scope to dump "MakeMesh" command
3505 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3507 TPythonDump pydump; // to prevent dump at mesh creation
3509 mesh = makeMesh( theMeshName );
3510 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3512 if ( mesh_i && theIDsOfElements.length() )
3514 TIDSortedElemSet elements;
3515 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3516 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3517 mesh_i->CreateGroupServants();
3520 if ( !myIsPreviewMode ) {
3521 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3522 << theIDsOfElements << ", "
3523 << theVector << ", "
3524 << theCopyGroups << ", '"
3525 << theMeshName << "' )";
3530 if (!myIsPreviewMode && mesh_i)
3531 mesh_i->GetGroups();
3533 return mesh._retn();
3536 //=======================================================================
3537 //function : TranslateObjectMakeMesh
3539 //=======================================================================
3541 SMESH::SMESH_Mesh_ptr
3542 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3543 const SMESH::DirStruct& theVector,
3544 CORBA::Boolean theCopyGroups,
3545 const char* theMeshName)
3546 throw (SALOME::SALOME_Exception)
3549 SMESH_Mesh_i* mesh_i;
3550 SMESH::SMESH_Mesh_var mesh;
3551 { // open new scope to dump "MakeMesh" command
3552 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3554 TPythonDump pydump; // to prevent dump at mesh creation
3555 mesh = makeMesh( theMeshName );
3556 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3558 TIDSortedElemSet elements;
3560 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3562 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3563 mesh_i->CreateGroupServants();
3565 if ( !myIsPreviewMode ) {
3566 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3567 << theObject << ", "
3568 << theVector << ", "
3569 << theCopyGroups << ", '"
3570 << theMeshName << "' )";
3575 if (!myIsPreviewMode && mesh_i)
3576 mesh_i->GetGroups();
3578 return mesh._retn();
3580 SMESH_CATCH( SMESH::throwCorbaException );
3584 //=======================================================================
3587 //=======================================================================
3589 SMESH::ListOfGroups*
3590 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3591 const SMESH::AxisStruct & theAxis,
3592 CORBA::Double theAngle,
3593 CORBA::Boolean theCopy,
3595 ::SMESH_Mesh* theTargetMesh)
3596 throw (SALOME::SALOME_Exception)
3601 if ( theTargetMesh )
3604 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3605 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3608 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3610 TIDSortedElemSet copyElements;
3611 TIDSortedElemSet* workElements = &theElements;
3612 if ( myIsPreviewMode ) {
3613 TPreviewMesh * tmpMesh = getPreviewMesh();
3614 tmpMesh->Copy( theElements, copyElements );
3615 if ( !theCopy && !theTargetMesh )
3617 TIDSortedElemSet elemsAround, elemsAroundCopy;
3618 getElementsAround( theElements, getMeshDS(), elemsAround );
3619 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3621 workElements = ©Elements;
3622 theMakeGroups = false;
3625 ::SMESH_MeshEditor::PGroupIDs groupIds =
3626 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3628 if ( !myIsPreviewMode)
3630 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3631 else declareMeshModified( /*isReComputeSafe=*/false );
3634 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3636 SMESH_CATCH( SMESH::throwCorbaException );
3640 //=======================================================================
3643 //=======================================================================
3645 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3646 const SMESH::AxisStruct & theAxis,
3647 CORBA::Double theAngle,
3648 CORBA::Boolean theCopy)
3649 throw (SALOME::SALOME_Exception)
3651 if (!myIsPreviewMode) {
3652 TPythonDump() << this << ".Rotate( "
3653 << theIDsOfElements << ", "
3655 << TVar( theAngle ) << ", "
3658 if (theIDsOfElements.length() > 0)
3660 TIDSortedElemSet elements;
3661 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3662 rotate(elements,theAxis,theAngle,theCopy,false);
3666 //=======================================================================
3667 //function : RotateObject
3669 //=======================================================================
3671 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3672 const SMESH::AxisStruct & theAxis,
3673 CORBA::Double theAngle,
3674 CORBA::Boolean theCopy)
3675 throw (SALOME::SALOME_Exception)
3677 if ( !myIsPreviewMode ) {
3678 TPythonDump() << this << ".RotateObject( "
3679 << theObject << ", "
3681 << TVar( theAngle ) << ", "
3684 TIDSortedElemSet elements;
3685 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3686 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3687 rotate(elements,theAxis,theAngle,theCopy,false);
3690 //=======================================================================
3691 //function : RotateMakeGroups
3693 //=======================================================================
3695 SMESH::ListOfGroups*
3696 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3697 const SMESH::AxisStruct& theAxis,
3698 CORBA::Double theAngle)
3699 throw (SALOME::SALOME_Exception)
3701 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3703 SMESH::ListOfGroups * aGroups = 0;
3704 if (theIDsOfElements.length() > 0)
3706 TIDSortedElemSet elements;
3707 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3708 aGroups = rotate(elements,theAxis,theAngle,true,true);
3710 if (!myIsPreviewMode) {
3711 dumpGroupsList(aPythonDump, aGroups);
3712 aPythonDump << this << ".RotateMakeGroups( "
3713 << theIDsOfElements << ", "
3715 << TVar( theAngle ) << " )";
3720 //=======================================================================
3721 //function : RotateObjectMakeGroups
3723 //=======================================================================
3725 SMESH::ListOfGroups*
3726 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3727 const SMESH::AxisStruct& theAxis,
3728 CORBA::Double theAngle)
3729 throw (SALOME::SALOME_Exception)
3731 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3733 SMESH::ListOfGroups * aGroups = 0;
3734 TIDSortedElemSet elements;
3735 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3736 aGroups = rotate(elements, theAxis, theAngle, true, true);
3738 if (!myIsPreviewMode) {
3739 dumpGroupsList(aPythonDump, aGroups);
3740 aPythonDump << this << ".RotateObjectMakeGroups( "
3741 << theObject << ", "
3743 << TVar( theAngle ) << " )";
3748 //=======================================================================
3749 //function : RotateMakeMesh
3751 //=======================================================================
3753 SMESH::SMESH_Mesh_ptr
3754 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3755 const SMESH::AxisStruct& theAxis,
3756 CORBA::Double theAngleInRadians,
3757 CORBA::Boolean theCopyGroups,
3758 const char* theMeshName)
3759 throw (SALOME::SALOME_Exception)
3762 SMESH::SMESH_Mesh_var mesh;
3763 SMESH_Mesh_i* mesh_i;
3765 { // open new scope to dump "MakeMesh" command
3766 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3768 TPythonDump pydump; // to prevent dump at mesh creation
3770 mesh = makeMesh( theMeshName );
3771 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3773 if ( mesh_i && theIDsOfElements.length() > 0 )
3775 TIDSortedElemSet elements;
3776 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3777 rotate(elements, theAxis, theAngleInRadians,
3778 false, theCopyGroups, & mesh_i->GetImpl());
3779 mesh_i->CreateGroupServants();
3781 if ( !myIsPreviewMode ) {
3782 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3783 << theIDsOfElements << ", "
3785 << TVar( theAngleInRadians ) << ", "
3786 << theCopyGroups << ", '"
3787 << theMeshName << "' )";
3792 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3793 mesh_i->GetGroups();
3795 return mesh._retn();
3797 SMESH_CATCH( SMESH::throwCorbaException );
3801 //=======================================================================
3802 //function : RotateObjectMakeMesh
3804 //=======================================================================
3806 SMESH::SMESH_Mesh_ptr
3807 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3808 const SMESH::AxisStruct& theAxis,
3809 CORBA::Double theAngleInRadians,
3810 CORBA::Boolean theCopyGroups,
3811 const char* theMeshName)
3812 throw (SALOME::SALOME_Exception)
3815 SMESH::SMESH_Mesh_var mesh;
3816 SMESH_Mesh_i* mesh_i;
3818 {// open new scope to dump "MakeMesh" command
3819 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3821 TPythonDump pydump; // to prevent dump at mesh creation
3822 mesh = makeMesh( theMeshName );
3823 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3825 TIDSortedElemSet elements;
3827 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3829 rotate(elements, theAxis, theAngleInRadians,
3830 false, theCopyGroups, & mesh_i->GetImpl());
3831 mesh_i->CreateGroupServants();
3833 if ( !myIsPreviewMode ) {
3834 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3835 << theObject << ", "
3837 << TVar( theAngleInRadians ) << ", "
3838 << theCopyGroups << ", '"
3839 << theMeshName << "' )";
3844 if (!myIsPreviewMode && mesh_i)
3845 mesh_i->GetGroups();
3847 return mesh._retn();
3849 SMESH_CATCH( SMESH::throwCorbaException );
3853 //=======================================================================
3856 //=======================================================================
3858 SMESH::ListOfGroups*
3859 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3860 const SMESH::PointStruct& thePoint,
3861 const SMESH::double_array& theScaleFact,
3862 CORBA::Boolean theCopy,
3864 ::SMESH_Mesh* theTargetMesh)
3865 throw (SALOME::SALOME_Exception)
3869 if ( theScaleFact.length() < 1 )
3870 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3871 if ( theScaleFact.length() == 2 )
3872 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3874 if ( theTargetMesh )
3877 TIDSortedElemSet elements;
3878 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3879 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3884 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3885 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3889 // fight against orthogonalization
3890 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3891 // 0, S[1], 0, thePoint.y * (1-S[1]),
3892 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3893 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3894 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3895 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3896 loc.SetCoord( thePoint.x * (1-S[0]),
3897 thePoint.y * (1-S[1]),
3898 thePoint.z * (1-S[2]));
3899 M.SetDiagonal( S[0], S[1], S[2] );
3901 TIDSortedElemSet copyElements;
3902 TIDSortedElemSet* workElements = &elements;
3903 if ( myIsPreviewMode )
3905 TPreviewMesh * tmpMesh = getPreviewMesh();
3906 tmpMesh->Copy( elements, copyElements);
3907 if ( !theCopy && !theTargetMesh )
3909 TIDSortedElemSet elemsAround, elemsAroundCopy;
3910 getElementsAround( elements, getMeshDS(), elemsAround );
3911 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3913 workElements = & copyElements;
3914 theMakeGroups = false;
3917 ::SMESH_MeshEditor::PGroupIDs groupIds =
3918 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3920 if ( !myIsPreviewMode )
3922 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3923 else declareMeshModified( /*isReComputeSafe=*/false );
3925 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3927 SMESH_CATCH( SMESH::throwCorbaException );
3931 //=======================================================================
3934 //=======================================================================
3936 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3937 const SMESH::PointStruct& thePoint,
3938 const SMESH::double_array& theScaleFact,
3939 CORBA::Boolean theCopy)
3940 throw (SALOME::SALOME_Exception)
3942 if ( !myIsPreviewMode ) {
3943 TPythonDump() << this << ".Scale( "
3944 << theObject << ", "
3946 << TVar( theScaleFact ) << ", "
3949 scale(theObject, thePoint, theScaleFact, theCopy, false);
3953 //=======================================================================
3954 //function : ScaleMakeGroups
3956 //=======================================================================
3958 SMESH::ListOfGroups*
3959 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3960 const SMESH::PointStruct& thePoint,
3961 const SMESH::double_array& theScaleFact)
3962 throw (SALOME::SALOME_Exception)
3964 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3966 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3967 if (!myIsPreviewMode) {
3968 dumpGroupsList(aPythonDump, aGroups);
3969 aPythonDump << this << ".Scale("
3972 << TVar( theScaleFact ) << ",True,True)";
3978 //=======================================================================
3979 //function : ScaleMakeMesh
3981 //=======================================================================
3983 SMESH::SMESH_Mesh_ptr
3984 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3985 const SMESH::PointStruct& thePoint,
3986 const SMESH::double_array& theScaleFact,
3987 CORBA::Boolean theCopyGroups,
3988 const char* theMeshName)
3989 throw (SALOME::SALOME_Exception)
3991 SMESH_Mesh_i* mesh_i;
3992 SMESH::SMESH_Mesh_var mesh;
3993 { // open new scope to dump "MakeMesh" command
3994 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3996 TPythonDump pydump; // to prevent dump at mesh creation
3997 mesh = makeMesh( theMeshName );
3998 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4002 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4003 mesh_i->CreateGroupServants();
4005 if ( !myIsPreviewMode )
4006 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4007 << theObject << ", "
4009 << TVar( theScaleFact ) << ", "
4010 << theCopyGroups << ", '"
4011 << theMeshName << "' )";
4015 if (!myIsPreviewMode && mesh_i)
4016 mesh_i->GetGroups();
4018 return mesh._retn();
4021 //================================================================================
4023 * \brief Make an offset mesh from a source 2D mesh
4024 * \param [inout] theObject - source mesh. New elements are added to this mesh
4025 * if \a theMeshName is empty.
4026 * \param [in] theValue - offset value
4027 * \param [in] theCopyGroups - to generate groups
4028 * \param [in] theMeshName - optional name of a new mesh
4029 * \param [out] theGroups - new groups
4030 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
4032 //================================================================================
4034 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4035 CORBA::Double theValue,
4036 CORBA::Boolean theCopyGroups,
4037 CORBA::Boolean theCopyElements,
4038 const char* theMeshName,
4039 SMESH::ListOfGroups_out theGroups)
4040 throw (SALOME::SALOME_Exception)
4045 SMESHDS_Mesh* aMeshDS = getMeshDS();
4047 SMESH::SMESH_Mesh_var mesh_var;
4048 ::SMESH_MeshEditor::PGroupIDs groupIds;
4052 TIDSortedElemSet elements, copyElements;
4053 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4054 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4057 SMESH_Mesh* tgtMesh = 0;
4058 if ( myIsPreviewMode )
4060 TPreviewMesh * tmpMesh = getPreviewMesh();
4062 tmpMesh->Copy( elements, copyElements );
4063 elements.swap( copyElements );
4064 theCopyGroups = false;
4065 theCopyElements = false;
4070 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4071 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4072 tgtMesh = & mesh_i->GetImpl();
4074 groupIds = getEditor().Offset( elements, theValue, tgtMesh,
4075 theCopyGroups, theCopyElements, !myIsPreviewMode );
4077 tgtMesh->GetMeshDS()->Modified();
4080 if ( myIsPreviewMode )
4082 //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4086 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4088 if ( *theMeshName && mesh_var->NbFaces() == 0 )
4090 // new mesh empty, remove it
4091 SALOMEDS::Study_var study = SMESH_Gen_i::getStudyServant();
4092 SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
4093 SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::ObjectToSObject( mesh_var );
4094 builder->RemoveObjectWithChildren( meshSO );
4095 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4098 // result of Offset() is a tuple (mesh, groups)
4099 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4100 else pyDump << mesh_var << ", ";
4101 pyDump << theGroups << " = " << this << ".Offset( "
4102 << theObject << ", "
4104 << theCopyGroups << ", "
4105 << theCopyElements << ", "
4106 << "'" << theMeshName<< "')";
4109 return mesh_var._retn();
4111 SMESH_CATCH( SMESH::throwCorbaException );
4112 return SMESH::SMESH_Mesh::_nil();
4115 //=======================================================================
4116 //function : findCoincidentNodes
4118 //=======================================================================
4120 void SMESH_MeshEditor_i::
4121 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4122 CORBA::Double Tolerance,
4123 SMESH::array_of_long_array_out GroupsOfNodes,
4124 CORBA::Boolean SeparateCornersAndMedium)
4126 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4127 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4129 GroupsOfNodes = new SMESH::array_of_long_array;
4130 GroupsOfNodes->length( aListOfListOfNodes.size() );
4131 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4132 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4134 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4135 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4136 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4137 aGroup.length( aListOfNodes.size() );
4138 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4139 aGroup[ j ] = (*lIt)->GetID();
4143 //=======================================================================
4144 //function : FindCoincidentNodes
4146 //=======================================================================
4148 void SMESH_MeshEditor_i::
4149 FindCoincidentNodes (CORBA::Double Tolerance,
4150 SMESH::array_of_long_array_out GroupsOfNodes,
4151 CORBA::Boolean SeparateCornersAndMedium)
4152 throw (SALOME::SALOME_Exception)
4157 TIDSortedNodeSet nodes; // no input nodes
4158 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4160 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4161 << Tolerance << ", "
4162 << SeparateCornersAndMedium << " )";
4164 SMESH_CATCH( SMESH::throwCorbaException );
4167 //=======================================================================
4168 //function : FindCoincidentNodesOnPart
4170 //=======================================================================
4172 void SMESH_MeshEditor_i::
4173 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4174 CORBA::Double Tolerance,
4175 SMESH::array_of_long_array_out GroupsOfNodes,
4176 CORBA::Boolean SeparateCornersAndMedium)
4177 throw (SALOME::SALOME_Exception)
4182 TIDSortedNodeSet nodes;
4183 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4185 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4187 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4189 << Tolerance << ", "
4190 << SeparateCornersAndMedium << " )";
4192 SMESH_CATCH( SMESH::throwCorbaException );
4195 //================================================================================
4197 * \brief Finds nodes coincident with Tolerance within Object excluding nodes within
4198 * ExceptSubMeshOrGroups
4200 //================================================================================
4202 void SMESH_MeshEditor_i::
4203 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4204 CORBA::Double theTolerance,
4205 SMESH::array_of_long_array_out theGroupsOfNodes,
4206 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4207 CORBA::Boolean theSeparateCornersAndMedium)
4208 throw (SALOME::SALOME_Exception)
4213 TIDSortedNodeSet nodes;
4214 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4216 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4218 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4220 while ( nodeIt->more() )
4221 nodes.erase( cast2Node( nodeIt->next() ));
4223 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4225 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4227 << theTolerance << ", "
4228 << theExceptSubMeshOrGroups << ", "
4229 << theSeparateCornersAndMedium << " )";
4231 SMESH_CATCH( SMESH::throwCorbaException );
4234 //=======================================================================
4235 //function : MergeNodes
4237 //=======================================================================
4239 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4240 const SMESH::ListOfIDSources& NodesToKeep,
4241 CORBA::Boolean AvoidMakingHoles)
4242 throw (SALOME::SALOME_Exception)
4247 SMESHDS_Mesh* aMesh = getMeshDS();
4249 TPythonDump aTPythonDump;
4250 aTPythonDump << this << ".MergeNodes([";
4252 TIDSortedNodeSet setOfNodesToKeep;
4253 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4255 prepareIdSource( NodesToKeep[i] );
4256 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
4257 while ( nodeIt->more() )
4258 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4261 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4262 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4264 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4265 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4266 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4267 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4269 CORBA::Long index = aNodeGroup[ j ];
4270 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4272 if ( setOfNodesToKeep.count( node ))
4273 aListOfNodes.push_front( node );
4275 aListOfNodes.push_back( node );
4278 if ( aListOfNodes.size() < 2 )
4279 aListOfListOfNodes.pop_back();
4281 if ( i > 0 ) aTPythonDump << ", ";
4282 aTPythonDump << aNodeGroup;
4285 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4287 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4289 declareMeshModified( /*isReComputeSafe=*/false );
4291 SMESH_CATCH( SMESH::throwCorbaException );
4294 //=======================================================================
4295 //function : FindEqualElements
4297 //=======================================================================
4299 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4300 SMESH::array_of_long_array_out GroupsOfElementsID)
4301 throw (SALOME::SALOME_Exception)
4306 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4307 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4309 TIDSortedElemSet elems;
4310 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4312 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4313 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4315 GroupsOfElementsID = new SMESH::array_of_long_array;
4316 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4318 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4319 aListOfListOfElementsID.begin();
4320 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4322 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4323 list<int>& listOfIDs = *arraysIt;
4324 aGroup.length( listOfIDs.size() );
4325 list<int>::iterator idIt = listOfIDs.begin();
4326 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4327 aGroup[ k ] = *idIt;
4330 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4334 SMESH_CATCH( SMESH::throwCorbaException );
4337 //=======================================================================
4338 //function : MergeElements
4340 //=======================================================================
4342 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4343 throw (SALOME::SALOME_Exception)
4348 TPythonDump aTPythonDump;
4349 aTPythonDump << this << ".MergeElements( [";
4351 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4353 for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) {
4354 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4355 aListOfListOfElementsID.push_back( list< int >() );
4356 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4357 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) {
4358 CORBA::Long id = anElemsIDGroup[ j ];
4359 aListOfElemsID.push_back( id );
4361 if ( aListOfElemsID.size() < 2 )
4362 aListOfListOfElementsID.pop_back();
4363 if ( i > 0 ) aTPythonDump << ", ";
4364 aTPythonDump << anElemsIDGroup;
4367 getEditor().MergeElements(aListOfListOfElementsID);
4369 declareMeshModified( /*isReComputeSafe=*/true );
4371 aTPythonDump << "] )";
4373 SMESH_CATCH( SMESH::throwCorbaException );
4376 //=======================================================================
4377 //function : MergeEqualElements
4379 //=======================================================================
4381 void SMESH_MeshEditor_i::MergeEqualElements()
4382 throw (SALOME::SALOME_Exception)
4387 getEditor().MergeEqualElements();
4389 declareMeshModified( /*isReComputeSafe=*/true );
4391 TPythonDump() << this << ".MergeEqualElements()";
4393 SMESH_CATCH( SMESH::throwCorbaException );
4396 //=============================================================================
4398 * Move the node to a given point
4400 //=============================================================================
4402 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4406 throw (SALOME::SALOME_Exception)
4409 initData(/*deleteSearchers=*/false);
4411 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4415 if ( theNodeSearcher )
4416 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4418 if ( myIsPreviewMode ) // make preview data
4420 // in a preview mesh, make edges linked to a node
4421 TPreviewMesh& tmpMesh = *getPreviewMesh();
4422 TIDSortedElemSet linkedNodes;
4423 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4424 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4425 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4426 for ( ; nIt != linkedNodes.end(); ++nIt )
4428 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4429 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4433 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4434 // fill preview data
4436 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4437 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4439 getMeshDS()->MoveNode(node, x, y, z);
4441 if ( !myIsPreviewMode )
4443 // Update Python script
4444 TPythonDump() << "isDone = " << this << ".MoveNode( "
4445 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4446 declareMeshModified( /*isReComputeSafe=*/false );
4449 SMESH_CATCH( SMESH::throwCorbaException );
4454 //================================================================================
4456 * \brief Return ID of node closest to a given point
4458 //================================================================================
4460 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4463 throw (SALOME::SALOME_Exception)
4466 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4468 if ( !theNodeSearcher ) {
4469 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4472 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4473 return node->GetID();
4475 SMESH_CATCH( SMESH::throwCorbaException );
4479 //================================================================================
4481 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4482 * move the node closest to the point to point's location and return ID of the node
4484 //================================================================================
4486 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4489 CORBA::Long theNodeID)
4490 throw (SALOME::SALOME_Exception)
4493 // We keep theNodeSearcher until any mesh modification:
4494 // 1) initData() deletes theNodeSearcher at any edition,
4495 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4497 initData(/*deleteSearchers=*/false);
4499 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4501 int nodeID = theNodeID;
4502 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4503 if ( !node ) // preview moving node
4505 if ( !theNodeSearcher ) {
4506 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4509 node = theNodeSearcher->FindClosestTo( p );
4512 nodeID = node->GetID();
4513 if ( myIsPreviewMode ) // make preview data
4515 // in a preview mesh, make edges linked to a node
4516 TPreviewMesh tmpMesh = *getPreviewMesh();
4517 TIDSortedElemSet linkedNodes;
4518 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4519 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4520 for ( ; nIt != linkedNodes.end(); ++nIt )
4522 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4523 tmpMesh.Copy( &edge );
4526 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4528 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4529 // fill preview data
4531 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4533 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4537 getMeshDS()->MoveNode(node, x, y, z);
4541 if ( !myIsPreviewMode )
4543 TPythonDump() << "nodeID = " << this
4544 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4545 << ", " << nodeID << " )";
4547 declareMeshModified( /*isReComputeSafe=*/false );
4552 SMESH_CATCH( SMESH::throwCorbaException );
4556 //=======================================================================
4558 * Return elements of given type where the given point is IN or ON.
4560 * 'ALL' type means elements of any type excluding nodes
4562 //=======================================================================
4564 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4567 SMESH::ElementType type)
4568 throw (SALOME::SALOME_Exception)
4571 SMESH::long_array_var res = new SMESH::long_array;
4572 vector< const SMDS_MeshElement* > foundElems;
4574 theSearchersDeleter.Set( myMesh );
4575 if ( !theElementSearcher ) {
4576 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4578 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4579 SMDSAbs_ElementType( type ),
4581 res->length( foundElems.size() );
4582 for ( size_t i = 0; i < foundElems.size(); ++i )
4583 res[i] = foundElems[i]->GetID();
4587 SMESH_CATCH( SMESH::throwCorbaException );
4591 //=======================================================================
4592 //function : FindAmongElementsByPoint
4593 //purpose : Searching among the given elements, return elements of given type
4594 // where the given point is IN or ON.
4595 // 'ALL' type means elements of any type excluding nodes
4596 //=======================================================================
4599 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4603 SMESH::ElementType type)
4604 throw (SALOME::SALOME_Exception)
4607 SMESH::long_array_var res = new SMESH::long_array;
4609 if ( type != SMESH::NODE )
4611 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4612 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4613 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4614 type != types[0] ) // but search of elements of dim > 0
4617 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4618 return FindElementsByPoint( x,y,z, type );
4620 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4622 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4623 if ( !theElementSearcher )
4625 // create a searcher from elementIDs
4626 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4627 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4629 if ( !idSourceToSet( elementIDs, meshDS, elements,
4630 ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ),
4631 /*emptyIfIsMesh=*/true))
4634 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4635 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4637 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4640 vector< const SMDS_MeshElement* > foundElems;
4642 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4643 SMDSAbs_ElementType( type ),
4645 res->length( foundElems.size() );
4646 for ( size_t i = 0; i < foundElems.size(); ++i )
4647 res[i] = foundElems[i]->GetID();
4651 SMESH_CATCH( SMESH::throwCorbaException );
4655 //=======================================================================
4656 //function : ProjectPoint
4657 //purpose : Project a point to a mesh object.
4658 // Return ID of an element of given type where the given point is projected
4659 // and coordinates of the projection point.
4660 // In the case if nothing found, return -1 and []
4661 //=======================================================================
4663 CORBA::Long SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
4666 SMESH::SMESH_IDSource_ptr meshObject,
4667 SMESH::ElementType type,
4668 SMESH::double_array_out projecton)
4669 throw (SALOME::SALOME_Exception)
4671 if ( CORBA::is_nil( meshObject ))
4672 THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
4676 SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
4677 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4678 if ( mesh_i != myMesh_i )
4680 SMESH::SMESH_MeshEditor_var editor=
4681 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4682 return editor->ProjectPoint( x,y,z, meshObject, type, projecton );
4686 theSearchersDeleter.Set( myMesh, getPartIOR( meshObject ));
4687 if ( !theElementSearcher )
4689 // create a searcher from meshObject
4691 SMDS_ElemIteratorPtr elemIt;
4692 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
4693 elemIt = myMesh_i->GetElements( meshObject, type );
4695 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4698 const SMDS_MeshElement* elem = 0;
4699 gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
4700 SMDSAbs_ElementType( type ),
4703 projecton = new SMESH::double_array();
4704 if ( elem && !elem->IsNull() )
4706 projecton->length( 3 );
4707 projecton[0] = pProj.X();
4708 projecton[1] = pProj.Y();
4709 projecton[2] = pProj.Z();
4710 return elem->GetID();
4713 SMESH_CATCH( SMESH::throwCorbaException );
4717 //=======================================================================
4718 //function : GetPointState
4719 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4720 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4721 //=======================================================================
4723 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4726 throw (SALOME::SALOME_Exception)
4729 theSearchersDeleter.Set( myMesh );
4730 if ( !theElementSearcher ) {
4731 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4733 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4735 SMESH_CATCH( SMESH::throwCorbaException );
4739 //=======================================================================
4740 //function : IsManifold
4741 //purpose : Check if a 2D mesh is manifold
4742 //=======================================================================
4744 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4745 throw (SALOME::SALOME_Exception)
4747 bool isManifold = true;
4750 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4751 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4753 /*closedOnly=*/true,
4755 SMESH_CATCH( SMESH::throwCorbaException );
4760 //=======================================================================
4761 //function : IsCoherentOrientation2D
4762 //purpose : Check if orientation of 2D elements is coherent
4763 //=======================================================================
4765 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4766 throw (SALOME::SALOME_Exception)
4768 bool isGoodOri = true;
4771 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4772 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4774 /*closedOnly=*/true,
4777 SMESH_CATCH( SMESH::throwCorbaException );
4782 //=======================================================================
4783 //function : FindSharpEdges
4784 //purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
4785 //=======================================================================
4787 SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
4788 CORBA::Boolean theAddExisting)
4789 throw (SALOME::SALOME_Exception)
4791 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
4796 std::vector< SMESH_MeshAlgos::Edge > edges =
4797 SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
4799 if ( myIsPreviewMode ) // fill a preview mesh with edges
4801 TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
4802 SMDS_Mesh* meshDS = mesh->GetMeshDS();
4803 for ( size_t i = 0; i < edges.size(); ++i )
4805 SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
4806 SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4807 SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
4808 if ( edges[i]._medium )
4810 xyz1.Set( edges[i]._medium );
4811 SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4812 mesh->GetMeshDS()->AddEdge( n1, n2, nm );
4816 mesh->GetMeshDS()->AddEdge( n1, n2 );
4822 resultEdges->length( edges.size() );
4823 for ( size_t i = 0; i < edges.size(); ++i )
4825 resultEdges[ i ].node1 = edges[i]._node1->GetID();
4826 resultEdges[ i ].node2 = edges[i]._node2->GetID();
4827 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
4830 SMESH_CATCH( SMESH::throwCorbaException );
4831 return resultEdges._retn();
4834 //=======================================================================
4835 //function : FindFreeBorders
4836 //purpose : Returns all or only closed FreeBorder's.
4837 //=======================================================================
4839 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4840 throw (SALOME::SALOME_Exception)
4842 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4845 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4846 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4848 resBorders->length( foundFreeBordes.size() );
4849 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
4851 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
4852 SMESH::FreeBorder& bordOut = resBorders[i];
4853 bordOut.nodeIDs.length( bordNodes.size() );
4854 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
4855 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
4858 SMESH_CATCH( SMESH::throwCorbaException );
4860 return resBorders._retn();
4863 //=======================================================================
4864 //function : FillHole
4865 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
4866 //=======================================================================
4868 SMESH::SMESH_Group_ptr
4869 SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole,
4870 const char* theGroupName)
4871 throw (SALOME::SALOME_Exception)
4875 if ( theHole.nodeIDs.length() < 4 )
4876 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
4877 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
4878 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
4879 "First and last nodes must be same", SALOME::BAD_PARAM);
4881 SMESH_MeshAlgos::TFreeBorder bordNodes;
4882 bordNodes.resize( theHole.nodeIDs.length() );
4883 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
4885 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
4886 if ( !bordNodes[ iN ] )
4887 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
4888 << " does not exist", SALOME::BAD_PARAM);
4893 // prepare a preview mesh
4894 MeshEditor_I::TPreviewMesh* previewMesh = 0;
4895 SMDS_Mesh* meshDS = getMeshDS();
4896 if ( myIsPreviewMode )
4898 // copy faces sharing nodes of theHole
4899 TIDSortedElemSet holeFaces;
4900 previewMesh = getPreviewMesh( SMDSAbs_Face );
4901 for ( size_t i = 0; i < bordNodes.size(); ++i )
4903 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
4904 while ( fIt->more() )
4906 const SMDS_MeshElement* face = fIt->next();
4907 if ( holeFaces.insert( face ).second )
4908 previewMesh->Copy( face );
4910 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
4911 ASSERT( bordNodes[i] );
4913 meshDS = previewMesh->GetMeshDS();
4917 std::vector<const SMDS_MeshElement*> newFaces;
4918 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
4920 if ( myIsPreviewMode )
4923 previewMesh->Clear();
4924 for ( size_t i = 0; i < newFaces.size(); ++i )
4925 previewMesh->Copy( newFaces[i] );
4929 // return new faces via a group
4930 SMESH::SMESH_Group_var group;
4931 if ( theGroupName && theGroupName[0] && !newFaces.empty() )
4933 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4934 for ( CORBA::ULong i = 0; i < groups->length(); ++i )
4936 SMESH::SMESH_GroupBase_var g = groups[ i ];
4937 if ( g->GetType() != SMESH::FACE ) continue;
4938 SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g );
4939 if ( standalone->_is_nil() ) continue;
4940 CORBA::String_var name = g->GetName();
4941 if ( strcmp( theGroupName, name.in() ) == 0 )
4947 if ( group->_is_nil() )
4948 group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName );
4950 if ( !group->_is_nil() )
4952 SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group );
4953 SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() );
4954 for ( size_t i = 0; i < newFaces.size(); ++i )
4955 grpDS->Add( newFaces[ i ]);
4960 getEditor().ClearLastCreated();
4961 SMESH_SequenceOfElemPtr& aSeq =
4962 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
4963 aSeq.swap( newFaces );
4966 if ( group->_is_nil() ) pyDump << "_group = ";
4967 else pyDump << group << " = ";
4968 pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
4970 return group._retn();
4973 SMESH_CATCH( SMESH::throwCorbaException );
4975 return SMESH::SMESH_Group::_nil();
4978 //=======================================================================
4979 //function : convError
4981 //=======================================================================
4983 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4985 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4989 RETCASE( SEW_BORDER1_NOT_FOUND );
4990 RETCASE( SEW_BORDER2_NOT_FOUND );
4991 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4992 RETCASE( SEW_BAD_SIDE_NODES );
4993 RETCASE( SEW_VOLUMES_TO_SPLIT );
4994 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4995 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4996 RETCASE( SEW_BAD_SIDE1_NODES );
4997 RETCASE( SEW_BAD_SIDE2_NODES );
4998 RETCASE( SEW_INTERNAL_ERROR );
5000 return SMESH::SMESH_MeshEditor::SEW_OK;
5003 //=======================================================================
5005 * Returns groups of FreeBorder's coincident within the given tolerance.
5006 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
5007 * to free borders being compared is used.
5009 //=======================================================================
5011 SMESH::CoincidentFreeBorders*
5012 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
5014 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
5018 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
5019 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
5021 // copy free borders
5022 aCFB->borders.length( cfb._borders.size() );
5023 for ( size_t i = 0; i < cfb._borders.size(); ++i )
5025 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
5026 SMESH::FreeBorder& aBRD = aCFB->borders[i];
5027 aBRD.nodeIDs.length( nodes.size() );
5028 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5029 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
5032 // copy coincident parts
5033 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
5034 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
5036 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
5037 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
5038 aGRP.length( grp.size() );
5039 for ( size_t iP = 0; iP < grp.size(); ++iP )
5041 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
5042 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5043 aPART.border = part._border;
5044 aPART.node1 = part._node1;
5045 aPART.node2 = part._node2;
5046 aPART.nodeLast = part._nodeLast;
5049 SMESH_CATCH( SMESH::doNothing );
5051 TPythonDump() << "CoincidentFreeBorders = "
5052 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
5054 return aCFB._retn();
5057 //=======================================================================
5059 * Sew FreeBorder's of each group
5061 //=======================================================================
5063 CORBA::Short SMESH_MeshEditor_i::
5064 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
5065 CORBA::Boolean createPolygons,
5066 CORBA::Boolean createPolyhedra)
5067 throw (SALOME::SALOME_Exception)
5069 CORBA::Short nbSewed = 0;
5071 SMESH_MeshAlgos::TFreeBorderVec groups;
5072 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
5074 // check the input and collect nodes
5075 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
5077 borderNodes.clear();
5078 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
5079 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
5081 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5082 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
5083 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
5085 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
5087 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
5088 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
5089 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
5090 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
5091 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
5092 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5094 // do not keep these nodes for further sewing as nodes can be removed by the sewing
5095 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
5096 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
5097 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
5099 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
5101 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
5103 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5105 borderNodes.push_back( n1 );
5106 borderNodes.push_back( n2 );
5107 borderNodes.push_back( n3 );
5109 groups.push_back( borderNodes );
5112 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
5113 // to get nodes that replace other nodes during merge we create 0D elements
5114 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
5117 vector< const SMDS_MeshElement* > tmp0Delems;
5118 for ( size_t i = 0; i < groups.size(); ++i )
5120 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5121 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5123 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
5125 tmp0Delems.push_back( it0D->next() );
5127 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
5131 // cout << endl << "INIT" << endl;
5132 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5134 // cout << i << " ";
5135 // if ( i % 3 == 0 ) cout << "^ ";
5136 // tmp0Delems[i]->GetNode(0)->Print( cout );
5141 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
5143 for ( size_t i = 0; i < groups.size(); ++i )
5145 bool isBordToBord = true;
5146 bool groupSewed = false;
5147 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5148 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
5150 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
5151 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
5152 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
5154 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
5155 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
5156 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
5158 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
5161 // TIDSortedElemSet emptySet, avoidSet;
5162 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
5164 // cout << "WRONG 2nd 1" << endl;
5165 // n0->Print( cout );
5166 // n1->Print( cout );
5168 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
5170 // cout << "WRONG 2nd 2" << endl;
5171 // n3->Print( cout );
5172 // n4->Print( cout );
5175 if ( !isBordToBord )
5177 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5178 n2 = 0; // and n2 is not used
5180 // 1st border moves to 2nd
5181 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5183 /*2ndIsFreeBorder=*/ isBordToBord,
5184 createPolygons, createPolyhedra);
5185 groupSewed = ( res == ok );
5187 isBordToBord = false;
5188 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5189 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5191 // cout << t << " ";
5192 // if ( t % 3 == 0 ) cout << "^ ";
5193 // tmp0Delems[t]->GetNode(0)->Print( cout );
5196 i0D += nodes.size();
5197 nbSewed += groupSewed;
5200 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5201 << freeBorders << ", "
5202 << createPolygons << ", "
5203 << createPolyhedra << " )";
5205 SMESH_CATCH( SMESH::doNothing );
5207 declareMeshModified( /*isReComputeSafe=*/false );
5209 // remove tmp 0D elements
5211 set< const SMDS_MeshElement* > removed0D;
5212 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5214 if ( removed0D.insert( tmp0Delems[i] ).second )
5215 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5217 SMESH_CATCH( SMESH::throwCorbaException );
5222 //=======================================================================
5223 //function : SewFreeBorders
5225 //=======================================================================
5227 SMESH::SMESH_MeshEditor::Sew_Error
5228 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5229 CORBA::Long SecondNodeID1,
5230 CORBA::Long LastNodeID1,
5231 CORBA::Long FirstNodeID2,
5232 CORBA::Long SecondNodeID2,
5233 CORBA::Long LastNodeID2,
5234 CORBA::Boolean CreatePolygons,
5235 CORBA::Boolean CreatePolyedrs)
5236 throw (SALOME::SALOME_Exception)
5241 SMESHDS_Mesh* aMesh = getMeshDS();
5243 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5244 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5245 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5246 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5247 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5248 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5250 if (!aBorderFirstNode ||
5251 !aBorderSecondNode||
5253 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5254 if (!aSide2FirstNode ||
5255 !aSide2SecondNode ||
5257 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5259 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5260 << FirstNodeID1 << ", "
5261 << SecondNodeID1 << ", "
5262 << LastNodeID1 << ", "
5263 << FirstNodeID2 << ", "
5264 << SecondNodeID2 << ", "
5265 << LastNodeID2 << ", "
5266 << CreatePolygons<< ", "
5267 << CreatePolyedrs<< " )";
5269 SMESH::SMESH_MeshEditor::Sew_Error error =
5270 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5281 declareMeshModified( /*isReComputeSafe=*/false );
5284 SMESH_CATCH( SMESH::throwCorbaException );
5285 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5289 //=======================================================================
5290 //function : SewConformFreeBorders
5292 //=======================================================================
5294 SMESH::SMESH_MeshEditor::Sew_Error
5295 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5296 CORBA::Long SecondNodeID1,
5297 CORBA::Long LastNodeID1,
5298 CORBA::Long FirstNodeID2,
5299 CORBA::Long SecondNodeID2)
5300 throw (SALOME::SALOME_Exception)
5305 SMESHDS_Mesh* aMesh = getMeshDS();
5307 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5308 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5309 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5310 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5311 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5312 const SMDS_MeshNode* aSide2ThirdNode = 0;
5314 if (!aBorderFirstNode ||
5315 !aBorderSecondNode||
5317 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5318 if (!aSide2FirstNode ||
5320 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5322 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5323 << FirstNodeID1 << ", "
5324 << SecondNodeID1 << ", "
5325 << LastNodeID1 << ", "
5326 << FirstNodeID2 << ", "
5327 << SecondNodeID2 << " )";
5329 SMESH::SMESH_MeshEditor::Sew_Error error =
5330 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5339 declareMeshModified( /*isReComputeSafe=*/false );
5342 SMESH_CATCH( SMESH::throwCorbaException );
5343 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5347 //=======================================================================
5348 //function : SewBorderToSide
5350 //=======================================================================
5352 SMESH::SMESH_MeshEditor::Sew_Error
5353 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5354 CORBA::Long SecondNodeIDOnFreeBorder,
5355 CORBA::Long LastNodeIDOnFreeBorder,
5356 CORBA::Long FirstNodeIDOnSide,
5357 CORBA::Long LastNodeIDOnSide,
5358 CORBA::Boolean CreatePolygons,
5359 CORBA::Boolean CreatePolyedrs)
5360 throw (SALOME::SALOME_Exception)
5365 SMESHDS_Mesh* aMesh = getMeshDS();
5367 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5368 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5369 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5370 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5371 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5372 const SMDS_MeshNode* aSide2ThirdNode = 0;
5374 if (!aBorderFirstNode ||
5375 !aBorderSecondNode||
5377 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5378 if (!aSide2FirstNode ||
5380 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5382 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5383 << FirstNodeIDOnFreeBorder << ", "
5384 << SecondNodeIDOnFreeBorder << ", "
5385 << LastNodeIDOnFreeBorder << ", "
5386 << FirstNodeIDOnSide << ", "
5387 << LastNodeIDOnSide << ", "
5388 << CreatePolygons << ", "
5389 << CreatePolyedrs << ") ";
5391 SMESH::SMESH_MeshEditor::Sew_Error error =
5392 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5402 declareMeshModified( /*isReComputeSafe=*/false );
5405 SMESH_CATCH( SMESH::throwCorbaException );
5406 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5410 //=======================================================================
5411 //function : SewSideElements
5413 //=======================================================================
5415 SMESH::SMESH_MeshEditor::Sew_Error
5416 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5417 const SMESH::long_array& IDsOfSide2Elements,
5418 CORBA::Long NodeID1OfSide1ToMerge,
5419 CORBA::Long NodeID1OfSide2ToMerge,
5420 CORBA::Long NodeID2OfSide1ToMerge,
5421 CORBA::Long NodeID2OfSide2ToMerge)
5422 throw (SALOME::SALOME_Exception)
5427 SMESHDS_Mesh* aMesh = getMeshDS();
5429 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5430 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5431 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5432 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5434 if (!aFirstNode1ToMerge ||
5435 !aFirstNode2ToMerge )
5436 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5437 if (!aSecondNode1ToMerge||
5438 !aSecondNode2ToMerge)
5439 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5441 TIDSortedElemSet aSide1Elems, aSide2Elems;
5442 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5443 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5445 TPythonDump() << "error = " << this << ".SewSideElements( "
5446 << IDsOfSide1Elements << ", "
5447 << IDsOfSide2Elements << ", "
5448 << NodeID1OfSide1ToMerge << ", "
5449 << NodeID1OfSide2ToMerge << ", "
5450 << NodeID2OfSide1ToMerge << ", "
5451 << NodeID2OfSide2ToMerge << ")";
5453 SMESH::SMESH_MeshEditor::Sew_Error error =
5454 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5457 aSecondNode1ToMerge,
5458 aSecondNode2ToMerge));
5460 declareMeshModified( /*isReComputeSafe=*/false );
5463 SMESH_CATCH( SMESH::throwCorbaException );
5464 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5467 //================================================================================
5469 * \brief Set new nodes for given element
5470 * \param ide - element id
5471 * \param newIDs - new node ids
5472 * \retval CORBA::Boolean - true if result is OK
5474 //================================================================================
5476 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5477 const SMESH::long_array& newIDs)
5478 throw (SALOME::SALOME_Exception)
5483 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5484 if(!elem) return false;
5486 int nbn = newIDs.length();
5488 vector<const SMDS_MeshNode*> aNodes(nbn);
5491 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5494 aNodes[nbn1] = aNode;
5497 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5498 << ide << ", " << newIDs << " )";
5500 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5502 declareMeshModified( /*isReComputeSafe=*/ !res );
5506 SMESH_CATCH( SMESH::throwCorbaException );
5510 //=======================================================================
5512 * \brief Makes a part of the mesh quadratic or bi-quadratic
5514 //=======================================================================
5516 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5517 CORBA::Boolean theToBiQuad,
5518 SMESH::SMESH_IDSource_ptr theObject)
5519 throw (SALOME::SALOME_Exception)
5524 TIDSortedElemSet elems;
5526 if ( !( elemsOK = CORBA::is_nil( theObject )))
5528 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5529 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5533 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5534 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5536 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5537 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5539 declareMeshModified( /*isReComputeSafe=*/false );
5542 SMESH_CATCH( SMESH::throwCorbaException );
5545 //=======================================================================
5546 //function : ConvertFromQuadratic
5548 //=======================================================================
5550 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5551 throw (SALOME::SALOME_Exception)
5556 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5557 TPythonDump() << this << ".ConvertFromQuadratic()";
5558 declareMeshModified( /*isReComputeSafe=*/!isDone );
5561 SMESH_CATCH( SMESH::throwCorbaException );
5565 //=======================================================================
5566 //function : ConvertToQuadratic
5568 //=======================================================================
5570 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5571 throw (SALOME::SALOME_Exception)
5573 convertToQuadratic( theForce3d, false );
5574 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5577 //================================================================================
5579 * \brief Makes a part of the mesh quadratic
5581 //================================================================================
5583 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5584 SMESH::SMESH_IDSource_ptr theObject)
5585 throw (SALOME::SALOME_Exception)
5587 convertToQuadratic( theForce3d, false, theObject );
5588 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5591 //================================================================================
5593 * \brief Makes a part of the mesh bi-quadratic
5595 //================================================================================
5597 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5598 SMESH::SMESH_IDSource_ptr theObject)
5599 throw (SALOME::SALOME_Exception)
5601 convertToQuadratic( theForce3d, true, theObject );
5602 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5605 //================================================================================
5607 * \brief Makes a part of the mesh linear
5609 //================================================================================
5611 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5612 throw (SALOME::SALOME_Exception)
5619 TIDSortedElemSet elems;
5620 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5622 if ( elems.empty() )
5624 ConvertFromQuadratic();
5626 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5628 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5632 getEditor().ConvertFromQuadratic(elems);
5635 declareMeshModified( /*isReComputeSafe=*/false );
5637 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5639 SMESH_CATCH( SMESH::throwCorbaException );
5642 //=======================================================================
5643 //function : makeMesh
5644 //purpose : create a named imported mesh
5645 //=======================================================================
5647 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5649 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5650 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5651 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5652 gen->SetName( meshSO, theMeshName, "Mesh" );
5653 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5655 return mesh._retn();
5658 //=======================================================================
5659 //function : dumpGroupsList
5661 //=======================================================================
5663 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5664 const SMESH::ListOfGroups * theGroupList)
5666 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5667 if ( isDumpGroupList )
5668 theDumpPython << theGroupList << " = ";
5671 //================================================================================
5673 \brief Generates the unique group name.
5674 \param thePrefix name prefix
5677 //================================================================================
5679 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5681 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5682 set<std::string> groupNames;
5684 // Get existing group names
5685 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5686 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5687 if (CORBA::is_nil(aGroup))
5690 CORBA::String_var name = aGroup->GetName();
5691 groupNames.insert( name.in() );
5695 std::string name = thePrefix;
5698 while (!groupNames.insert(name).second)
5699 name = SMESH_Comment( thePrefix ) << "_" << index++;
5704 //================================================================================
5706 * \brief Prepare SMESH_IDSource for work
5708 //================================================================================
5710 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5712 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5714 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5715 filter->SetMesh( mesh );
5718 //================================================================================
5720 * \brief Retrieve elements of given type from SMESH_IDSource
5722 //================================================================================
5724 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5725 const SMESHDS_Mesh* theMeshDS,
5726 TIDSortedElemSet& theElemSet,
5727 const SMDSAbs_ElementType theType,
5728 const bool emptyIfIsMesh,
5729 IDSource_Error* error)
5732 if ( error ) *error = IDSource_OK;
5734 if ( CORBA::is_nil( theIDSource ))
5736 if ( error ) *error = IDSource_INVALID;
5739 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5741 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5742 *error = IDSource_EMPTY;
5745 prepareIdSource( theIDSource );
5746 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5747 if ( anIDs->length() == 0 )
5749 if ( error ) *error = IDSource_EMPTY;
5752 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5753 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5755 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5757 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5761 if ( error ) *error = IDSource_INVALID;
5767 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5768 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5770 if ( error ) *error = IDSource_INVALID;
5777 //================================================================================
5779 * \brief Duplicates given elements, i.e. creates new elements based on the
5780 * same nodes as the given ones.
5781 * \param theElements - container of elements to duplicate.
5782 * \param theGroupName - a name of group to contain the generated elements.
5783 * If a group with such a name already exists, the new elements
5784 * are added to the existing group, else a new group is created.
5785 * If \a theGroupName is empty, new elements are not added
5787 * \return a group where the new elements are added. NULL if theGroupName == "".
5790 //================================================================================
5792 SMESH::SMESH_Group_ptr
5793 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5794 const char* theGroupName)
5795 throw (SALOME::SALOME_Exception)
5797 SMESH::SMESH_Group_var newGroup;
5804 TIDSortedElemSet elems;
5805 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5807 getEditor().DoubleElements( elems );
5809 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5812 SMESH::ElementType type =
5813 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5814 // find existing group
5815 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5816 for ( size_t i = 0; i < groups->length(); ++i )
5817 if ( groups[i]->GetType() == type )
5819 CORBA::String_var name = groups[i]->GetName();
5820 if ( strcmp( name, theGroupName ) == 0 ) {
5821 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5825 // create a new group
5826 if ( newGroup->_is_nil() )
5827 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5829 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5831 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5832 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5833 for ( size_t i = 0; i < aSeq.size(); i++ )
5834 groupDS->SMDSGroup().Add( aSeq[i] );
5839 if ( !newGroup->_is_nil() )
5840 pyDump << newGroup << " = ";
5841 pyDump << this << ".DoubleElements( "
5842 << theElements << ", " << "'" << theGroupName <<"')";
5844 SMESH_CATCH( SMESH::throwCorbaException );
5846 return newGroup._retn();
5849 //================================================================================
5851 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5852 \param theNodes - identifiers of nodes to be doubled
5853 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5854 nodes. If list of element identifiers is empty then nodes are doubled but
5855 they not assigned to elements
5856 \return TRUE if operation has been completed successfully, FALSE otherwise
5857 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5859 //================================================================================
5861 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5862 const SMESH::long_array& theModifiedElems )
5863 throw (SALOME::SALOME_Exception)
5868 list< int > aListOfNodes;
5870 for ( i = 0, n = theNodes.length(); i < n; i++ )
5871 aListOfNodes.push_back( theNodes[ i ] );
5873 list< int > aListOfElems;
5874 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5875 aListOfElems.push_back( theModifiedElems[ i ] );
5877 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5879 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5881 // Update Python script
5882 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5886 SMESH_CATCH( SMESH::throwCorbaException );
5890 //================================================================================
5892 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5893 This method provided for convenience works as DoubleNodes() described above.
5894 \param theNodeId - identifier of node to be doubled.
5895 \param theModifiedElems - identifiers of elements to be updated.
5896 \return TRUE if operation has been completed successfully, FALSE otherwise
5897 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5899 //================================================================================
5901 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5902 const SMESH::long_array& theModifiedElems )
5903 throw (SALOME::SALOME_Exception)
5906 SMESH::long_array_var aNodes = new SMESH::long_array;
5907 aNodes->length( 1 );
5908 aNodes[ 0 ] = theNodeId;
5910 TPythonDump pyDump; // suppress dump by the next line
5912 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5914 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5918 SMESH_CATCH( SMESH::throwCorbaException );
5922 //================================================================================
5924 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5925 This method provided for convenience works as DoubleNodes() described above.
5926 \param theNodes - group of nodes to be doubled.
5927 \param theModifiedElems - group of elements to be updated.
5928 \return TRUE if operation has been completed successfully, FALSE otherwise
5929 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5931 //================================================================================
5933 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5934 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5935 throw (SALOME::SALOME_Exception)
5938 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5941 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5942 SMESH::long_array_var aModifiedElems;
5943 if ( !CORBA::is_nil( theModifiedElems ) )
5944 aModifiedElems = theModifiedElems->GetListOfID();
5946 aModifiedElems = new SMESH::long_array;
5948 TPythonDump pyDump; // suppress dump by the next line
5950 bool done = DoubleNodes( aNodes, aModifiedElems );
5952 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5956 SMESH_CATCH( SMESH::throwCorbaException );
5960 //================================================================================
5962 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5963 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5964 * \param theNodes - group of nodes to be doubled.
5965 * \param theModifiedElems - group of elements to be updated.
5966 * \return a new group with newly created nodes
5967 * \sa DoubleNodeGroup()
5969 //================================================================================
5971 SMESH::SMESH_Group_ptr
5972 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5973 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5974 throw (SALOME::SALOME_Exception)
5977 SMESH::SMESH_Group_var aNewGroup;
5979 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5980 return aNewGroup._retn();
5983 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5984 SMESH::long_array_var aModifiedElems;
5985 if ( !CORBA::is_nil( theModifiedElems ) )
5986 aModifiedElems = theModifiedElems->GetListOfID();
5988 aModifiedElems = new SMESH::long_array;
5989 aModifiedElems->length( 0 );
5992 TPythonDump pyDump; // suppress dump by the next line
5994 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5997 // Create group with newly created nodes
5998 SMESH::long_array_var anIds = GetLastCreatedNodes();
5999 if (anIds->length() > 0) {
6000 std::string anUnindexedName (theNodes->GetName());
6001 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6002 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6003 aNewGroup->Add(anIds);
6004 pyDump << aNewGroup << " = ";
6008 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6009 << theModifiedElems << " )";
6011 return aNewGroup._retn();
6013 SMESH_CATCH( SMESH::throwCorbaException );
6017 //================================================================================
6019 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6020 This method provided for convenience works as DoubleNodes() described above.
6021 \param theNodes - list of groups of nodes to be doubled
6022 \param theModifiedElems - list of groups of elements to be updated.
6023 \return TRUE if operation has been completed successfully, FALSE otherwise
6024 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6026 //================================================================================
6028 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6029 const SMESH::ListOfGroups& theModifiedElems )
6030 throw (SALOME::SALOME_Exception)
6035 std::list< int > aNodes;
6037 for ( i = 0, n = theNodes.length(); i < n; i++ )
6039 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6040 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6042 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6043 for ( j = 0, m = aCurr->length(); j < m; j++ )
6044 aNodes.push_back( aCurr[ j ] );
6048 std::list< int > anElems;
6049 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6051 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6052 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6054 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6055 for ( j = 0, m = aCurr->length(); j < m; j++ )
6056 anElems.push_back( aCurr[ j ] );
6060 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6062 declareMeshModified( /*isReComputeSafe=*/false );
6064 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6068 SMESH_CATCH( SMESH::throwCorbaException );
6072 //================================================================================
6074 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6075 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6076 * \param theNodes - group of nodes to be doubled.
6077 * \param theModifiedElems - group of elements to be updated.
6078 * \return a new group with newly created nodes
6079 * \sa DoubleNodeGroups()
6081 //================================================================================
6083 SMESH::SMESH_Group_ptr
6084 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6085 const SMESH::ListOfGroups& theModifiedElems )
6086 throw (SALOME::SALOME_Exception)
6088 SMESH::SMESH_Group_var aNewGroup;
6090 TPythonDump pyDump; // suppress dump by the next line
6092 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6096 // Create group with newly created nodes
6097 SMESH::long_array_var anIds = GetLastCreatedNodes();
6098 if (anIds->length() > 0) {
6099 std::string anUnindexedName (theNodes[0]->GetName());
6100 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6101 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6102 aNewGroup->Add(anIds);
6103 pyDump << aNewGroup << " = ";
6107 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6108 << theModifiedElems << " )";
6110 return aNewGroup._retn();
6114 //================================================================================
6116 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6117 \param theElems - the list of elements (edges or faces) to be replicated
6118 The nodes for duplication could be found from these elements
6119 \param theNodesNot - list of nodes to NOT replicate
6120 \param theAffectedElems - the list of elements (cells and edges) to which the
6121 replicated nodes should be associated to.
6122 \return TRUE if operation has been completed successfully, FALSE otherwise
6123 \sa DoubleNodeGroup(), DoubleNodeGroups()
6125 //================================================================================
6127 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6128 const SMESH::long_array& theNodesNot,
6129 const SMESH::long_array& theAffectedElems )
6130 throw (SALOME::SALOME_Exception)
6135 SMESHDS_Mesh* aMeshDS = getMeshDS();
6136 TIDSortedElemSet anElems, aNodes, anAffected;
6137 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6138 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6139 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6141 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6143 // Update Python script
6144 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6145 << theNodesNot << ", " << theAffectedElems << " )";
6147 declareMeshModified( /*isReComputeSafe=*/false );
6150 SMESH_CATCH( SMESH::throwCorbaException );
6154 //================================================================================
6156 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6157 \param theElems - the list of elements (edges or faces) to be replicated
6158 The nodes for duplication could be found from these elements
6159 \param theNodesNot - list of nodes to NOT replicate
6160 \param theShape - shape to detect affected elements (element which geometric center
6161 located on or inside shape).
6162 The replicated nodes should be associated to affected elements.
6163 \return TRUE if operation has been completed successfully, FALSE otherwise
6164 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6166 //================================================================================
6168 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6169 const SMESH::long_array& theNodesNot,
6170 GEOM::GEOM_Object_ptr theShape )
6171 throw (SALOME::SALOME_Exception)
6177 SMESHDS_Mesh* aMeshDS = getMeshDS();
6178 TIDSortedElemSet anElems, aNodes;
6179 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6180 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6182 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6183 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6185 // Update Python script
6186 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6187 << theNodesNot << ", " << theShape << " )";
6189 declareMeshModified( /*isReComputeSafe=*/false );
6192 SMESH_CATCH( SMESH::throwCorbaException );
6196 //================================================================================
6198 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6199 \param theElems - group of of elements (edges or faces) to be replicated
6200 \param theNodesNot - group of nodes not to replicated
6201 \param theAffectedElems - group of elements to which the replicated nodes
6202 should be associated to.
6203 \return TRUE if operation has been completed successfully, FALSE otherwise
6204 \sa DoubleNodes(), DoubleNodeGroups()
6206 //================================================================================
6209 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6210 SMESH::SMESH_GroupBase_ptr theNodesNot,
6211 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6212 throw (SALOME::SALOME_Exception)
6215 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6221 SMESHDS_Mesh* aMeshDS = getMeshDS();
6222 TIDSortedElemSet anElems, aNodes, anAffected;
6223 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6224 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6225 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6227 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6229 // Update Python script
6230 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6231 << theNodesNot << ", " << theAffectedElems << " )";
6233 declareMeshModified( /*isReComputeSafe=*/false );
6236 SMESH_CATCH( SMESH::throwCorbaException );
6240 //================================================================================
6242 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6243 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6244 * \param theElems - group of of elements (edges or faces) to be replicated
6245 * \param theNodesNot - group of nodes not to replicated
6246 * \param theAffectedElems - group of elements to which the replicated nodes
6247 * should be associated to.
6248 * \return a new group with newly created elements
6249 * \sa DoubleNodeElemGroup()
6251 //================================================================================
6253 SMESH::SMESH_Group_ptr
6254 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6255 SMESH::SMESH_GroupBase_ptr theNodesNot,
6256 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6257 throw (SALOME::SALOME_Exception)
6260 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6264 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6265 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6267 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6269 << theNodesNot << ", "
6270 << theAffectedElems << " )";
6272 return elemGroup._retn();
6275 //================================================================================
6277 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6278 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6279 * \param theElems - group of of elements (edges or faces) to be replicated
6280 * \param theNodesNot - group of nodes not to replicated
6281 * \param theAffectedElems - group of elements to which the replicated nodes
6282 * should be associated to.
6283 * \return a new group with newly created elements
6284 * \sa DoubleNodeElemGroup()
6286 //================================================================================
6288 SMESH::ListOfGroups*
6289 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6290 SMESH::SMESH_GroupBase_ptr theNodesNot,
6291 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6292 CORBA::Boolean theElemGroupNeeded,
6293 CORBA::Boolean theNodeGroupNeeded)
6294 throw (SALOME::SALOME_Exception)
6297 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6298 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6299 aTwoGroups->length( 2 );
6301 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6302 return aTwoGroups._retn();
6307 SMESHDS_Mesh* aMeshDS = getMeshDS();
6308 TIDSortedElemSet anElems, aNodes, anAffected;
6309 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6310 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6311 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6314 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6316 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6322 // Create group with newly created elements
6323 CORBA::String_var elemGroupName = theElems->GetName();
6324 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6325 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6327 SMESH::long_array_var anIds = GetLastCreatedElems();
6328 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6329 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6330 aNewElemGroup->Add(anIds);
6332 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6334 SMESH::long_array_var anIds = GetLastCreatedNodes();
6335 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6336 aNewNodeGroup->Add(anIds);
6340 // Update Python script
6343 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6344 else pyDump << aNewElemGroup << ", ";
6345 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6346 else pyDump << aNewNodeGroup << " ] = ";
6348 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6349 << theNodesNot << ", "
6350 << theAffectedElems << ", "
6351 << theElemGroupNeeded << ", "
6352 << theNodeGroupNeeded <<" )";
6354 aTwoGroups[0] = aNewElemGroup._retn();
6355 aTwoGroups[1] = aNewNodeGroup._retn();
6356 return aTwoGroups._retn();
6358 SMESH_CATCH( SMESH::throwCorbaException );
6362 //================================================================================
6364 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6365 \param theElems - group of of elements (edges or faces) to be replicated
6366 \param theNodesNot - group of nodes not to replicated
6367 \param theShape - shape to detect affected elements (element which geometric center
6368 located on or inside shape).
6369 The replicated nodes should be associated to affected elements.
6370 \return TRUE if operation has been completed successfully, FALSE otherwise
6371 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6373 //================================================================================
6376 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6377 SMESH::SMESH_GroupBase_ptr theNodesNot,
6378 GEOM::GEOM_Object_ptr theShape )
6379 throw (SALOME::SALOME_Exception)
6382 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6388 SMESHDS_Mesh* aMeshDS = getMeshDS();
6389 TIDSortedElemSet anElems, aNodes, anAffected;
6390 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6391 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6393 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6394 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6397 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6399 // Update Python script
6400 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6401 << theNodesNot << ", " << theShape << " )";
6404 SMESH_CATCH( SMESH::throwCorbaException );
6408 //================================================================================
6410 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6411 * \param [in] theGrpList - groups
6412 * \param [in] theMeshDS - mesh
6413 * \param [out] theElemSet - set of elements
6414 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6416 //================================================================================
6418 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6419 SMESHDS_Mesh* theMeshDS,
6420 TIDSortedElemSet& theElemSet,
6421 const bool theIsNodeGrp)
6423 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6425 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6426 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6427 : aGrp->GetType() != SMESH::NODE ) )
6429 SMESH::long_array_var anIDs = aGrp->GetIDs();
6430 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6435 //================================================================================
6437 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6438 This method provided for convenience works as DoubleNodes() described above.
6439 \param theElems - list of groups of elements (edges or faces) to be replicated
6440 \param theNodesNot - list of groups of nodes not to replicated
6441 \param theAffectedElems - group of elements to which the replicated nodes
6442 should be associated to.
6443 \return TRUE if operation has been completed successfully, FALSE otherwise
6444 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6446 //================================================================================
6449 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6450 const SMESH::ListOfGroups& theNodesNot,
6451 const SMESH::ListOfGroups& theAffectedElems)
6452 throw (SALOME::SALOME_Exception)
6458 SMESHDS_Mesh* aMeshDS = getMeshDS();
6459 TIDSortedElemSet anElems, aNodes, anAffected;
6460 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6461 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6462 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6464 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6466 // Update Python script
6467 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6468 << &theNodesNot << ", " << &theAffectedElems << " )";
6470 declareMeshModified( /*isReComputeSafe=*/false );
6473 SMESH_CATCH( SMESH::throwCorbaException );
6477 //================================================================================
6479 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6480 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6481 \param theElems - list of groups of elements (edges or faces) to be replicated
6482 \param theNodesNot - list of groups of nodes not to replicated
6483 \param theAffectedElems - group of elements to which the replicated nodes
6484 should be associated to.
6485 * \return a new group with newly created elements
6486 * \sa DoubleNodeElemGroups()
6488 //================================================================================
6490 SMESH::SMESH_Group_ptr
6491 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6492 const SMESH::ListOfGroups& theNodesNot,
6493 const SMESH::ListOfGroups& theAffectedElems)
6494 throw (SALOME::SALOME_Exception)
6497 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6501 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6502 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6504 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6506 << theNodesNot << ", "
6507 << theAffectedElems << " )";
6509 return elemGroup._retn();
6512 //================================================================================
6514 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6515 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6516 \param theElems - list of groups of elements (edges or faces) to be replicated
6517 \param theNodesNot - list of groups of nodes not to replicated
6518 \param theAffectedElems - group of elements to which the replicated nodes
6519 should be associated to.
6520 * \return a new group with newly created elements
6521 * \sa DoubleNodeElemGroups()
6523 //================================================================================
6525 SMESH::ListOfGroups*
6526 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6527 const SMESH::ListOfGroups& theNodesNot,
6528 const SMESH::ListOfGroups& theAffectedElems,
6529 CORBA::Boolean theElemGroupNeeded,
6530 CORBA::Boolean theNodeGroupNeeded)
6531 throw (SALOME::SALOME_Exception)
6534 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6535 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6536 aTwoGroups->length( 2 );
6541 SMESHDS_Mesh* aMeshDS = getMeshDS();
6542 TIDSortedElemSet anElems, aNodes, anAffected;
6543 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6544 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6545 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6547 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6549 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6554 // Create group with newly created elements
6555 CORBA::String_var elemGroupName = theElems[0]->GetName();
6556 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6557 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6559 SMESH::long_array_var anIds = GetLastCreatedElems();
6560 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6561 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6562 aNewElemGroup->Add(anIds);
6564 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6566 SMESH::long_array_var anIds = GetLastCreatedNodes();
6567 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6568 aNewNodeGroup->Add(anIds);
6572 // Update Python script
6575 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6576 else pyDump << aNewElemGroup << ", ";
6577 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6578 else pyDump << aNewNodeGroup << " ] = ";
6580 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6581 << &theNodesNot << ", "
6582 << &theAffectedElems << ", "
6583 << theElemGroupNeeded << ", "
6584 << theNodeGroupNeeded << " )";
6586 aTwoGroups[0] = aNewElemGroup._retn();
6587 aTwoGroups[1] = aNewNodeGroup._retn();
6588 return aTwoGroups._retn();
6590 SMESH_CATCH( SMESH::throwCorbaException );
6594 //================================================================================
6596 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6597 This method provided for convenience works as DoubleNodes() described above.
6598 \param theElems - list of groups of elements (edges or faces) to be replicated
6599 \param theNodesNot - list of groups of nodes not to replicated
6600 \param theShape - shape to detect affected elements (element which geometric center
6601 located on or inside shape).
6602 The replicated nodes should be associated to affected elements.
6603 \return TRUE if operation has been completed successfully, FALSE otherwise
6604 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6606 //================================================================================
6609 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6610 const SMESH::ListOfGroups& theNodesNot,
6611 GEOM::GEOM_Object_ptr theShape )
6612 throw (SALOME::SALOME_Exception)
6618 SMESHDS_Mesh* aMeshDS = getMeshDS();
6619 TIDSortedElemSet anElems, aNodes;
6620 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6621 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6623 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6624 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6626 // Update Python script
6627 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6628 << &theNodesNot << ", " << theShape << " )";
6630 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6633 SMESH_CATCH( SMESH::throwCorbaException );
6637 //================================================================================
6639 \brief Identify the elements that will be affected by node duplication (actual
6640 duplication is not performed.
6641 This method is the first step of DoubleNodeElemGroupsInRegion.
6642 \param theElems - list of groups of elements (edges or faces) to be replicated
6643 \param theNodesNot - list of groups of nodes not to replicated
6644 \param theShape - shape to detect affected elements (element which geometric center
6645 located on or inside shape).
6646 The replicated nodes should be associated to affected elements.
6647 \return groups of affected elements
6648 \sa DoubleNodeElemGroupsInRegion()
6650 //================================================================================
6651 SMESH::ListOfGroups*
6652 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6653 const SMESH::ListOfGroups& theNodesNot,
6654 GEOM::GEOM_Object_ptr theShape )
6655 throw (SALOME::SALOME_Exception)
6658 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6659 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6660 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6661 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6665 ::SMESH_MeshEditor aMeshEditor(myMesh);
6667 SMESHDS_Mesh* aMeshDS = getMeshDS();
6668 TIDSortedElemSet anElems, aNodes;
6669 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6670 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6671 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6673 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6674 TIDSortedElemSet anAffected;
6675 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6677 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6680 if ( aResult && anAffected.size() > 0 )
6682 SMESH::long_array_var volumeIds = new SMESH::long_array;
6683 SMESH::long_array_var faceIds = new SMESH::long_array;
6684 SMESH::long_array_var edgeIds = new SMESH::long_array;
6685 volumeIds->length( anAffected.size() );
6686 faceIds ->length( anAffected.size() );
6687 edgeIds ->length( anAffected.size() );
6692 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6693 for (; eIt != anAffected.end(); ++eIt)
6695 const SMDS_MeshElement* anElem = *eIt;
6696 int elemId = anElem->GetID();
6697 switch ( anElem->GetType() ) {
6698 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6699 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6700 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6704 volumeIds->length(ivol);
6705 faceIds->length(iface);
6706 edgeIds->length(iedge);
6711 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6712 GenerateGroupName("affectedVolumes").c_str());
6713 aNewVolumeGroup->Add(volumeIds);
6714 aListOfGroups->length( nbGroups+1 );
6715 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6719 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6720 GenerateGroupName("affectedFaces").c_str());
6721 aNewFaceGroup->Add(faceIds);
6722 aListOfGroups->length( nbGroups+1 );
6723 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6727 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6728 GenerateGroupName("affectedEdges").c_str());
6729 aNewEdgeGroup->Add(edgeIds);
6730 aListOfGroups->length( nbGroups+1 );
6731 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6735 // Update Python script
6737 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6738 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6740 return aListOfGroups._retn();
6742 SMESH_CATCH( SMESH::throwCorbaException );
6746 //================================================================================
6748 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6749 The created 2D mesh elements based on nodes of free faces of boundary volumes
6750 \return TRUE if operation has been completed successfully, FALSE otherwise
6752 //================================================================================
6754 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6755 throw (SALOME::SALOME_Exception)
6760 bool aResult = getEditor().Make2DMeshFrom3D();
6762 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6764 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6767 SMESH_CATCH( SMESH::throwCorbaException );
6771 //================================================================================
6773 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6774 * The list of groups must contain at least two groups. The groups have to be disjoint:
6775 * no common element into two different groups.
6776 * The nodes of the internal faces at the boundaries of the groups are doubled.
6777 * Optionally, the internal faces are replaced by flat elements.
6778 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6779 * The flat elements are stored in groups of volumes.
6780 * These groups are named according to the position of the group in the list:
6781 * 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.
6782 * 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.
6783 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6784 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6785 * \param theDomains - list of groups of volumes
6786 * \param createJointElems - if TRUE, create the elements
6787 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6788 * the boundary between \a theDomains and the rest mesh
6789 * \return TRUE if operation has been completed successfully, FALSE otherwise
6791 //================================================================================
6794 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6795 CORBA::Boolean createJointElems,
6796 CORBA::Boolean onAllBoundaries )
6797 throw (SALOME::SALOME_Exception)
6804 SMESHDS_Mesh* aMeshDS = getMeshDS();
6806 // MESSAGE("theDomains.length = "<<theDomains.length());
6807 if ( theDomains.length() <= 1 && !onAllBoundaries )
6808 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6810 vector<TIDSortedElemSet> domains;
6811 domains.resize( theDomains.length() );
6813 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6815 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6816 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6818 // if ( aGrp->GetType() != SMESH::VOLUME )
6819 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6820 SMESH::long_array_var anIDs = aGrp->GetIDs();
6821 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6825 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6826 // TODO publish the groups of flat elements in study
6828 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6830 // Update Python script
6831 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6832 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6834 SMESH_CATCH( SMESH::throwCorbaException );
6836 myMesh_i->CreateGroupServants(); // publish created groups if any
6841 //================================================================================
6843 * \brief Double nodes on some external faces and create flat elements.
6844 * Flat elements are mainly used by some types of mechanic calculations.
6846 * Each group of the list must be constituted of faces.
6847 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6848 * @param theGroupsOfFaces - list of groups of faces
6849 * @return TRUE if operation has been completed successfully, FALSE otherwise
6851 //================================================================================
6854 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6855 throw (SALOME::SALOME_Exception)
6860 SMESHDS_Mesh* aMeshDS = getMeshDS();
6862 vector<TIDSortedElemSet> faceGroups;
6865 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6867 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6868 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6870 TIDSortedElemSet faceGroup;
6872 faceGroups.push_back(faceGroup);
6873 SMESH::long_array_var anIDs = aGrp->GetIDs();
6874 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6878 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6879 // TODO publish the groups of flat elements in study
6881 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6883 // Update Python script
6884 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6887 SMESH_CATCH( SMESH::throwCorbaException );
6891 //================================================================================
6893 * \brief Identify all the elements around a geom shape, get the faces delimiting
6896 * Build groups of volume to remove, groups of faces to replace on the skin of the
6897 * object, groups of faces to remove inside the object, (idem edges).
6898 * Build ordered list of nodes at the border of each group of faces to replace
6899 * (to be used to build a geom subshape).
6901 //================================================================================
6903 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6904 GEOM::GEOM_Object_ptr theShape,
6905 const char* groupName,
6906 const SMESH::double_array& theNodesCoords,
6907 SMESH::array_of_long_array_out GroupsOfNodes)
6908 throw (SALOME::SALOME_Exception)
6913 std::vector<std::vector<int> > aListOfListOfNodes;
6914 ::SMESH_MeshEditor aMeshEditor( myMesh );
6916 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6917 if ( !theNodeSearcher )
6918 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6920 vector<double> nodesCoords;
6921 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6923 nodesCoords.push_back( theNodesCoords[i] );
6926 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6927 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6928 nodesCoords, aListOfListOfNodes);
6930 GroupsOfNodes = new SMESH::array_of_long_array;
6931 GroupsOfNodes->length( aListOfListOfNodes.size() );
6932 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6933 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6935 vector<int>& aListOfNodes = *llIt;
6936 vector<int>::iterator lIt = aListOfNodes.begin();;
6937 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6938 aGroup.length( aListOfNodes.size() );
6939 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6940 aGroup[ j ] = (*lIt);
6942 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6945 << ", '" << groupName << "', "
6946 << theNodesCoords << " )";
6948 SMESH_CATCH( SMESH::throwCorbaException );
6951 // issue 20749 ===================================================================
6953 * \brief Creates missing boundary elements
6954 * \param elements - elements whose boundary is to be checked
6955 * \param dimension - defines type of boundary elements to create
6956 * \param groupName - a name of group to store created boundary elements in,
6957 * "" means not to create the group
6958 * \param meshName - a name of new mesh to store created boundary elements in,
6959 * "" means not to create the new mesh
6960 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6961 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6962 * boundary elements will be copied into the new mesh
6963 * \param group - returns the create group, if any
6964 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6966 // ================================================================================
6968 SMESH::SMESH_Mesh_ptr
6969 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6970 SMESH::Bnd_Dimension dim,
6971 const char* groupName,
6972 const char* meshName,
6973 CORBA::Boolean toCopyElements,
6974 CORBA::Boolean toCopyExistingBondary,
6975 SMESH::SMESH_Group_out group)
6976 throw (SALOME::SALOME_Exception)
6981 if ( dim > SMESH::BND_1DFROM2D )
6982 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6984 SMESHDS_Mesh* aMeshDS = getMeshDS();
6986 SMESH::SMESH_Mesh_var mesh_var;
6987 SMESH::SMESH_Group_var group_var;
6991 TIDSortedElemSet elements;
6992 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6993 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6997 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6998 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7000 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7002 // group of new boundary elements
7003 SMESH_Group* smesh_group = 0;
7004 if ( strlen(groupName) )
7006 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7007 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7008 smesh_group = group_i->GetSmeshGroup();
7012 getEditor().MakeBoundaryMesh( elements,
7013 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7017 toCopyExistingBondary);
7020 smesh_mesh->GetMeshDS()->Modified();
7023 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7025 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7026 if ( mesh_var->_is_nil() )
7027 pyDump << myMesh_i->_this() << ", ";
7029 pyDump << mesh_var << ", ";
7030 if ( group_var->_is_nil() )
7031 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7033 pyDump << group_var << " = ";
7034 pyDump << this << ".MakeBoundaryMesh( "
7036 << "SMESH." << dimName[int(dim)] << ", "
7037 << "'" << groupName << "', "
7038 << "'" << meshName<< "', "
7039 << toCopyElements << ", "
7040 << toCopyExistingBondary << ")";
7042 group = group_var._retn();
7043 return mesh_var._retn();
7045 SMESH_CATCH( SMESH::throwCorbaException );
7046 return SMESH::SMESH_Mesh::_nil();
7049 //================================================================================
7051 * \brief Creates missing boundary elements
7052 * \param dimension - defines type of boundary elements to create
7053 * \param groupName - a name of group to store all boundary elements in,
7054 * "" means not to create the group
7055 * \param meshName - a name of a new mesh, which is a copy of the initial
7056 * mesh + created boundary elements; "" means not to create the new mesh
7057 * \param toCopyAll - if true, the whole initial mesh will be copied into
7058 * the new mesh else only boundary elements will be copied into the new mesh
7059 * \param groups - optional groups of elements to make boundary around
7060 * \param mesh - returns the mesh where elements were added to
7061 * \param group - returns the created group, if any
7062 * \retval long - number of added boundary elements
7064 //================================================================================
7066 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7067 const char* groupName,
7068 const char* meshName,
7069 CORBA::Boolean toCopyAll,
7070 const SMESH::ListOfIDSources& groups,
7071 SMESH::SMESH_Mesh_out mesh,
7072 SMESH::SMESH_Group_out group)
7073 throw (SALOME::SALOME_Exception)
7078 if ( dim > SMESH::BND_1DFROM2D )
7079 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7081 // separate groups belonging to this and other mesh
7082 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7083 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7084 groupsOfThisMesh ->length( groups.length() );
7085 groupsOfOtherMesh->length( groups.length() );
7086 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7087 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7089 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7090 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7091 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7093 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7094 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7095 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7097 groupsOfThisMesh->length( nbGroups );
7098 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7103 if ( nbGroupsOfOtherMesh > 0 )
7105 // process groups belonging to another mesh
7106 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7107 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7108 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7109 groupsOfOtherMesh, mesh, group );
7112 SMESH::SMESH_Mesh_var mesh_var;
7113 SMESH::SMESH_Group_var group_var;
7116 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7117 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7121 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7123 /*toCopyGroups=*/false,
7124 /*toKeepIDs=*/true);
7126 mesh_var = makeMesh(meshName);
7128 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7129 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7132 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7133 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7135 // group of boundary elements
7136 SMESH_Group* smesh_group = 0;
7137 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7138 if ( strlen( groupName ))
7140 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7141 group_var = mesh_i->CreateGroup( groupType, groupName );
7142 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7143 smesh_group = group_i->GetSmeshGroup();
7146 TIDSortedElemSet elements;
7148 if ( groups.length() > 0 )
7150 for ( int i = 0; i < nbGroups; ++i )
7153 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7155 SMESH::Bnd_Dimension bdim =
7156 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7157 nbAdded += getEditor().MakeBoundaryMesh( elements,
7158 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7161 /*toCopyElements=*/false,
7162 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7163 /*toAddExistingBondary=*/true,
7164 /*aroundElements=*/true);
7170 nbAdded += getEditor().MakeBoundaryMesh( elements,
7171 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7174 /*toCopyElements=*/false,
7175 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7176 /*toAddExistingBondary=*/true);
7178 tgtMesh->GetMeshDS()->Modified();
7180 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7182 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7183 pyDump << "nbAdded, ";
7184 if ( mesh_var->_is_nil() )
7185 pyDump << myMesh_i->_this() << ", ";
7187 pyDump << mesh_var << ", ";
7188 if ( group_var->_is_nil() )
7189 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7191 pyDump << group_var << " = ";
7192 pyDump << this << ".MakeBoundaryElements( "
7193 << "SMESH." << dimName[int(dim)] << ", "
7194 << "'" << groupName << "', "
7195 << "'" << meshName<< "', "
7196 << toCopyAll << ", "
7199 mesh = mesh_var._retn();
7200 group = group_var._retn();
7203 SMESH_CATCH( SMESH::throwCorbaException );
7207 //================================================================================
7209 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7210 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7211 * plane passing through pairs of points specified by each PolySegment structure.
7212 * If there are several paths connecting a pair of points, the shortest path is
7213 * selected by the module. Position of the cutting plane is defined by the two
7214 * points and an optional vector lying on the plane specified by a PolySegment.
7215 * By default the vector is defined by Mesh module as following. A middle point
7216 * of the two given points is computed. The middle point is projected to the mesh.
7217 * The vector goes from the middle point to the projection point. In case of planar
7218 * mesh, the vector is normal to the mesh.
7219 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7220 * Return the used vector and position of the middle point.
7221 * \param [in] groupName - optional name of a group where created mesh segments will
7224 //================================================================================
7226 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7227 const char* theGroupName)
7228 throw (SALOME::SALOME_Exception)
7230 if ( theSegments.length() == 0 )
7231 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7232 if ( myMesh->NbFaces() == 0 )
7233 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7236 initData(/*deleteSearchers=*/false);
7238 SMESHDS_Group* groupDS = 0;
7239 SMESHDS_Mesh* meshDS = getMeshDS();
7240 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7242 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7243 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7244 while ( faceIt->more() )
7245 tmpMesh->Copy( faceIt->next() );
7246 meshDS = tmpMesh->GetMeshDS();
7248 else if ( theGroupName[0] ) // find/create a group of segments
7250 SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7251 while ( !groupDS && grpIt->more() )
7253 SMESH_Group* group = grpIt->next();
7254 if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7255 strcmp( group->GetName(), theGroupName ) == 0 )
7257 groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7262 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7264 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7265 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7269 // convert input polySegments
7270 ::SMESH_MeshEditor::TListOfPolySegments segments( theSegments.length() );
7271 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7273 SMESH::PolySegment& segIn = theSegments[ i ];
7274 ::SMESH_MeshEditor::PolySegment& segOut = segments[ i ];
7275 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7276 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7277 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7278 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7279 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7282 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7285 segOut.myVector.SetCoord( segIn.vector.PS.x,
7287 segIn.vector.PS.z );
7290 // get a static ElementSearcher
7291 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7292 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7293 if ( !theElementSearcher )
7294 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7297 getEditor().MakePolyLine( segments, groupDS, theElementSearcher );
7300 if ( myIsPreviewMode )
7302 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7304 SMESH::PolySegment& segOut = theSegments[ i ];
7305 ::SMESH_MeshEditor::PolySegment& segIn = segments[ i ];
7306 segOut.vector.PS.x = segIn.myVector.X();
7307 segOut.vector.PS.y = segIn.myVector.Y();
7308 segOut.vector.PS.z = segIn.myVector.Z();
7313 TPythonDump() << "_segments = []";
7314 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7316 SMESH::PolySegment& segIn = theSegments[ i ];
7317 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7318 << segIn.node1ID1 << ", "
7319 << segIn.node1ID2 << ", "
7320 << segIn.node2ID1 << ", "
7321 << segIn.node2ID2 << ", "
7322 << "smeshBuilder.MakeDirStruct( "
7323 << segIn.vector.PS.x << ", "
7324 << segIn.vector.PS.y << ", "
7325 << segIn.vector.PS.z << ")))";
7327 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7330 SMESH_CATCH( SMESH::throwCorbaException );