1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
46 #include "SMDS_SetIterator.hxx"
47 #include "SMDS_VolumeTool.hxx"
48 #include "SMESHDS_Group.hxx"
49 #include "SMESHDS_GroupOnGeom.hxx"
50 #include "SMESH_ControlsDef.hxx"
51 #include "SMESH_Filter_i.hxx"
52 #include "SMESH_Gen_i.hxx"
53 #include "SMESH_Group.hxx"
54 #include "SMESH_Group_i.hxx"
55 #include "SMESH_MeshAlgos.hxx"
56 #include "SMESH_MeshPartDS.hxx"
57 #include "SMESH_MesherHelper.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMeshEventListener.hxx"
60 #include "SMESH_subMesh_i.hxx"
62 #include <utilities.h>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <Utils_CorbaException.hxx>
65 #include <SALOMEDS_wrap.hxx>
66 #include <SALOME_GenericObj_i.hh>
68 #include <BRepAdaptor_Surface.hxx>
69 #include <BRep_Tool.hxx>
70 #include <TopExp_Explorer.hxx>
72 #include <TopoDS_Edge.hxx>
73 #include <TopoDS_Face.hxx>
78 #include <Standard_Failure.hxx>
79 #include <Standard_ErrorHandler.hxx>
84 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
86 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
89 using SMESH::TPythonDump;
92 namespace MeshEditor_I {
94 //=============================================================================
96 * \brief Mesh to apply modifications for preview purposes
98 //=============================================================================
100 struct TPreviewMesh: public SMESH_Mesh
102 SMDSAbs_ElementType myPreviewType; // type to show
104 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
105 _isShapeToMesh = (_id =_studyId = 0);
106 _myMeshDS = new SMESHDS_Mesh( _id, true );
107 myPreviewType = previewElements;
109 //!< Copy a set of elements
110 void Copy(const TIDSortedElemSet & theElements,
111 TIDSortedElemSet& theCopyElements,
112 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
113 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
115 // loop on theIDsOfElements
116 TIDSortedElemSet::const_iterator eIt = theElements.begin();
117 for ( ; eIt != theElements.end(); ++eIt )
119 const SMDS_MeshElement* anElem = *eIt;
120 if ( !anElem ) continue;
121 SMDSAbs_ElementType type = anElem->GetType();
122 if ( type == theAvoidType ||
123 ( theSelectType != SMDSAbs_All && type != theSelectType ))
125 const SMDS_MeshElement* anElemCopy;
126 if ( type == SMDSAbs_Node)
127 anElemCopy = Copy( cast2Node(anElem) );
129 anElemCopy = Copy( anElem );
131 theCopyElements.insert( theCopyElements.end(), anElemCopy );
135 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
137 // copy element nodes
138 int anElemNbNodes = anElem->NbNodes();
139 vector< int > anElemNodesID( anElemNbNodes ) ;
140 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
141 for ( int i = 0; itElemNodes->more(); i++)
143 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
145 anElemNodesID[i] = anElemNode->GetID();
148 // creates a corresponding element on copied nodes
149 ::SMESH_MeshEditor::ElemFeatures elemType;
150 elemType.Init( anElem, /*basicOnly=*/false );
151 elemType.SetID( anElem->GetID() );
152 SMDS_MeshElement* anElemCopy =
153 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
157 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
159 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
160 anElemNode->GetID());
164 GetMeshDS()->ClearMesh();
166 void Remove( SMDSAbs_ElementType type )
168 Remove( GetMeshDS()->elementsIterator( type ));
170 void Remove( SMDS_ElemIteratorPtr eIt )
172 while ( eIt->more() )
173 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
175 };// struct TPreviewMesh
177 static SMESH_NodeSearcher * theNodeSearcher = 0;
178 static SMESH_ElementSearcher * theElementSearcher = 0;
180 //=============================================================================
182 * \brief Deleter of theNodeSearcher at any compute event occurred
184 //=============================================================================
186 struct TSearchersDeleter : public SMESH_subMeshEventListener
189 string myMeshPartIOR;
191 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
192 "SMESH_MeshEditor_i::TSearchersDeleter"),
194 //!< Delete theNodeSearcher
197 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
198 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
200 typedef map < int, SMESH_subMesh * > TDependsOnMap;
201 //!< The meshod called by submesh: do my main job
202 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
203 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
205 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
207 Unset( sm->GetFather() );
210 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
211 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
213 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
220 myMeshPartIOR = meshPartIOR;
221 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
222 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
223 while ( smIt->more() )
226 sm->SetEventListener( this, 0, sm );
230 //!< delete self from all submeshes
231 void Unset(SMESH_Mesh* mesh)
233 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
234 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
235 while ( smIt->more() )
236 smIt->next()->DeleteEventListener( this );
241 } theSearchersDeleter;
243 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
245 TCollection_AsciiString typeStr;
246 switch ( theMirrorType ) {
247 case SMESH::SMESH_MeshEditor::POINT:
248 typeStr = "SMESH.SMESH_MeshEditor.POINT";
250 case SMESH::SMESH_MeshEditor::AXIS:
251 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
254 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
258 //================================================================================
260 * \brief function for conversion of long_array to TIDSortedElemSet
261 * \param IDs - array of IDs
262 * \param aMesh - mesh
263 * \param aMap - collection to fill
264 * \param aType - element type
266 //================================================================================
268 void arrayToSet(const SMESH::long_array & IDs,
269 const SMESHDS_Mesh* aMesh,
270 TIDSortedElemSet& aMap,
271 const SMDSAbs_ElementType aType = SMDSAbs_All,
272 SMDS_MeshElement::Filter* aFilter = NULL)
274 SMDS_MeshElement::NonNullFilter filter1;
275 SMDS_MeshElement::TypeFilter filter2( aType );
277 if ( aFilter == NULL )
278 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
280 SMDS_MeshElement::Filter & filter = *aFilter;
282 if ( aType == SMDSAbs_Node )
283 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
284 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
286 aMap.insert( aMap.end(), elem );
289 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
290 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
292 aMap.insert( aMap.end(), elem );
296 //================================================================================
298 * \brief Retrieve nodes from SMESH_IDSource
300 //================================================================================
302 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
303 const SMESHDS_Mesh* theMeshDS,
304 TIDSortedNodeSet& theNodeSet)
307 if ( CORBA::is_nil( theObject ) )
309 SMESH::array_of_ElementType_var types = theObject->GetTypes();
310 SMESH::long_array_var aElementsId = theObject->GetIDs();
311 if ( types->length() == 1 && types[0] == SMESH::NODE)
313 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
314 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
315 theNodeSet.insert( theNodeSet.end(), n);
317 else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
319 SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
320 while ( nIt->more( ))
321 if ( const SMDS_MeshElement * elem = nIt->next() )
322 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
326 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
327 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
328 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
332 //================================================================================
334 * \brief Returns elements connected to the given elements
336 //================================================================================
338 void getElementsAround(const TIDSortedElemSet& theElements,
339 const SMESHDS_Mesh* theMeshDS,
340 TIDSortedElemSet& theElementsAround)
342 if ( theElements.empty() ) return;
344 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
345 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
347 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
348 return; // all the elements are in theElements
351 elemType = SMDSAbs_All;
353 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
355 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
356 for ( ; elemIt != theElements.end(); ++elemIt )
358 const SMDS_MeshElement* e = *elemIt;
359 int i = e->NbCornerNodes();
362 const SMDS_MeshNode* n = e->GetNode( i );
363 if ( !isNodeChecked[ n->GetID() ])
365 isNodeChecked[ n->GetID() ] = true;
366 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
367 while ( invIt->more() )
369 const SMDS_MeshElement* elemAround = invIt->next();
370 if ( !theElements.count( elemAround ))
371 theElementsAround.insert( elemAround );
378 //================================================================================
380 * \brief Return a string used to detect change of mesh part on which theElementSearcher
381 * is going to be used
383 //================================================================================
385 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
387 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
388 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
389 // take into account passible group modification
390 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
391 partIOR += SMESH_Comment( type );
395 } // namespace MeshEditor_I
397 using namespace MeshEditor_I;
399 //=============================================================================
403 //=============================================================================
405 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
407 myMesh( &theMesh->GetImpl() ),
409 myIsPreviewMode ( isPreview ),
415 //================================================================================
419 //================================================================================
421 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
423 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
424 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
425 poa->deactivate_object(anObjectId.in());
427 //deleteAuxIDSources();
428 delete myPreviewMesh; myPreviewMesh = 0;
429 delete myPreviewEditor; myPreviewEditor = 0;
432 //================================================================================
434 * \brief Returns the mesh
436 //================================================================================
438 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
440 return myMesh_i->_this();
443 //================================================================================
445 * \brief Clear members
447 //================================================================================
449 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
451 if ( myIsPreviewMode ) {
452 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
455 if ( deleteSearchers )
456 TSearchersDeleter::Delete();
458 getEditor().GetError().reset();
459 getEditor().ClearLastCreated();
462 //================================================================================
464 * \brief Increment mesh modif time and optionally record that the performed
465 * modification may influence further mesh re-compute.
466 * \param [in] isReComputeSafe - true if the modification does not influence
467 * further mesh re-compute
469 //================================================================================
471 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
473 myMesh->GetMeshDS()->Modified();
474 if ( !isReComputeSafe )
475 myMesh->SetIsModified( true );
478 //================================================================================
480 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
481 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
483 //================================================================================
485 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
487 if ( myIsPreviewMode && !myPreviewEditor ) {
488 if ( !myPreviewMesh ) getPreviewMesh();
489 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
491 return myIsPreviewMode ? *myPreviewEditor : myEditor;
494 //================================================================================
496 * \brief Initialize and return myPreviewMesh
497 * \param previewElements - type of elements to show in preview
499 * WARNING: call it once per method!
501 //================================================================================
503 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
505 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
507 delete myPreviewEditor;
509 delete myPreviewMesh;
510 myPreviewMesh = new TPreviewMesh( previewElements );
512 myPreviewMesh->Clear();
513 return myPreviewMesh;
516 //================================================================================
518 * Return data of mesh edition preview
520 //================================================================================
522 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
523 throw (SALOME::SALOME_Exception)
526 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
528 if ( myIsPreviewMode || hasBadElems )
530 list<int> aNodesConnectivity;
531 typedef map<int, int> TNodesMap;
534 SMESHDS_Mesh* aMeshDS;
535 std::unique_ptr< SMESH_MeshPartDS > aMeshPartDS;
537 aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
538 aMeshDS = aMeshPartDS.get();
541 aMeshDS = getEditor().GetMeshDS();
543 myPreviewData = new SMESH::MeshPreviewStruct();
544 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
547 SMDSAbs_ElementType previewType = SMDSAbs_All;
549 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
550 previewType = aPreviewMesh->myPreviewType;
551 switch ( previewType ) {
552 case SMDSAbs_Edge : break;
553 case SMDSAbs_Face : break;
554 case SMDSAbs_Volume: break;
556 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
560 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
562 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
564 while ( itMeshElems->more() ) {
565 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
566 SMDS_NodeIteratorPtr itElemNodes =
567 (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
568 aMeshElem->interlacedNodesIterator() :
569 aMeshElem->nodeIterator() );
570 while ( itElemNodes->more() ) {
571 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
572 int aNodeID = aMeshNode->GetID();
573 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
574 if ( anIter == nodesMap.end() ) {
575 // filling the nodes coordinates
576 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
577 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
578 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
579 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
582 aNodesConnectivity.push_back(anIter->second);
585 // filling the elements types
586 SMDSAbs_ElementType aType = aMeshElem->GetType();
587 bool isPoly = aMeshElem->IsPoly();
588 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
589 myPreviewData->elementTypes[i].isPoly = isPoly;
590 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
593 myPreviewData->nodesXYZ.length( j );
595 // filling the elements connectivities
596 list<int>::iterator aConnIter = aNodesConnectivity.begin();
597 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
598 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
599 myPreviewData->elementConnectivities[i] = *aConnIter;
601 return myPreviewData._retn();
603 SMESH_CATCH( SMESH::throwCorbaException );
607 //================================================================================
609 * \brief Returns list of it's IDs of created nodes
610 * \retval SMESH::long_array* - list of node ID
612 //================================================================================
614 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
615 throw (SALOME::SALOME_Exception)
618 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
620 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
621 myLastCreatedNodes->length( aSeq.size() );
622 for ( size_t i = 0; i < aSeq.size(); i++)
623 myLastCreatedNodes[i] = aSeq[i]->GetID();
625 return myLastCreatedNodes._retn();
626 SMESH_CATCH( SMESH::throwCorbaException );
630 //================================================================================
632 * \brief Returns list of it's IDs of created elements
633 * \retval SMESH::long_array* - list of elements' ID
635 //================================================================================
637 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
638 throw (SALOME::SALOME_Exception)
641 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
643 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
644 myLastCreatedElems->length( aSeq.size() );
645 for ( size_t i = 0; i < aSeq.size(); i++ )
646 myLastCreatedElems[i] = aSeq[i]->GetID();
648 return myLastCreatedElems._retn();
649 SMESH_CATCH( SMESH::throwCorbaException );
653 //=======================================================================
654 //function : ClearLastCreated
655 //purpose : Clears sequences of last created elements and nodes
656 //=======================================================================
658 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
661 getEditor().ClearLastCreated();
662 SMESH_CATCH( SMESH::throwCorbaException );
665 //=======================================================================
667 * Returns description of an error/warning occurred during the last operation
668 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
670 //=======================================================================
672 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
673 throw (SALOME::SALOME_Exception)
676 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
677 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
678 if ( errIn && !errIn->IsOK() )
680 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
681 errOut->comment = errIn->myComment.c_str();
682 errOut->subShapeID = -1;
683 errOut->hasBadMesh = !errIn->myBadElements.empty();
688 errOut->subShapeID = -1;
689 errOut->hasBadMesh = false;
692 return errOut._retn();
693 SMESH_CATCH( SMESH::throwCorbaException );
697 //=======================================================================
698 //function : MakeIDSource
699 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
700 // Call UnRegister() as you fininsh using it!!
701 //=======================================================================
703 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
704 public virtual SALOME::GenericObj_i
706 SMESH::long_array _ids;
707 SMESH::ElementType _type;
708 SMESH::SMESH_Mesh_ptr _mesh;
709 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
710 SMESH::long_array* GetMeshInfo() { return 0; }
711 SMESH::long_array* GetNbElementsByType()
713 SMESH::long_array_var aRes = new SMESH::long_array();
714 aRes->length(SMESH::NB_ELEMENT_TYPES);
715 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
716 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
719 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
720 bool IsMeshInfoCorrect() { return true; }
721 SMESH::array_of_ElementType* GetTypes()
723 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
724 if ( _ids.length() > 0 ) {
728 return types._retn();
730 SALOMEDS::TMPFile* GetVtkUgStream()
732 SALOMEDS::TMPFile_var SeqFile;
733 return SeqFile._retn();
737 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
738 SMESH::ElementType type)
740 _IDSource* idSrc = new _IDSource;
741 idSrc->_mesh = myMesh_i->_this();
744 if ( type == SMESH::ALL && ids.length() > 0 )
745 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
747 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
749 return anIDSourceVar._retn();
752 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
754 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
757 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
760 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
762 nbIds = (int) tmpIdSource->_ids.length();
763 return & tmpIdSource->_ids[0];
769 // void SMESH_MeshEditor_i::deleteAuxIDSources()
771 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
772 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
774 // myAuxIDSources.clear();
777 //=============================================================================
781 //=============================================================================
784 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
785 throw (SALOME::SALOME_Exception)
792 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
793 IdList.push_back( IDsOfElements[i] );
795 // Update Python script
796 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
799 bool ret = getEditor().Remove( IdList, false );
801 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
804 SMESH_CATCH( SMESH::throwCorbaException );
808 //=============================================================================
812 //=============================================================================
814 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
815 throw (SALOME::SALOME_Exception)
821 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
822 IdList.push_back( IDsOfNodes[i] );
824 // Update Python script
825 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
827 bool ret = getEditor().Remove( IdList, true );
829 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
832 SMESH_CATCH( SMESH::throwCorbaException );
836 //=============================================================================
840 //=============================================================================
842 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
843 throw (SALOME::SALOME_Exception)
848 // Update Python script
849 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
851 // Create filter to find all orphan nodes
852 SMESH::Controls::Filter::TIdSequence seq;
853 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
854 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
856 // remove orphan nodes (if there are any)
857 list< int > IdList( seq.begin(), seq.end() );
859 int nbNodesBefore = myMesh->NbNodes();
860 getEditor().Remove( IdList, true );
861 int nbNodesAfter = myMesh->NbNodes();
863 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
864 return nbNodesBefore - nbNodesAfter;
866 SMESH_CATCH( SMESH::throwCorbaException );
870 //=============================================================================
874 //=============================================================================
876 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
877 throw (SALOME::SALOME_Exception)
882 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
884 // Update Python script
885 TPythonDump() << "nodeID = " << this << ".AddNode( "
886 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
888 declareMeshModified( /*isReComputeSafe=*/false );
891 SMESH_CATCH( SMESH::throwCorbaException );
895 //=============================================================================
897 * Create 0D element on the given node.
899 //=============================================================================
901 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode,
902 CORBA::Boolean DuplicateElements)
903 throw (SALOME::SALOME_Exception)
908 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
909 SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
911 SMDS_MeshElement* elem = 0;
912 if ( DuplicateElements || !it0D->more() )
913 elem = getMeshDS()->Add0DElement(aNode);
915 // Update Python script
916 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
918 declareMeshModified( /*isReComputeSafe=*/false );
920 return elem ? elem->GetID() : 0;
922 SMESH_CATCH( SMESH::throwCorbaException );
926 //=============================================================================
928 * Create a ball element on the given node.
930 //=============================================================================
932 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
933 throw (SALOME::SALOME_Exception)
938 if ( diameter < std::numeric_limits<double>::min() )
939 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
941 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
942 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
944 // Update Python script
945 TPythonDump() << "ballElem = "
946 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
948 declareMeshModified( /*isReComputeSafe=*/false );
949 return elem ? elem->GetID() : 0;
951 SMESH_CATCH( SMESH::throwCorbaException );
955 //=============================================================================
957 * Create an edge, either linear and quadratic (this is determed
958 * by number of given nodes, two or three)
960 //=============================================================================
962 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
963 throw (SALOME::SALOME_Exception)
968 int NbNodes = IDsOfNodes.length();
969 SMDS_MeshElement* elem = 0;
972 CORBA::Long index1 = IDsOfNodes[0];
973 CORBA::Long index2 = IDsOfNodes[1];
974 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
975 getMeshDS()->FindNode(index2));
977 // Update Python script
978 TPythonDump() << "edge = " << this << ".AddEdge([ "
979 << index1 << ", " << index2 <<" ])";
982 CORBA::Long n1 = IDsOfNodes[0];
983 CORBA::Long n2 = IDsOfNodes[1];
984 CORBA::Long n12 = IDsOfNodes[2];
985 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
986 getMeshDS()->FindNode(n2),
987 getMeshDS()->FindNode(n12));
988 // Update Python script
989 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
990 <<n1<<", "<<n2<<", "<<n12<<" ])";
993 declareMeshModified( /*isReComputeSafe=*/false );
994 return elem ? elem->GetID() : 0;
996 SMESH_CATCH( SMESH::throwCorbaException );
1000 //=============================================================================
1004 //=============================================================================
1006 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1007 throw (SALOME::SALOME_Exception)
1012 int NbNodes = IDsOfNodes.length();
1018 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1019 for (int i = 0; i < NbNodes; i++)
1020 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1022 SMDS_MeshElement* elem = 0;
1024 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1025 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1026 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1027 nodes[4], nodes[5]); break;
1028 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1029 nodes[4], nodes[5], nodes[6]); break;
1030 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1031 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1032 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1033 nodes[4], nodes[5], nodes[6], nodes[7],
1035 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1038 // Update Python script
1039 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1041 declareMeshModified( /*isReComputeSafe=*/false );
1043 return elem ? elem->GetID() : 0;
1045 SMESH_CATCH( SMESH::throwCorbaException );
1049 //=============================================================================
1053 //=============================================================================
1055 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1056 throw (SALOME::SALOME_Exception)
1061 int NbNodes = IDsOfNodes.length();
1062 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1063 for (int i = 0; i < NbNodes; i++)
1064 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1067 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1069 // Update Python script
1070 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1072 declareMeshModified( /*isReComputeSafe=*/false );
1073 return elem ? elem->GetID() : 0;
1075 SMESH_CATCH( SMESH::throwCorbaException );
1079 //=============================================================================
1081 * AddQuadPolygonalFace
1083 //=============================================================================
1085 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1086 throw (SALOME::SALOME_Exception)
1091 int NbNodes = IDsOfNodes.length();
1092 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1093 for (int i = 0; i < NbNodes; i++)
1094 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1096 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1098 // Update Python script
1099 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1101 declareMeshModified( /*isReComputeSafe=*/false );
1102 return elem ? elem->GetID() : 0;
1104 SMESH_CATCH( SMESH::throwCorbaException );
1108 //=============================================================================
1110 * Create volume, either linear and quadratic (this is determed
1111 * by number of given nodes)
1113 //=============================================================================
1115 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1116 throw (SALOME::SALOME_Exception)
1121 int NbNodes = IDsOfNodes.length();
1122 vector< const SMDS_MeshNode*> n(NbNodes);
1123 for(int i=0;i<NbNodes;i++)
1124 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1126 SMDS_MeshElement* elem = 0;
1129 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1130 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1131 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1132 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1133 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1134 n[6],n[7],n[8],n[9]);
1136 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1137 n[6],n[7],n[8],n[9],n[10],n[11]);
1139 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1140 n[7],n[8],n[9],n[10],n[11],n[12]);
1142 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1143 n[9],n[10],n[11],n[12],n[13],n[14]);
1145 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1146 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1147 n[15],n[16],n[17],n[18],n[19]);
1149 case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1150 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1153 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1154 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1155 n[15],n[16],n[17],n[18],n[19],
1156 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1160 // Update Python script
1161 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1163 declareMeshModified( /*isReComputeSafe=*/false );
1164 return elem ? elem->GetID() : 0;
1166 SMESH_CATCH( SMESH::throwCorbaException );
1170 //=============================================================================
1172 * AddPolyhedralVolume
1174 //=============================================================================
1175 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1176 const SMESH::long_array & Quantities)
1177 throw (SALOME::SALOME_Exception)
1182 int NbNodes = IDsOfNodes.length();
1183 std::vector<const SMDS_MeshNode*> n (NbNodes);
1184 for (int i = 0; i < NbNodes; i++)
1186 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1187 if (!aNode) return 0;
1191 int NbFaces = Quantities.length();
1192 std::vector<int> q (NbFaces);
1193 for (int j = 0; j < NbFaces; j++)
1194 q[j] = Quantities[j];
1196 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1198 // Update Python script
1199 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1200 << IDsOfNodes << ", " << Quantities << " )";
1202 declareMeshModified( /*isReComputeSafe=*/false );
1203 return elem ? elem->GetID() : 0;
1205 SMESH_CATCH( SMESH::throwCorbaException );
1209 //=============================================================================
1211 * AddPolyhedralVolumeByFaces
1213 //=============================================================================
1215 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1216 throw (SALOME::SALOME_Exception)
1221 int NbFaces = IdsOfFaces.length();
1222 std::vector<const SMDS_MeshNode*> poly_nodes;
1223 std::vector<int> quantities (NbFaces);
1225 for (int i = 0; i < NbFaces; i++) {
1226 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1227 quantities[i] = aFace->NbNodes();
1229 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1230 while (It->more()) {
1231 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1235 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1237 // Update Python script
1238 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1239 << IdsOfFaces << " )";
1241 declareMeshModified( /*isReComputeSafe=*/false );
1242 return elem ? elem->GetID() : 0;
1244 SMESH_CATCH( SMESH::throwCorbaException );
1248 //=============================================================================
1250 // \brief Create 0D elements on all nodes of the given object.
1251 // \param theObject object on whose nodes 0D elements will be created.
1252 // \param theGroupName optional name of a group to add 0D elements created
1253 // and/or found on nodes of \a theObject.
1254 // \param DuplicateElements to add one more 0D element to a node or not.
1255 // \return an object (a new group or a temporary SMESH_IDSource) holding
1256 // ids of new and/or found 0D elements.
1258 //=============================================================================
1260 SMESH::SMESH_IDSource_ptr
1261 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1262 const char* theGroupName,
1263 CORBA::Boolean theDuplicateElements)
1264 throw (SALOME::SALOME_Exception)
1269 SMESH::SMESH_IDSource_var result;
1272 TIDSortedElemSet elements, elems0D;
1273 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1274 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1276 SMESH::long_array_var newElems = new SMESH::long_array;
1277 newElems->length( elems0D.size() );
1278 TIDSortedElemSet::iterator eIt = elems0D.begin();
1279 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1280 newElems[ i ] = (*eIt)->GetID();
1282 SMESH::SMESH_GroupBase_var groupToFill;
1283 if ( theGroupName && strlen( theGroupName ))
1285 // Get existing group named theGroupName
1286 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1287 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1288 SMESH::SMESH_GroupBase_var group = groups[i];
1289 if ( !group->_is_nil() ) {
1290 CORBA::String_var name = group->GetName();
1291 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1292 groupToFill = group;
1297 if ( groupToFill->_is_nil() )
1298 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1299 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1300 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1303 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1305 group_i->Add( newElems );
1306 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1307 pyDump << groupToFill;
1311 result = MakeIDSource( newElems, SMESH::ELEM0D );
1312 pyDump << "elem0DIDs";
1315 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1316 << theObject << ", '" << theGroupName << "' )";
1318 return result._retn();
1320 SMESH_CATCH( SMESH::throwCorbaException );
1324 //=============================================================================
1326 * \brief Bind a node to a vertex
1327 * \param NodeID - node ID
1328 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1329 * \retval boolean - false if NodeID or VertexID is invalid
1331 //=============================================================================
1333 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1334 throw (SALOME::SALOME_Exception)
1338 SMESHDS_Mesh * mesh = getMeshDS();
1339 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1341 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1343 if ( mesh->MaxShapeIndex() < VertexID )
1344 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1346 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1347 if ( shape.ShapeType() != TopAbs_VERTEX )
1348 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1350 mesh->SetNodeOnVertex( node, VertexID );
1352 myMesh->SetIsModified( true );
1354 SMESH_CATCH( SMESH::throwCorbaException );
1357 //=============================================================================
1359 * \brief Store node position on an edge
1360 * \param NodeID - node ID
1361 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1362 * \param paramOnEdge - parameter on edge where the node is located
1363 * \retval boolean - false if any parameter is invalid
1365 //=============================================================================
1367 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1368 CORBA::Double paramOnEdge)
1369 throw (SALOME::SALOME_Exception)
1373 SMESHDS_Mesh * mesh = getMeshDS();
1374 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1376 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1378 if ( mesh->MaxShapeIndex() < EdgeID )
1379 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1381 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1382 if ( shape.ShapeType() != TopAbs_EDGE )
1383 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1386 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1387 if ( paramOnEdge < f || paramOnEdge > l )
1388 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1390 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1392 myMesh->SetIsModified( true );
1394 SMESH_CATCH( SMESH::throwCorbaException );
1397 //=============================================================================
1399 * \brief Store node position on a face
1400 * \param NodeID - node ID
1401 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1402 * \param u - U parameter on face where the node is located
1403 * \param v - V parameter on face where the node is located
1404 * \retval boolean - false if any parameter is invalid
1406 //=============================================================================
1408 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1409 CORBA::Double u, CORBA::Double v)
1410 throw (SALOME::SALOME_Exception)
1413 SMESHDS_Mesh * mesh = getMeshDS();
1414 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1416 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1418 if ( mesh->MaxShapeIndex() < FaceID )
1419 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1421 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1422 if ( shape.ShapeType() != TopAbs_FACE )
1423 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1425 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1426 bool isOut = ( u < surf.FirstUParameter() ||
1427 u > surf.LastUParameter() ||
1428 v < surf.FirstVParameter() ||
1429 v > surf.LastVParameter() );
1433 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1434 << " u( " << surf.FirstUParameter()
1435 << "," << surf.LastUParameter()
1436 << ") v( " << surf.FirstVParameter()
1437 << "," << surf.LastVParameter() << ")" );
1439 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1442 mesh->SetNodeOnFace( node, FaceID, u, v );
1443 myMesh->SetIsModified( true );
1445 SMESH_CATCH( SMESH::throwCorbaException );
1448 //=============================================================================
1450 * \brief Bind a node to a solid
1451 * \param NodeID - node ID
1452 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1453 * \retval boolean - false if NodeID or SolidID is invalid
1455 //=============================================================================
1457 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1458 throw (SALOME::SALOME_Exception)
1461 SMESHDS_Mesh * mesh = getMeshDS();
1462 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1464 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1466 if ( mesh->MaxShapeIndex() < SolidID )
1467 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1469 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1470 if ( shape.ShapeType() != TopAbs_SOLID &&
1471 shape.ShapeType() != TopAbs_SHELL)
1472 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1474 mesh->SetNodeInVolume( node, SolidID );
1476 SMESH_CATCH( SMESH::throwCorbaException );
1479 //=============================================================================
1481 * \brief Bind an element to a shape
1482 * \param ElementID - element ID
1483 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1485 //=============================================================================
1487 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1488 CORBA::Long ShapeID)
1489 throw (SALOME::SALOME_Exception)
1492 SMESHDS_Mesh * mesh = getMeshDS();
1493 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1495 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1497 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1498 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1500 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1501 if ( shape.ShapeType() != TopAbs_EDGE &&
1502 shape.ShapeType() != TopAbs_FACE &&
1503 shape.ShapeType() != TopAbs_SOLID &&
1504 shape.ShapeType() != TopAbs_SHELL )
1505 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1507 mesh->SetMeshElementOnShape( elem, ShapeID );
1509 myMesh->SetIsModified( true );
1511 SMESH_CATCH( SMESH::throwCorbaException );
1514 //=============================================================================
1518 //=============================================================================
1520 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1521 CORBA::Long NodeID2)
1522 throw (SALOME::SALOME_Exception)
1527 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1528 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1532 // Update Python script
1533 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1534 << NodeID1 << ", " << NodeID2 << " )";
1536 int ret = getEditor().InverseDiag ( n1, n2 );
1538 declareMeshModified( /*isReComputeSafe=*/false );
1541 SMESH_CATCH( SMESH::throwCorbaException );
1545 //=============================================================================
1549 //=============================================================================
1551 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1552 CORBA::Long NodeID2)
1553 throw (SALOME::SALOME_Exception)
1558 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1559 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1563 // Update Python script
1564 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1565 << NodeID1 << ", " << NodeID2 << " )";
1568 bool stat = getEditor().DeleteDiag ( n1, n2 );
1570 declareMeshModified( /*isReComputeSafe=*/!stat );
1574 SMESH_CATCH( SMESH::throwCorbaException );
1578 //=============================================================================
1582 //=============================================================================
1584 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1585 throw (SALOME::SALOME_Exception)
1590 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1592 CORBA::Long index = IDsOfElements[i];
1593 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1595 getEditor().Reorient( elem );
1597 // Update Python script
1598 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1600 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1603 SMESH_CATCH( SMESH::throwCorbaException );
1607 //=============================================================================
1611 //=============================================================================
1613 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1614 throw (SALOME::SALOME_Exception)
1619 TPythonDump aTPythonDump; // suppress dump in Reorient()
1621 prepareIdSource( theObject );
1623 SMESH::long_array_var anElementsId = theObject->GetIDs();
1624 CORBA::Boolean isDone = Reorient(anElementsId);
1626 // Update Python script
1627 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1629 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1632 SMESH_CATCH( SMESH::throwCorbaException );
1636 //=======================================================================
1637 //function : Reorient2D
1638 //purpose : Reorient faces contained in \a the2Dgroup.
1639 // the2Dgroup - the mesh or its part to reorient
1640 // theDirection - desired direction of normal of \a theFace
1641 // theFace - ID of face whose orientation is checked.
1642 // It can be < 1 then \a thePoint is used to find a face.
1643 // thePoint - is used to find a face if \a theFace < 1.
1644 // return number of reoriented elements.
1645 //=======================================================================
1647 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1648 const SMESH::DirStruct& theDirection,
1649 CORBA::Long theFace,
1650 const SMESH::PointStruct& thePoint)
1651 throw (SALOME::SALOME_Exception)
1654 initData(/*deleteSearchers=*/false);
1656 TIDSortedElemSet elements;
1657 IDSource_Error error;
1658 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1659 if ( error == IDSource_EMPTY )
1661 if ( error == IDSource_INVALID )
1662 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1665 const SMDS_MeshElement* face = 0;
1668 face = getMeshDS()->FindElement( theFace );
1670 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1671 if ( face->GetType() != SMDSAbs_Face )
1672 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1676 // create theElementSearcher if needed
1677 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1678 if ( !theElementSearcher )
1680 if ( elements.empty() ) // search in the whole mesh
1682 if ( myMesh->NbFaces() == 0 )
1683 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1685 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1689 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1690 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1692 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1696 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1697 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1700 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1701 if ( !elements.empty() && !elements.count( face ))
1702 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1705 const SMESH::PointStruct * P = &theDirection.PS;
1706 gp_Vec dirVec( P->x, P->y, P->z );
1707 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1708 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1710 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1713 declareMeshModified( /*isReComputeSafe=*/false );
1715 TPythonDump() << this << ".Reorient2D( "
1716 << the2Dgroup << ", "
1717 << theDirection << ", "
1719 << thePoint << " )";
1723 SMESH_CATCH( SMESH::throwCorbaException );
1727 //=======================================================================
1728 //function : Reorient2DBy3D
1729 //purpose : Reorient faces basing on orientation of adjacent volumes.
1730 //=======================================================================
1732 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1733 SMESH::SMESH_IDSource_ptr volumeGroup,
1734 CORBA::Boolean outsideNormal)
1735 throw (SALOME::SALOME_Exception)
1740 TIDSortedElemSet volumes;
1741 IDSource_Error volsError;
1742 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1745 for ( size_t i = 0; i < faceGroups.length(); ++i )
1747 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1749 TIDSortedElemSet faces;
1750 IDSource_Error error;
1751 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1752 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1753 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1754 if ( error == IDSource_OK && volsError != IDSource_OK )
1755 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1757 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1759 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1764 declareMeshModified( /*isReComputeSafe=*/false );
1766 TPythonDump() << this << ".Reorient2DBy3D( "
1767 << faceGroups << ", "
1768 << volumeGroup << ", "
1769 << outsideNormal << " )";
1773 SMESH_CATCH( SMESH::throwCorbaException );
1777 //=============================================================================
1779 * \brief Fuse neighbour triangles into quadrangles.
1781 //=============================================================================
1783 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1784 SMESH::NumericalFunctor_ptr Criterion,
1785 CORBA::Double MaxAngle)
1786 throw (SALOME::SALOME_Exception)
1791 SMESHDS_Mesh* aMesh = getMeshDS();
1792 TIDSortedElemSet faces,copyFaces;
1793 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1794 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1795 TIDSortedElemSet* workElements = & faces;
1797 if ( myIsPreviewMode ) {
1798 SMDSAbs_ElementType select = SMDSAbs_Face;
1799 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1800 workElements = & copyFaces;
1803 SMESH::NumericalFunctor_i* aNumericalFunctor =
1804 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1805 SMESH::Controls::NumericalFunctorPtr aCrit;
1806 if ( !aNumericalFunctor )
1807 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1809 aCrit = aNumericalFunctor->GetNumericalFunctor();
1811 if ( !myIsPreviewMode ) {
1812 // Update Python script
1813 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1814 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1817 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1819 declareMeshModified( /*isReComputeSafe=*/!stat );
1822 SMESH_CATCH( SMESH::throwCorbaException );
1826 //=============================================================================
1828 * \brief Fuse neighbour triangles into quadrangles.
1830 //=============================================================================
1832 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1833 SMESH::NumericalFunctor_ptr Criterion,
1834 CORBA::Double MaxAngle)
1835 throw (SALOME::SALOME_Exception)
1840 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1842 prepareIdSource( theObject );
1843 SMESH::long_array_var anElementsId = theObject->GetIDs();
1844 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1846 if ( !myIsPreviewMode ) {
1847 SMESH::NumericalFunctor_i* aNumericalFunctor =
1848 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1850 // Update Python script
1851 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1852 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1857 SMESH_CATCH( SMESH::throwCorbaException );
1861 //=============================================================================
1863 * \brief Split quadrangles into triangles.
1865 //=============================================================================
1867 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1868 SMESH::NumericalFunctor_ptr Criterion)
1869 throw (SALOME::SALOME_Exception)
1874 SMESHDS_Mesh* aMesh = getMeshDS();
1875 TIDSortedElemSet faces;
1876 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1878 SMESH::NumericalFunctor_i* aNumericalFunctor =
1879 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1880 SMESH::Controls::NumericalFunctorPtr aCrit;
1881 if ( !aNumericalFunctor )
1882 aCrit.reset( new SMESH::Controls::AspectRatio() );
1884 aCrit = aNumericalFunctor->GetNumericalFunctor();
1887 // Update Python script
1888 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1890 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1892 declareMeshModified( /*isReComputeSafe=*/false );
1895 SMESH_CATCH( SMESH::throwCorbaException );
1899 //=============================================================================
1901 * \brief Split quadrangles into triangles.
1903 //=============================================================================
1905 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1906 SMESH::NumericalFunctor_ptr Criterion)
1907 throw (SALOME::SALOME_Exception)
1912 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1914 prepareIdSource( theObject );
1915 SMESH::long_array_var anElementsId = theObject->GetIDs();
1916 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1918 SMESH::NumericalFunctor_i* aNumericalFunctor =
1919 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1921 // Update Python script
1922 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1924 declareMeshModified( /*isReComputeSafe=*/false );
1927 SMESH_CATCH( SMESH::throwCorbaException );
1931 //================================================================================
1933 * \brief Split each of quadrangles into 4 triangles.
1934 * \param [in] theObject - theQuads Container of quadrangles to split.
1936 //================================================================================
1938 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1939 throw (SALOME::SALOME_Exception)
1944 TIDSortedElemSet faces;
1945 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1947 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1949 getEditor().QuadTo4Tri( faces );
1950 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1952 SMESH_CATCH( SMESH::throwCorbaException );
1955 //=============================================================================
1957 * \brief Split quadrangles into triangles.
1959 //=============================================================================
1961 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1962 CORBA::Boolean Diag13)
1963 throw (SALOME::SALOME_Exception)
1968 SMESHDS_Mesh* aMesh = getMeshDS();
1969 TIDSortedElemSet faces;
1970 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1972 // Update Python script
1973 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1974 << IDsOfElements << ", " << Diag13 << " )";
1976 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1978 declareMeshModified( /*isReComputeSafe=*/ !stat );
1981 SMESH_CATCH( SMESH::throwCorbaException );
1985 //=============================================================================
1987 * \brief Split quadrangles into triangles.
1989 //=============================================================================
1991 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1992 CORBA::Boolean Diag13)
1993 throw (SALOME::SALOME_Exception)
1998 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2000 prepareIdSource( theObject );
2001 SMESH::long_array_var anElementsId = theObject->GetIDs();
2002 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2004 // Update Python script
2005 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2006 << theObject << ", " << Diag13 << " )";
2008 declareMeshModified( /*isReComputeSafe=*/!isDone );
2011 SMESH_CATCH( SMESH::throwCorbaException );
2016 //=============================================================================
2018 * Find better splitting of the given quadrangle.
2019 * \param IDOfQuad ID of the quadrangle to be split.
2020 * \param Criterion A criterion to choose a diagonal for splitting.
2021 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2022 * diagonal is better, 0 if error occurs.
2024 //=============================================================================
2026 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2027 SMESH::NumericalFunctor_ptr Criterion)
2028 throw (SALOME::SALOME_Exception)
2033 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2034 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2036 SMESH::NumericalFunctor_i* aNumericalFunctor =
2037 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2038 SMESH::Controls::NumericalFunctorPtr aCrit;
2039 if (aNumericalFunctor)
2040 aCrit = aNumericalFunctor->GetNumericalFunctor();
2042 aCrit.reset(new SMESH::Controls::AspectRatio());
2044 int id = getEditor().BestSplit(quad, aCrit);
2045 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2049 SMESH_CATCH( SMESH::throwCorbaException );
2053 //================================================================================
2055 * \brief Split volumic elements into tetrahedrons
2057 //================================================================================
2059 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2060 CORBA::Short methodFlags)
2061 throw (SALOME::SALOME_Exception)
2066 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2067 const int noneFacet = -1;
2068 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2069 while( volIt->more() )
2070 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2072 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2073 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2075 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2076 << elems << ", " << methodFlags << " )";
2078 SMESH_CATCH( SMESH::throwCorbaException );
2081 //================================================================================
2083 * \brief Split hexahedra into triangular prisms
2084 * \param elems - elements to split
2085 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2086 * to split into triangles
2087 * \param methodFlags - flags passing splitting method:
2088 * 1 - split the hexahedron into 2 prisms
2089 * 2 - split the hexahedron into 4 prisms
2091 //================================================================================
2093 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2094 const SMESH::PointStruct & startHexPoint,
2095 const SMESH::DirStruct& facetToSplitNormal,
2096 CORBA::Short methodFlags,
2097 CORBA::Boolean allDomains)
2098 throw (SALOME::SALOME_Exception)
2102 prepareIdSource( elems );
2104 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2107 gp_Dir( facetToSplitNormal.PS.x,
2108 facetToSplitNormal.PS.y,
2109 facetToSplitNormal.PS.z ));
2110 TIDSortedElemSet elemSet;
2111 SMESH::long_array_var anElementsId = elems->GetIDs();
2112 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2113 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2115 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2116 while ( !elemSet.empty() )
2118 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2122 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2123 for ( ; ef != elemFacets.end(); ++ef )
2124 elemSet.erase( ef->first );
2127 if ( methodFlags == 2 )
2128 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2130 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2132 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2133 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2135 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2137 << startHexPoint << ", "
2138 << facetToSplitNormal<< ", "
2139 << methodFlags<< ", "
2140 << allDomains << " )";
2142 SMESH_CATCH( SMESH::throwCorbaException );
2145 //================================================================================
2147 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2148 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2149 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2150 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2151 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2152 * will be split in order to keep the mesh conformal.
2153 * \param elems - elements to split
2155 //================================================================================
2157 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2158 throw (SALOME::SALOME_Exception)
2163 TIDSortedElemSet elemSet;
2164 for ( size_t i = 0; i < theElems.length(); ++i )
2166 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2167 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2168 if ( mesh->GetId() != myMesh_i->GetId() )
2169 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2171 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2173 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2175 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2177 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2178 << theElems << " )";
2180 SMESH_CATCH( SMESH::throwCorbaException );
2183 //=======================================================================
2186 //=======================================================================
2189 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2190 const SMESH::long_array & IDsOfFixedNodes,
2191 CORBA::Long MaxNbOfIterations,
2192 CORBA::Double MaxAspectRatio,
2193 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2194 throw (SALOME::SALOME_Exception)
2196 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2197 MaxAspectRatio, Method, false );
2201 //=======================================================================
2202 //function : SmoothParametric
2204 //=======================================================================
2207 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2208 const SMESH::long_array & IDsOfFixedNodes,
2209 CORBA::Long MaxNbOfIterations,
2210 CORBA::Double MaxAspectRatio,
2211 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2212 throw (SALOME::SALOME_Exception)
2214 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2215 MaxAspectRatio, Method, true );
2219 //=======================================================================
2220 //function : SmoothObject
2222 //=======================================================================
2225 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2226 const SMESH::long_array & IDsOfFixedNodes,
2227 CORBA::Long MaxNbOfIterations,
2228 CORBA::Double MaxAspectRatio,
2229 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2230 throw (SALOME::SALOME_Exception)
2232 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2233 MaxAspectRatio, Method, false);
2237 //=======================================================================
2238 //function : SmoothParametricObject
2240 //=======================================================================
2243 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2244 const SMESH::long_array & IDsOfFixedNodes,
2245 CORBA::Long MaxNbOfIterations,
2246 CORBA::Double MaxAspectRatio,
2247 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2248 throw (SALOME::SALOME_Exception)
2250 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2251 MaxAspectRatio, Method, true);
2255 //=============================================================================
2259 //=============================================================================
2262 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2263 const SMESH::long_array & IDsOfFixedNodes,
2264 CORBA::Long MaxNbOfIterations,
2265 CORBA::Double MaxAspectRatio,
2266 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2268 throw (SALOME::SALOME_Exception)
2273 SMESHDS_Mesh* aMesh = getMeshDS();
2275 TIDSortedElemSet elements;
2276 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2278 set<const SMDS_MeshNode*> fixedNodes;
2279 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2280 CORBA::Long index = IDsOfFixedNodes[i];
2281 const SMDS_MeshNode * node = aMesh->FindNode(index);
2283 fixedNodes.insert( node );
2285 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2286 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2287 method = ::SMESH_MeshEditor::CENTROIDAL;
2289 getEditor().Smooth(elements, fixedNodes, method,
2290 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2292 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2294 // Update Python script
2295 TPythonDump() << "isDone = " << this << "."
2296 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2297 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2298 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2299 << "SMESH.SMESH_MeshEditor."
2300 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2301 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2305 SMESH_CATCH( SMESH::throwCorbaException );
2309 //=============================================================================
2313 //=============================================================================
2316 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2317 const SMESH::long_array & IDsOfFixedNodes,
2318 CORBA::Long MaxNbOfIterations,
2319 CORBA::Double MaxAspectRatio,
2320 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2322 throw (SALOME::SALOME_Exception)
2327 TPythonDump aTPythonDump; // suppress dump in smooth()
2329 prepareIdSource( theObject );
2330 SMESH::long_array_var anElementsId = theObject->GetIDs();
2331 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2332 MaxAspectRatio, Method, IsParametric);
2334 // Update Python script
2335 aTPythonDump << "isDone = " << this << "."
2336 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2337 << theObject << ", " << IDsOfFixedNodes << ", "
2338 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2339 << "SMESH.SMESH_MeshEditor."
2340 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2341 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2345 SMESH_CATCH( SMESH::throwCorbaException );
2349 //=============================================================================
2353 //=============================================================================
2355 void SMESH_MeshEditor_i::RenumberNodes()
2356 throw (SALOME::SALOME_Exception)
2359 // Update Python script
2360 TPythonDump() << this << ".RenumberNodes()";
2362 getMeshDS()->Renumber( true );
2364 SMESH_CATCH( SMESH::throwCorbaException );
2367 //=============================================================================
2371 //=============================================================================
2373 void SMESH_MeshEditor_i::RenumberElements()
2374 throw (SALOME::SALOME_Exception)
2377 // Update Python script
2378 TPythonDump() << this << ".RenumberElements()";
2380 getMeshDS()->Renumber( false );
2382 SMESH_CATCH( SMESH::throwCorbaException );
2385 //=======================================================================
2387 * \brief Return groups by their IDs
2389 //=======================================================================
2391 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2392 throw (SALOME::SALOME_Exception)
2397 myMesh_i->CreateGroupServants();
2398 return myMesh_i->GetGroups( *groupIDs );
2400 SMESH_CATCH( SMESH::throwCorbaException );
2404 //=======================================================================
2405 //function : RotationSweepObjects
2407 //=======================================================================
2409 SMESH::ListOfGroups*
2410 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2411 const SMESH::ListOfIDSources & theEdges,
2412 const SMESH::ListOfIDSources & theFaces,
2413 const SMESH::AxisStruct & theAxis,
2414 CORBA::Double theAngleInRadians,
2415 CORBA::Long theNbOfSteps,
2416 CORBA::Double theTolerance,
2417 const bool theMakeGroups)
2418 throw (SALOME::SALOME_Exception)
2423 TIDSortedElemSet elemsNodes[2];
2424 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2425 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2426 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2428 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2429 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2430 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2431 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2433 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2434 bool makeWalls=true;
2435 if ( myIsPreviewMode )
2437 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2438 TPreviewMesh * tmpMesh = getPreviewMesh();
2439 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2440 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2441 workElements = & copyElements[0];
2442 //makeWalls = false; -- faces are needed for preview
2445 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2447 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2448 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2450 ::SMESH_MeshEditor::PGroupIDs groupIds =
2451 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2452 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2454 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2456 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2458 if ( !myIsPreviewMode )
2460 dumpGroupsList( aPythonDump, aGroups );
2461 aPythonDump << this<< ".RotationSweepObjects( "
2466 << TVar( theAngleInRadians ) << ", "
2467 << TVar( theNbOfSteps ) << ", "
2468 << TVar( theTolerance ) << ", "
2469 << theMakeGroups << " )";
2473 getPreviewMesh()->Remove( SMDSAbs_Volume );
2476 return aGroups ? aGroups : new SMESH::ListOfGroups;
2478 SMESH_CATCH( SMESH::throwCorbaException );
2482 namespace MeshEditor_I
2485 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2487 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2489 bool myIsExtrusionByNormal;
2491 static int makeFlags( CORBA::Boolean MakeGroups,
2492 CORBA::Boolean LinearVariation = false,
2493 CORBA::Boolean ByAverageNormal = false,
2494 CORBA::Boolean UseInputElemsOnly = false,
2495 CORBA::Long Flags = 0,
2496 CORBA::Boolean MakeBoundary = true )
2498 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2499 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2500 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2501 if ( LinearVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2502 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2506 ExtrusionParams(const SMESH::DirStruct & theDir,
2507 CORBA::Long theNbOfSteps,
2508 const SMESH::double_array & theScaleFactors,
2509 CORBA::Boolean theLinearVariation,
2510 const SMESH::double_array & theBasePoint,
2511 CORBA::Boolean theMakeGroups):
2512 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2516 toList( theScaleFactors ),
2517 TBasePoint( theBasePoint ),
2518 makeFlags( theMakeGroups, theLinearVariation )),
2519 myIsExtrusionByNormal( false )
2523 ExtrusionParams(const SMESH::DirStruct & theDir,
2524 CORBA::Long theNbOfSteps,
2525 CORBA::Boolean theMakeGroups,
2526 CORBA::Long theExtrFlags,
2527 CORBA::Double theSewTolerance):
2528 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2532 std::list<double>(),
2534 makeFlags( theMakeGroups, false, false, false,
2535 theExtrFlags, false ),
2537 myIsExtrusionByNormal( false )
2540 // params for extrusion by normal
2541 ExtrusionParams(CORBA::Double theStepSize,
2542 CORBA::Long theNbOfSteps,
2543 CORBA::Short theDim,
2544 CORBA::Boolean theByAverageNormal,
2545 CORBA::Boolean theUseInputElemsOnly,
2546 CORBA::Boolean theMakeGroups ):
2547 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2549 makeFlags( theMakeGroups, false,
2550 theByAverageNormal, theUseInputElemsOnly ),
2552 myIsExtrusionByNormal( true )
2558 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2563 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2565 std::list<double> scales;
2566 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2567 scales.push_back( theScaleFactors[i] );
2571 // structure used to convert SMESH::double_array to gp_XYZ*
2575 TBasePoint( const SMESH::double_array & theBasePoint )
2578 if ( theBasePoint.length() == 3 )
2580 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2584 operator const gp_XYZ*() const { return pp; }
2589 //=======================================================================
2591 * \brief Generate dim+1 elements by extrusion of elements along vector
2592 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2593 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2594 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2595 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2596 * \param [in] nbOfSteps - number of elements to generate from one element
2597 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2598 * corresponding to groups the input elements included in.
2599 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2601 //=======================================================================
2603 SMESH::ListOfGroups*
2604 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2605 const SMESH::ListOfIDSources & theEdges,
2606 const SMESH::ListOfIDSources & theFaces,
2607 const SMESH::DirStruct & theStepVector,
2608 CORBA::Long theNbOfSteps,
2609 const SMESH::double_array & theScaleFactors,
2610 CORBA::Boolean theLinearVariation,
2611 const SMESH::double_array & theBasePoint,
2612 CORBA::Boolean theToMakeGroups)
2613 throw (SALOME::SALOME_Exception)
2618 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
2619 theLinearVariation, theBasePoint, theToMakeGroups );
2621 TIDSortedElemSet elemsNodes[2];
2622 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2623 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2624 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2626 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2627 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2628 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2629 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2631 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2632 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2633 if ( myIsPreviewMode )
2635 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2636 // previewType = SMDSAbs_Edge;
2638 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2639 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2640 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2641 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2642 workElements = & copyElements[0];
2644 params.SetNoGroups();
2646 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2648 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2649 ::SMESH_MeshEditor::PGroupIDs groupIds =
2650 getEditor().ExtrusionSweep( workElements, params, aHistory );
2652 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2654 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2656 if ( !myIsPreviewMode )
2658 dumpGroupsList( aPythonDump, aGroups );
2659 aPythonDump << this<< ".ExtrusionSweepObjects( "
2663 << theStepVector << ", "
2664 << TVar( theNbOfSteps ) << ", "
2665 << theToMakeGroups << " )";
2669 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2672 return aGroups ? aGroups : new SMESH::ListOfGroups;
2674 SMESH_CATCH( SMESH::throwCorbaException );
2678 //=======================================================================
2679 //function : ExtrusionByNormal
2681 //=======================================================================
2683 SMESH::ListOfGroups*
2684 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2685 CORBA::Double stepSize,
2686 CORBA::Long nbOfSteps,
2687 CORBA::Boolean byAverageNormal,
2688 CORBA::Boolean useInputElemsOnly,
2689 CORBA::Boolean makeGroups,
2691 throw (SALOME::SALOME_Exception)
2696 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2698 ExtrusionParams params( stepSize, nbOfSteps, dim,
2699 byAverageNormal, useInputElemsOnly, makeGroups );
2701 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2702 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2704 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2705 if (( elemTypes->length() == 1 ) &&
2706 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2707 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2710 TIDSortedElemSet elemsNodes[2];
2711 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2712 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2714 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2715 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2716 if ( myIsPreviewMode )
2718 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2719 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2720 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2721 workElements = & copyElements[0];
2723 params.SetNoGroups();
2726 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2727 ::SMESH_MeshEditor::PGroupIDs groupIds =
2728 getEditor().ExtrusionSweep( workElements, params, aHistory );
2730 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2732 if (!myIsPreviewMode) {
2733 dumpGroupsList(aPythonDump, aGroups);
2734 aPythonDump << this << ".ExtrusionByNormal( " << objects
2735 << ", " << TVar( stepSize )
2736 << ", " << TVar( nbOfSteps )
2737 << ", " << byAverageNormal
2738 << ", " << useInputElemsOnly
2739 << ", " << makeGroups
2745 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2748 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2750 return aGroups ? aGroups : new SMESH::ListOfGroups;
2752 SMESH_CATCH( SMESH::throwCorbaException );
2756 //=======================================================================
2757 //function : AdvancedExtrusion
2759 //=======================================================================
2761 SMESH::ListOfGroups*
2762 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2763 const SMESH::DirStruct & theStepVector,
2764 CORBA::Long theNbOfSteps,
2765 CORBA::Long theExtrFlags,
2766 CORBA::Double theSewTolerance,
2767 CORBA::Boolean theMakeGroups)
2768 throw (SALOME::SALOME_Exception)
2773 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2775 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2776 theExtrFlags, theSewTolerance );
2778 TIDSortedElemSet elemsNodes[2];
2779 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2781 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2782 ::SMESH_MeshEditor::PGroupIDs groupIds =
2783 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2785 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2787 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2789 if ( !myIsPreviewMode ) {
2790 dumpGroupsList(aPythonDump, aGroups);
2791 aPythonDump << this << ".AdvancedExtrusion( "
2792 << theIDsOfElements << ", "
2793 << theStepVector << ", "
2794 << theNbOfSteps << ", "
2795 << theExtrFlags << ", "
2796 << theSewTolerance << ", "
2797 << theMakeGroups << " )";
2801 getPreviewMesh()->Remove( SMDSAbs_Volume );
2804 return aGroups ? aGroups : new SMESH::ListOfGroups;
2806 SMESH_CATCH( SMESH::throwCorbaException );
2810 //================================================================================
2812 * \brief Convert extrusion error to IDL enum
2814 //================================================================================
2818 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2820 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2824 RETCASE( EXTR_NO_ELEMENTS );
2825 RETCASE( EXTR_PATH_NOT_EDGE );
2826 RETCASE( EXTR_BAD_PATH_SHAPE );
2827 RETCASE( EXTR_BAD_STARTING_NODE );
2828 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2829 RETCASE( EXTR_CANT_GET_TANGENT );
2831 return SMESH::SMESH_MeshEditor::EXTR_OK;
2835 //=======================================================================
2836 //function : extrusionAlongPath
2838 //=======================================================================
2839 SMESH::ListOfGroups*
2840 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2841 const SMESH::ListOfIDSources & theEdges,
2842 const SMESH::ListOfIDSources & theFaces,
2843 SMESH::SMESH_IDSource_ptr thePathMesh,
2844 GEOM::GEOM_Object_ptr thePathShape,
2845 CORBA::Long theNodeStart,
2846 CORBA::Boolean theHasAngles,
2847 const SMESH::double_array & theAngles,
2848 CORBA::Boolean theLinearVariation,
2849 CORBA::Boolean theHasRefPoint,
2850 const SMESH::PointStruct & theRefPoint,
2852 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2853 throw (SALOME::SALOME_Exception)
2858 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2860 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2861 if ( thePathMesh->_is_nil() )
2862 return aGroups._retn();
2865 SMESH_subMesh* aSubMesh = 0;
2866 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2867 if ( thePathShape->_is_nil() )
2869 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2870 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2872 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2873 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2874 if ( !aMeshImp ) return aGroups._retn();
2875 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2876 if ( !aSubMesh ) return aGroups._retn();
2878 else if ( !aMeshImp ||
2879 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2881 return aGroups._retn();
2886 if ( !aMeshImp ) return aGroups._retn();
2887 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2888 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2889 if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
2890 return aGroups._retn();
2893 SMDS_MeshNode* nodeStart =
2894 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2896 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2897 return aGroups._retn();
2900 TIDSortedElemSet elemsNodes[2];
2901 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2902 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2903 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2905 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2906 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2907 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2908 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2910 list<double> angles;
2911 for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) {
2912 angles.push_back( theAngles[i] );
2915 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2917 int nbOldGroups = myMesh->NbGroup();
2919 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2920 if ( myIsPreviewMode )
2922 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2923 TPreviewMesh * tmpMesh = getPreviewMesh();
2924 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2925 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2926 workElements = & copyElements[0];
2927 theMakeGroups = false;
2930 ::SMESH_MeshEditor::Extrusion_Error error;
2932 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2933 theHasAngles, angles, theLinearVariation,
2934 theHasRefPoint, refPnt, theMakeGroups );
2936 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2937 theHasAngles, angles, theLinearVariation,
2938 theHasRefPoint, refPnt, theMakeGroups );
2940 declareMeshModified( /*isReComputeSafe=*/true );
2941 theError = convExtrError( error );
2943 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2944 if ( theMakeGroups ) {
2945 list<int> groupIDs = myMesh->GetGroupIds();
2946 list<int>::iterator newBegin = groupIDs.begin();
2947 std::advance( newBegin, nbOldGroups ); // skip old groups
2948 groupIDs.erase( groupIDs.begin(), newBegin );
2949 aGroups = getGroups( & groupIDs );
2950 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2953 if ( !myIsPreviewMode ) {
2954 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2955 else aPythonDump << "(_noGroups, error) = ";
2956 aPythonDump << this << ".ExtrusionAlongPathObjects( "
2960 << thePathMesh << ", "
2961 << thePathShape << ", "
2962 << theNodeStart << ", "
2963 << theHasAngles << ", "
2964 << TVar( theAngles ) << ", "
2965 << theLinearVariation << ", "
2966 << theHasRefPoint << ", "
2967 << "SMESH.PointStruct( "
2968 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2969 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2970 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2971 << theMakeGroups << " )";
2975 getPreviewMesh()->Remove( SMDSAbs_Volume );
2978 return aGroups._retn();
2980 SMESH_CATCH( SMESH::throwCorbaException );
2984 //================================================================================
2986 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2987 * of given angles along path steps
2988 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2989 * which proceeds the extrusion
2990 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2991 * is used to define the sub-mesh for the path
2993 //================================================================================
2995 SMESH::double_array*
2996 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2997 GEOM::GEOM_Object_ptr thePathShape,
2998 const SMESH::double_array & theAngles)
3000 SMESH::double_array_var aResult = new SMESH::double_array();
3001 int nbAngles = theAngles.length();
3002 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3004 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3005 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3006 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3007 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3008 return aResult._retn();
3009 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3010 if ( nbSteps == nbAngles )
3012 aResult.inout() = theAngles;
3016 aResult->length( nbSteps );
3017 double rAn2St = double( nbAngles ) / double( nbSteps );
3018 double angPrev = 0, angle;
3019 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3021 double angCur = rAn2St * ( iSt+1 );
3022 double angCurFloor = floor( angCur );
3023 double angPrevFloor = floor( angPrev );
3024 if ( angPrevFloor == angCurFloor )
3025 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3028 int iP = int( angPrevFloor );
3029 double angPrevCeil = ceil(angPrev);
3030 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3032 int iC = int( angCurFloor );
3033 if ( iC < nbAngles )
3034 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3036 iP = int( angPrevCeil );
3038 angle += theAngles[ iC ];
3040 aResult[ iSt ] = angle;
3045 // Update Python script
3046 TPythonDump() << "rotAngles = " << theAngles;
3047 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3048 << thePathMesh << ", "
3049 << thePathShape << ", "
3052 return aResult._retn();
3055 //=======================================================================
3058 //=======================================================================
3060 SMESH::ListOfGroups*
3061 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3062 const SMESH::AxisStruct & theAxis,
3063 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3064 CORBA::Boolean theCopy,
3066 ::SMESH_Mesh* theTargetMesh)
3067 throw (SALOME::SALOME_Exception)
3072 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3073 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3075 if ( theTargetMesh )
3079 switch ( theMirrorType ) {
3080 case SMESH::SMESH_MeshEditor::POINT:
3081 aTrsf.SetMirror( P );
3083 case SMESH::SMESH_MeshEditor::AXIS:
3084 aTrsf.SetMirror( gp_Ax1( P, V ));
3087 aTrsf.SetMirror( gp_Ax2( P, V ));
3090 TIDSortedElemSet copyElements;
3091 TIDSortedElemSet* workElements = & theElements;
3093 if ( myIsPreviewMode )
3095 TPreviewMesh * tmpMesh = getPreviewMesh();
3096 tmpMesh->Copy( theElements, copyElements);
3097 if ( !theCopy && !theTargetMesh )
3099 TIDSortedElemSet elemsAround, elemsAroundCopy;
3100 getElementsAround( theElements, getMeshDS(), elemsAround );
3101 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3103 workElements = & copyElements;
3104 theMakeGroups = false;
3107 ::SMESH_MeshEditor::PGroupIDs groupIds =
3108 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3110 if ( !myIsPreviewMode )
3112 if ( theTargetMesh )
3113 theTargetMesh->GetMeshDS()->Modified();
3115 declareMeshModified( /*isReComputeSafe=*/false );
3118 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3120 SMESH_CATCH( SMESH::throwCorbaException );
3124 //=======================================================================
3127 //=======================================================================
3129 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3130 const SMESH::AxisStruct & theAxis,
3131 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3132 CORBA::Boolean theCopy)
3133 throw (SALOME::SALOME_Exception)
3135 if ( !myIsPreviewMode ) {
3136 TPythonDump() << this << ".Mirror( "
3137 << theIDsOfElements << ", "
3139 << mirrorTypeName(theMirrorType) << ", "
3142 if ( theIDsOfElements.length() > 0 )
3144 TIDSortedElemSet elements;
3145 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3146 mirror(elements, theAxis, theMirrorType, theCopy, false);
3151 //=======================================================================
3152 //function : MirrorObject
3154 //=======================================================================
3156 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3157 const SMESH::AxisStruct & theAxis,
3158 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3159 CORBA::Boolean theCopy)
3160 throw (SALOME::SALOME_Exception)
3162 if ( !myIsPreviewMode ) {
3163 TPythonDump() << this << ".MirrorObject( "
3164 << theObject << ", "
3166 << mirrorTypeName(theMirrorType) << ", "
3169 TIDSortedElemSet elements;
3171 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3173 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3174 mirror(elements, theAxis, theMirrorType, theCopy, false);
3177 //=======================================================================
3178 //function : MirrorMakeGroups
3180 //=======================================================================
3182 SMESH::ListOfGroups*
3183 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3184 const SMESH::AxisStruct& theMirror,
3185 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3186 throw (SALOME::SALOME_Exception)
3188 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3190 SMESH::ListOfGroups * aGroups = 0;
3191 if ( theIDsOfElements.length() > 0 )
3193 TIDSortedElemSet elements;
3194 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3195 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3197 if (!myIsPreviewMode) {
3198 dumpGroupsList(aPythonDump, aGroups);
3199 aPythonDump << this << ".MirrorMakeGroups( "
3200 << theIDsOfElements << ", "
3201 << theMirror << ", "
3202 << mirrorTypeName(theMirrorType) << " )";
3207 //=======================================================================
3208 //function : MirrorObjectMakeGroups
3210 //=======================================================================
3212 SMESH::ListOfGroups*
3213 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3214 const SMESH::AxisStruct& theMirror,
3215 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3216 throw (SALOME::SALOME_Exception)
3218 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3220 SMESH::ListOfGroups * aGroups = 0;
3221 TIDSortedElemSet elements;
3222 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3223 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3225 if (!myIsPreviewMode)
3227 dumpGroupsList(aPythonDump,aGroups);
3228 aPythonDump << this << ".MirrorObjectMakeGroups( "
3229 << theObject << ", "
3230 << theMirror << ", "
3231 << mirrorTypeName(theMirrorType) << " )";
3236 //=======================================================================
3237 //function : MirrorMakeMesh
3239 //=======================================================================
3241 SMESH::SMESH_Mesh_ptr
3242 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3243 const SMESH::AxisStruct& theMirror,
3244 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3245 CORBA::Boolean theCopyGroups,
3246 const char* theMeshName)
3247 throw (SALOME::SALOME_Exception)
3249 SMESH_Mesh_i* mesh_i;
3250 SMESH::SMESH_Mesh_var mesh;
3251 { // open new scope to dump "MakeMesh" command
3252 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3254 TPythonDump pydump; // to prevent dump at mesh creation
3256 mesh = makeMesh( theMeshName );
3257 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3258 if (mesh_i && theIDsOfElements.length() > 0 )
3260 TIDSortedElemSet elements;
3261 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3262 mirror(elements, theMirror, theMirrorType,
3263 false, theCopyGroups, & mesh_i->GetImpl());
3264 mesh_i->CreateGroupServants();
3267 if (!myIsPreviewMode) {
3268 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3269 << theIDsOfElements << ", "
3270 << theMirror << ", "
3271 << mirrorTypeName(theMirrorType) << ", "
3272 << theCopyGroups << ", '"
3273 << theMeshName << "' )";
3278 if (!myIsPreviewMode && mesh_i)
3279 mesh_i->GetGroups();
3281 return mesh._retn();
3284 //=======================================================================
3285 //function : MirrorObjectMakeMesh
3287 //=======================================================================
3289 SMESH::SMESH_Mesh_ptr
3290 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3291 const SMESH::AxisStruct& theMirror,
3292 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3293 CORBA::Boolean theCopyGroups,
3294 const char* theMeshName)
3295 throw (SALOME::SALOME_Exception)
3297 SMESH_Mesh_i* mesh_i;
3298 SMESH::SMESH_Mesh_var mesh;
3299 { // open new scope to dump "MakeMesh" command
3300 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3302 TPythonDump pydump; // to prevent dump at mesh creation
3304 mesh = makeMesh( theMeshName );
3305 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3306 TIDSortedElemSet elements;
3308 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3310 mirror(elements, theMirror, theMirrorType,
3311 false, theCopyGroups, & mesh_i->GetImpl());
3312 mesh_i->CreateGroupServants();
3314 if (!myIsPreviewMode) {
3315 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3316 << theObject << ", "
3317 << theMirror << ", "
3318 << mirrorTypeName(theMirrorType) << ", "
3319 << theCopyGroups << ", '"
3320 << theMeshName << "' )";
3325 if (!myIsPreviewMode && mesh_i)
3326 mesh_i->GetGroups();
3328 return mesh._retn();
3331 //=======================================================================
3332 //function : translate
3334 //=======================================================================
3336 SMESH::ListOfGroups*
3337 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3338 const SMESH::DirStruct & theVector,
3339 CORBA::Boolean theCopy,
3341 ::SMESH_Mesh* theTargetMesh)
3342 throw (SALOME::SALOME_Exception)
3347 if ( theTargetMesh )
3351 const SMESH::PointStruct * P = &theVector.PS;
3352 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3354 TIDSortedElemSet copyElements;
3355 TIDSortedElemSet* workElements = &theElements;
3357 if ( myIsPreviewMode )
3359 TPreviewMesh * tmpMesh = getPreviewMesh();
3360 tmpMesh->Copy( theElements, copyElements);
3361 if ( !theCopy && !theTargetMesh )
3363 TIDSortedElemSet elemsAround, elemsAroundCopy;
3364 getElementsAround( theElements, getMeshDS(), elemsAround );
3365 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3367 workElements = & copyElements;
3368 theMakeGroups = false;
3371 ::SMESH_MeshEditor::PGroupIDs groupIds =
3372 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3374 if ( !myIsPreviewMode )
3376 if ( theTargetMesh )
3377 theTargetMesh->GetMeshDS()->Modified();
3379 declareMeshModified( /*isReComputeSafe=*/false );
3382 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3384 SMESH_CATCH( SMESH::throwCorbaException );
3388 //=======================================================================
3389 //function : Translate
3391 //=======================================================================
3393 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3394 const SMESH::DirStruct & theVector,
3395 CORBA::Boolean theCopy)
3396 throw (SALOME::SALOME_Exception)
3398 if (!myIsPreviewMode) {
3399 TPythonDump() << this << ".Translate( "
3400 << theIDsOfElements << ", "
3401 << theVector << ", "
3404 if (theIDsOfElements.length()) {
3405 TIDSortedElemSet elements;
3406 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3407 translate(elements, theVector, theCopy, false);
3411 //=======================================================================
3412 //function : TranslateObject
3414 //=======================================================================
3416 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3417 const SMESH::DirStruct & theVector,
3418 CORBA::Boolean theCopy)
3419 throw (SALOME::SALOME_Exception)
3421 if (!myIsPreviewMode) {
3422 TPythonDump() << this << ".TranslateObject( "
3423 << theObject << ", "
3424 << theVector << ", "
3427 TIDSortedElemSet elements;
3429 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3431 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3432 translate(elements, theVector, theCopy, false);
3435 //=======================================================================
3436 //function : TranslateMakeGroups
3438 //=======================================================================
3440 SMESH::ListOfGroups*
3441 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3442 const SMESH::DirStruct& theVector)
3443 throw (SALOME::SALOME_Exception)
3445 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3447 SMESH::ListOfGroups * aGroups = 0;
3448 if (theIDsOfElements.length()) {
3449 TIDSortedElemSet elements;
3450 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3451 aGroups = translate(elements,theVector,true,true);
3453 if (!myIsPreviewMode) {
3454 dumpGroupsList(aPythonDump, aGroups);
3455 aPythonDump << this << ".TranslateMakeGroups( "
3456 << theIDsOfElements << ", "
3457 << theVector << " )";
3462 //=======================================================================
3463 //function : TranslateObjectMakeGroups
3465 //=======================================================================
3467 SMESH::ListOfGroups*
3468 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3469 const SMESH::DirStruct& theVector)
3470 throw (SALOME::SALOME_Exception)
3472 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3474 SMESH::ListOfGroups * aGroups = 0;
3475 TIDSortedElemSet elements;
3476 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3477 aGroups = translate(elements, theVector, true, true);
3479 if (!myIsPreviewMode) {
3480 dumpGroupsList(aPythonDump, aGroups);
3481 aPythonDump << this << ".TranslateObjectMakeGroups( "
3482 << theObject << ", "
3483 << theVector << " )";
3488 //=======================================================================
3489 //function : TranslateMakeMesh
3491 //=======================================================================
3493 SMESH::SMESH_Mesh_ptr
3494 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3495 const SMESH::DirStruct& theVector,
3496 CORBA::Boolean theCopyGroups,
3497 const char* theMeshName)
3498 throw (SALOME::SALOME_Exception)
3500 SMESH_Mesh_i* mesh_i;
3501 SMESH::SMESH_Mesh_var mesh;
3503 { // open new scope to dump "MakeMesh" command
3504 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3506 TPythonDump pydump; // to prevent dump at mesh creation
3508 mesh = makeMesh( theMeshName );
3509 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3511 if ( mesh_i && theIDsOfElements.length() )
3513 TIDSortedElemSet elements;
3514 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3515 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3516 mesh_i->CreateGroupServants();
3519 if ( !myIsPreviewMode ) {
3520 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3521 << theIDsOfElements << ", "
3522 << theVector << ", "
3523 << theCopyGroups << ", '"
3524 << theMeshName << "' )";
3529 if (!myIsPreviewMode && mesh_i)
3530 mesh_i->GetGroups();
3532 return mesh._retn();
3535 //=======================================================================
3536 //function : TranslateObjectMakeMesh
3538 //=======================================================================
3540 SMESH::SMESH_Mesh_ptr
3541 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3542 const SMESH::DirStruct& theVector,
3543 CORBA::Boolean theCopyGroups,
3544 const char* theMeshName)
3545 throw (SALOME::SALOME_Exception)
3548 SMESH_Mesh_i* mesh_i;
3549 SMESH::SMESH_Mesh_var mesh;
3550 { // open new scope to dump "MakeMesh" command
3551 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3553 TPythonDump pydump; // to prevent dump at mesh creation
3554 mesh = makeMesh( theMeshName );
3555 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3557 TIDSortedElemSet elements;
3559 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3561 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3562 mesh_i->CreateGroupServants();
3564 if ( !myIsPreviewMode ) {
3565 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3566 << theObject << ", "
3567 << theVector << ", "
3568 << theCopyGroups << ", '"
3569 << theMeshName << "' )";
3574 if (!myIsPreviewMode && mesh_i)
3575 mesh_i->GetGroups();
3577 return mesh._retn();
3579 SMESH_CATCH( SMESH::throwCorbaException );
3583 //=======================================================================
3586 //=======================================================================
3588 SMESH::ListOfGroups*
3589 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3590 const SMESH::AxisStruct & theAxis,
3591 CORBA::Double theAngle,
3592 CORBA::Boolean theCopy,
3594 ::SMESH_Mesh* theTargetMesh)
3595 throw (SALOME::SALOME_Exception)
3600 if ( theTargetMesh )
3603 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3604 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3607 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3609 TIDSortedElemSet copyElements;
3610 TIDSortedElemSet* workElements = &theElements;
3611 if ( myIsPreviewMode ) {
3612 TPreviewMesh * tmpMesh = getPreviewMesh();
3613 tmpMesh->Copy( theElements, copyElements );
3614 if ( !theCopy && !theTargetMesh )
3616 TIDSortedElemSet elemsAround, elemsAroundCopy;
3617 getElementsAround( theElements, getMeshDS(), elemsAround );
3618 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3620 workElements = ©Elements;
3621 theMakeGroups = false;
3624 ::SMESH_MeshEditor::PGroupIDs groupIds =
3625 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3627 if ( !myIsPreviewMode)
3629 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3630 else declareMeshModified( /*isReComputeSafe=*/false );
3633 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3635 SMESH_CATCH( SMESH::throwCorbaException );
3639 //=======================================================================
3642 //=======================================================================
3644 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3645 const SMESH::AxisStruct & theAxis,
3646 CORBA::Double theAngle,
3647 CORBA::Boolean theCopy)
3648 throw (SALOME::SALOME_Exception)
3650 if (!myIsPreviewMode) {
3651 TPythonDump() << this << ".Rotate( "
3652 << theIDsOfElements << ", "
3654 << TVar( theAngle ) << ", "
3657 if (theIDsOfElements.length() > 0)
3659 TIDSortedElemSet elements;
3660 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3661 rotate(elements,theAxis,theAngle,theCopy,false);
3665 //=======================================================================
3666 //function : RotateObject
3668 //=======================================================================
3670 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3671 const SMESH::AxisStruct & theAxis,
3672 CORBA::Double theAngle,
3673 CORBA::Boolean theCopy)
3674 throw (SALOME::SALOME_Exception)
3676 if ( !myIsPreviewMode ) {
3677 TPythonDump() << this << ".RotateObject( "
3678 << theObject << ", "
3680 << TVar( theAngle ) << ", "
3683 TIDSortedElemSet elements;
3684 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3685 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3686 rotate(elements,theAxis,theAngle,theCopy,false);
3689 //=======================================================================
3690 //function : RotateMakeGroups
3692 //=======================================================================
3694 SMESH::ListOfGroups*
3695 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3696 const SMESH::AxisStruct& theAxis,
3697 CORBA::Double theAngle)
3698 throw (SALOME::SALOME_Exception)
3700 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3702 SMESH::ListOfGroups * aGroups = 0;
3703 if (theIDsOfElements.length() > 0)
3705 TIDSortedElemSet elements;
3706 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3707 aGroups = rotate(elements,theAxis,theAngle,true,true);
3709 if (!myIsPreviewMode) {
3710 dumpGroupsList(aPythonDump, aGroups);
3711 aPythonDump << this << ".RotateMakeGroups( "
3712 << theIDsOfElements << ", "
3714 << TVar( theAngle ) << " )";
3719 //=======================================================================
3720 //function : RotateObjectMakeGroups
3722 //=======================================================================
3724 SMESH::ListOfGroups*
3725 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3726 const SMESH::AxisStruct& theAxis,
3727 CORBA::Double theAngle)
3728 throw (SALOME::SALOME_Exception)
3730 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3732 SMESH::ListOfGroups * aGroups = 0;
3733 TIDSortedElemSet elements;
3734 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3735 aGroups = rotate(elements, theAxis, theAngle, true, true);
3737 if (!myIsPreviewMode) {
3738 dumpGroupsList(aPythonDump, aGroups);
3739 aPythonDump << this << ".RotateObjectMakeGroups( "
3740 << theObject << ", "
3742 << TVar( theAngle ) << " )";
3747 //=======================================================================
3748 //function : RotateMakeMesh
3750 //=======================================================================
3752 SMESH::SMESH_Mesh_ptr
3753 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3754 const SMESH::AxisStruct& theAxis,
3755 CORBA::Double theAngleInRadians,
3756 CORBA::Boolean theCopyGroups,
3757 const char* theMeshName)
3758 throw (SALOME::SALOME_Exception)
3761 SMESH::SMESH_Mesh_var mesh;
3762 SMESH_Mesh_i* mesh_i;
3764 { // open new scope to dump "MakeMesh" command
3765 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3767 TPythonDump pydump; // to prevent dump at mesh creation
3769 mesh = makeMesh( theMeshName );
3770 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3772 if ( mesh_i && theIDsOfElements.length() > 0 )
3774 TIDSortedElemSet elements;
3775 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3776 rotate(elements, theAxis, theAngleInRadians,
3777 false, theCopyGroups, & mesh_i->GetImpl());
3778 mesh_i->CreateGroupServants();
3780 if ( !myIsPreviewMode ) {
3781 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3782 << theIDsOfElements << ", "
3784 << TVar( theAngleInRadians ) << ", "
3785 << theCopyGroups << ", '"
3786 << theMeshName << "' )";
3791 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3792 mesh_i->GetGroups();
3794 return mesh._retn();
3796 SMESH_CATCH( SMESH::throwCorbaException );
3800 //=======================================================================
3801 //function : RotateObjectMakeMesh
3803 //=======================================================================
3805 SMESH::SMESH_Mesh_ptr
3806 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3807 const SMESH::AxisStruct& theAxis,
3808 CORBA::Double theAngleInRadians,
3809 CORBA::Boolean theCopyGroups,
3810 const char* theMeshName)
3811 throw (SALOME::SALOME_Exception)
3814 SMESH::SMESH_Mesh_var mesh;
3815 SMESH_Mesh_i* mesh_i;
3817 {// open new scope to dump "MakeMesh" command
3818 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3820 TPythonDump pydump; // to prevent dump at mesh creation
3821 mesh = makeMesh( theMeshName );
3822 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3824 TIDSortedElemSet elements;
3826 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3828 rotate(elements, theAxis, theAngleInRadians,
3829 false, theCopyGroups, & mesh_i->GetImpl());
3830 mesh_i->CreateGroupServants();
3832 if ( !myIsPreviewMode ) {
3833 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3834 << theObject << ", "
3836 << TVar( theAngleInRadians ) << ", "
3837 << theCopyGroups << ", '"
3838 << theMeshName << "' )";
3843 if (!myIsPreviewMode && mesh_i)
3844 mesh_i->GetGroups();
3846 return mesh._retn();
3848 SMESH_CATCH( SMESH::throwCorbaException );
3852 //=======================================================================
3855 //=======================================================================
3857 SMESH::ListOfGroups*
3858 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3859 const SMESH::PointStruct& thePoint,
3860 const SMESH::double_array& theScaleFact,
3861 CORBA::Boolean theCopy,
3863 ::SMESH_Mesh* theTargetMesh)
3864 throw (SALOME::SALOME_Exception)
3868 if ( theScaleFact.length() < 1 )
3869 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3870 if ( theScaleFact.length() == 2 )
3871 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3873 if ( theTargetMesh )
3876 TIDSortedElemSet elements;
3877 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3878 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3883 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3884 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3888 // fight against orthogonalization
3889 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3890 // 0, S[1], 0, thePoint.y * (1-S[1]),
3891 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3892 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3893 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3894 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3895 loc.SetCoord( thePoint.x * (1-S[0]),
3896 thePoint.y * (1-S[1]),
3897 thePoint.z * (1-S[2]));
3898 M.SetDiagonal( S[0], S[1], S[2] );
3900 TIDSortedElemSet copyElements;
3901 TIDSortedElemSet* workElements = &elements;
3902 if ( myIsPreviewMode )
3904 TPreviewMesh * tmpMesh = getPreviewMesh();
3905 tmpMesh->Copy( elements, copyElements);
3906 if ( !theCopy && !theTargetMesh )
3908 TIDSortedElemSet elemsAround, elemsAroundCopy;
3909 getElementsAround( elements, getMeshDS(), elemsAround );
3910 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3912 workElements = & copyElements;
3913 theMakeGroups = false;
3916 ::SMESH_MeshEditor::PGroupIDs groupIds =
3917 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3919 if ( !myIsPreviewMode )
3921 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3922 else declareMeshModified( /*isReComputeSafe=*/false );
3924 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3926 SMESH_CATCH( SMESH::throwCorbaException );
3930 //=======================================================================
3933 //=======================================================================
3935 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3936 const SMESH::PointStruct& thePoint,
3937 const SMESH::double_array& theScaleFact,
3938 CORBA::Boolean theCopy)
3939 throw (SALOME::SALOME_Exception)
3941 if ( !myIsPreviewMode ) {
3942 TPythonDump() << this << ".Scale( "
3943 << theObject << ", "
3945 << TVar( theScaleFact ) << ", "
3948 scale(theObject, thePoint, theScaleFact, theCopy, false);
3952 //=======================================================================
3953 //function : ScaleMakeGroups
3955 //=======================================================================
3957 SMESH::ListOfGroups*
3958 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3959 const SMESH::PointStruct& thePoint,
3960 const SMESH::double_array& theScaleFact)
3961 throw (SALOME::SALOME_Exception)
3963 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3965 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3966 if (!myIsPreviewMode) {
3967 dumpGroupsList(aPythonDump, aGroups);
3968 aPythonDump << this << ".Scale("
3971 << TVar( theScaleFact ) << ",True,True)";
3977 //=======================================================================
3978 //function : ScaleMakeMesh
3980 //=======================================================================
3982 SMESH::SMESH_Mesh_ptr
3983 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3984 const SMESH::PointStruct& thePoint,
3985 const SMESH::double_array& theScaleFact,
3986 CORBA::Boolean theCopyGroups,
3987 const char* theMeshName)
3988 throw (SALOME::SALOME_Exception)
3990 SMESH_Mesh_i* mesh_i;
3991 SMESH::SMESH_Mesh_var mesh;
3992 { // open new scope to dump "MakeMesh" command
3993 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3995 TPythonDump pydump; // to prevent dump at mesh creation
3996 mesh = makeMesh( theMeshName );
3997 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4001 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4002 mesh_i->CreateGroupServants();
4004 if ( !myIsPreviewMode )
4005 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4006 << theObject << ", "
4008 << TVar( theScaleFact ) << ", "
4009 << theCopyGroups << ", '"
4010 << theMeshName << "' )";
4014 if (!myIsPreviewMode && mesh_i)
4015 mesh_i->GetGroups();
4017 return mesh._retn();
4020 //================================================================================
4022 * \brief Make an offset mesh from a source 2D mesh
4023 * \param [inout] theObject - source mesh. New elements are added to this mesh
4024 * if \a theMeshName is empty.
4025 * \param [in] theValue - offset value
4026 * \param [in] theCopyGroups - to generate groups
4027 * \param [in] theMeshName - optional name of a new mesh
4028 * \param [out] theGroups - new groups
4029 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
4031 //================================================================================
4033 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4034 CORBA::Double theValue,
4035 CORBA::Boolean theCopyGroups,
4036 const char* theMeshName,
4037 SMESH::ListOfGroups_out theGroups)
4038 throw (SALOME::SALOME_Exception)
4043 SMESHDS_Mesh* aMeshDS = getMeshDS();
4045 SMESH::SMESH_Mesh_var mesh_var;
4046 ::SMESH_MeshEditor::PGroupIDs groupIds;
4050 TIDSortedElemSet elements, copyElements;
4051 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4052 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4055 SMESH_Mesh* tgtMesh = 0;
4056 if ( myIsPreviewMode )
4058 TPreviewMesh * tmpMesh = getPreviewMesh();
4060 tmpMesh->Copy( elements, copyElements );
4061 theCopyGroups = false;
4066 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4067 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4068 tgtMesh = & mesh_i->GetImpl();
4070 groupIds = getEditor().Offset( elements, theValue, tgtMesh, theCopyGroups, !myIsPreviewMode );
4072 tgtMesh->GetMeshDS()->Modified();
4075 if ( myIsPreviewMode )
4077 getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4081 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4083 // result of Offset() is a tuple (mesh, groups)
4084 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4085 else pyDump << mesh_var << ", ";
4086 pyDump << theGroups << " = "
4087 << this << ".Offset( "
4089 << theCopyGroups << ", "
4090 << "'" << theMeshName<< "')";
4093 return mesh_var._retn();
4095 SMESH_CATCH( SMESH::throwCorbaException );
4096 return SMESH::SMESH_Mesh::_nil();
4099 //=======================================================================
4100 //function : findCoincidentNodes
4102 //=======================================================================
4104 void SMESH_MeshEditor_i::
4105 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4106 CORBA::Double Tolerance,
4107 SMESH::array_of_long_array_out GroupsOfNodes,
4108 CORBA::Boolean SeparateCornersAndMedium)
4110 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4111 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4113 GroupsOfNodes = new SMESH::array_of_long_array;
4114 GroupsOfNodes->length( aListOfListOfNodes.size() );
4115 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4116 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4118 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4119 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4120 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4121 aGroup.length( aListOfNodes.size() );
4122 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4123 aGroup[ j ] = (*lIt)->GetID();
4127 //=======================================================================
4128 //function : FindCoincidentNodes
4130 //=======================================================================
4132 void SMESH_MeshEditor_i::
4133 FindCoincidentNodes (CORBA::Double Tolerance,
4134 SMESH::array_of_long_array_out GroupsOfNodes,
4135 CORBA::Boolean SeparateCornersAndMedium)
4136 throw (SALOME::SALOME_Exception)
4141 TIDSortedNodeSet nodes; // no input nodes
4142 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4144 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4145 << Tolerance << ", "
4146 << SeparateCornersAndMedium << " )";
4148 SMESH_CATCH( SMESH::throwCorbaException );
4151 //=======================================================================
4152 //function : FindCoincidentNodesOnPart
4154 //=======================================================================
4156 void SMESH_MeshEditor_i::
4157 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4158 CORBA::Double Tolerance,
4159 SMESH::array_of_long_array_out GroupsOfNodes,
4160 CORBA::Boolean SeparateCornersAndMedium)
4161 throw (SALOME::SALOME_Exception)
4166 TIDSortedNodeSet nodes;
4167 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4169 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4171 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4173 << Tolerance << ", "
4174 << SeparateCornersAndMedium << " )";
4176 SMESH_CATCH( SMESH::throwCorbaException );
4179 //================================================================================
4181 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4182 * ExceptSubMeshOrGroups
4184 //================================================================================
4186 void SMESH_MeshEditor_i::
4187 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4188 CORBA::Double theTolerance,
4189 SMESH::array_of_long_array_out theGroupsOfNodes,
4190 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4191 CORBA::Boolean theSeparateCornersAndMedium)
4192 throw (SALOME::SALOME_Exception)
4197 TIDSortedNodeSet nodes;
4198 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4200 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4202 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4204 while ( nodeIt->more() )
4205 nodes.erase( cast2Node( nodeIt->next() ));
4207 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4209 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4211 << theTolerance << ", "
4212 << theExceptSubMeshOrGroups << ", "
4213 << theSeparateCornersAndMedium << " )";
4215 SMESH_CATCH( SMESH::throwCorbaException );
4218 //=======================================================================
4219 //function : MergeNodes
4221 //=======================================================================
4223 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4224 const SMESH::ListOfIDSources& NodesToKeep,
4225 CORBA::Boolean AvoidMakingHoles)
4226 throw (SALOME::SALOME_Exception)
4231 SMESHDS_Mesh* aMesh = getMeshDS();
4233 TPythonDump aTPythonDump;
4234 aTPythonDump << this << ".MergeNodes([";
4236 TIDSortedNodeSet setOfNodesToKeep;
4237 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4239 prepareIdSource( NodesToKeep[i] );
4240 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
4241 while ( nodeIt->more() )
4242 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4245 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4246 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4248 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4249 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4250 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4251 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4253 CORBA::Long index = aNodeGroup[ j ];
4254 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4256 if ( setOfNodesToKeep.count( node ))
4257 aListOfNodes.push_front( node );
4259 aListOfNodes.push_back( node );
4262 if ( aListOfNodes.size() < 2 )
4263 aListOfListOfNodes.pop_back();
4265 if ( i > 0 ) aTPythonDump << ", ";
4266 aTPythonDump << aNodeGroup;
4269 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4271 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4273 declareMeshModified( /*isReComputeSafe=*/false );
4275 SMESH_CATCH( SMESH::throwCorbaException );
4278 //=======================================================================
4279 //function : FindEqualElements
4281 //=======================================================================
4283 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4284 SMESH::array_of_long_array_out GroupsOfElementsID)
4285 throw (SALOME::SALOME_Exception)
4290 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4291 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4293 TIDSortedElemSet elems;
4294 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4296 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4297 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4299 GroupsOfElementsID = new SMESH::array_of_long_array;
4300 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4302 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4303 aListOfListOfElementsID.begin();
4304 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4306 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4307 list<int>& listOfIDs = *arraysIt;
4308 aGroup.length( listOfIDs.size() );
4309 list<int>::iterator idIt = listOfIDs.begin();
4310 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4311 aGroup[ k ] = *idIt;
4314 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4318 SMESH_CATCH( SMESH::throwCorbaException );
4321 //=======================================================================
4322 //function : MergeElements
4324 //=======================================================================
4326 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4327 throw (SALOME::SALOME_Exception)
4332 TPythonDump aTPythonDump;
4333 aTPythonDump << this << ".MergeElements( [";
4335 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4337 for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) {
4338 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4339 aListOfListOfElementsID.push_back( list< int >() );
4340 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4341 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) {
4342 CORBA::Long id = anElemsIDGroup[ j ];
4343 aListOfElemsID.push_back( id );
4345 if ( aListOfElemsID.size() < 2 )
4346 aListOfListOfElementsID.pop_back();
4347 if ( i > 0 ) aTPythonDump << ", ";
4348 aTPythonDump << anElemsIDGroup;
4351 getEditor().MergeElements(aListOfListOfElementsID);
4353 declareMeshModified( /*isReComputeSafe=*/true );
4355 aTPythonDump << "] )";
4357 SMESH_CATCH( SMESH::throwCorbaException );
4360 //=======================================================================
4361 //function : MergeEqualElements
4363 //=======================================================================
4365 void SMESH_MeshEditor_i::MergeEqualElements()
4366 throw (SALOME::SALOME_Exception)
4371 getEditor().MergeEqualElements();
4373 declareMeshModified( /*isReComputeSafe=*/true );
4375 TPythonDump() << this << ".MergeEqualElements()";
4377 SMESH_CATCH( SMESH::throwCorbaException );
4380 //=============================================================================
4382 * Move the node to a given point
4384 //=============================================================================
4386 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4390 throw (SALOME::SALOME_Exception)
4393 initData(/*deleteSearchers=*/false);
4395 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4399 if ( theNodeSearcher )
4400 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4402 if ( myIsPreviewMode ) // make preview data
4404 // in a preview mesh, make edges linked to a node
4405 TPreviewMesh& tmpMesh = *getPreviewMesh();
4406 TIDSortedElemSet linkedNodes;
4407 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4408 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4409 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4410 for ( ; nIt != linkedNodes.end(); ++nIt )
4412 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4413 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4417 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4418 // fill preview data
4420 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4421 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4423 getMeshDS()->MoveNode(node, x, y, z);
4425 if ( !myIsPreviewMode )
4427 // Update Python script
4428 TPythonDump() << "isDone = " << this << ".MoveNode( "
4429 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4430 declareMeshModified( /*isReComputeSafe=*/false );
4433 SMESH_CATCH( SMESH::throwCorbaException );
4438 //================================================================================
4440 * \brief Return ID of node closest to a given point
4442 //================================================================================
4444 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4447 throw (SALOME::SALOME_Exception)
4450 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4452 if ( !theNodeSearcher ) {
4453 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4456 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4457 return node->GetID();
4459 SMESH_CATCH( SMESH::throwCorbaException );
4463 //================================================================================
4465 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4466 * move the node closest to the point to point's location and return ID of the node
4468 //================================================================================
4470 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4473 CORBA::Long theNodeID)
4474 throw (SALOME::SALOME_Exception)
4477 // We keep theNodeSearcher until any mesh modification:
4478 // 1) initData() deletes theNodeSearcher at any edition,
4479 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4481 initData(/*deleteSearchers=*/false);
4483 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4485 int nodeID = theNodeID;
4486 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4487 if ( !node ) // preview moving node
4489 if ( !theNodeSearcher ) {
4490 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4493 node = theNodeSearcher->FindClosestTo( p );
4496 nodeID = node->GetID();
4497 if ( myIsPreviewMode ) // make preview data
4499 // in a preview mesh, make edges linked to a node
4500 TPreviewMesh tmpMesh = *getPreviewMesh();
4501 TIDSortedElemSet linkedNodes;
4502 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4503 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4504 for ( ; nIt != linkedNodes.end(); ++nIt )
4506 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4507 tmpMesh.Copy( &edge );
4510 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4512 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4513 // fill preview data
4515 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4517 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4521 getMeshDS()->MoveNode(node, x, y, z);
4525 if ( !myIsPreviewMode )
4527 TPythonDump() << "nodeID = " << this
4528 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4529 << ", " << nodeID << " )";
4531 declareMeshModified( /*isReComputeSafe=*/false );
4536 SMESH_CATCH( SMESH::throwCorbaException );
4540 //=======================================================================
4542 * Return elements of given type where the given point is IN or ON.
4544 * 'ALL' type means elements of any type excluding nodes
4546 //=======================================================================
4548 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4551 SMESH::ElementType type)
4552 throw (SALOME::SALOME_Exception)
4555 SMESH::long_array_var res = new SMESH::long_array;
4556 vector< const SMDS_MeshElement* > foundElems;
4558 theSearchersDeleter.Set( myMesh );
4559 if ( !theElementSearcher ) {
4560 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4562 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4563 SMDSAbs_ElementType( type ),
4565 res->length( foundElems.size() );
4566 for ( size_t i = 0; i < foundElems.size(); ++i )
4567 res[i] = foundElems[i]->GetID();
4571 SMESH_CATCH( SMESH::throwCorbaException );
4575 //=======================================================================
4576 //function : FindAmongElementsByPoint
4577 //purpose : Searching among the given elements, return elements of given type
4578 // where the given point is IN or ON.
4579 // 'ALL' type means elements of any type excluding nodes
4580 //=======================================================================
4583 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4587 SMESH::ElementType type)
4588 throw (SALOME::SALOME_Exception)
4591 SMESH::long_array_var res = new SMESH::long_array;
4593 if ( type != SMESH::NODE )
4595 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4596 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4597 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4598 type != types[0] ) // but search of elements of dim > 0
4601 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4602 return FindElementsByPoint( x,y,z, type );
4604 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4606 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4607 if ( !theElementSearcher )
4609 // create a searcher from elementIDs
4610 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4611 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4613 if ( !idSourceToSet( elementIDs, meshDS, elements,
4614 ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ),
4615 /*emptyIfIsMesh=*/true))
4618 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4619 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4621 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4624 vector< const SMDS_MeshElement* > foundElems;
4626 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4627 SMDSAbs_ElementType( type ),
4629 res->length( foundElems.size() );
4630 for ( size_t i = 0; i < foundElems.size(); ++i )
4631 res[i] = foundElems[i]->GetID();
4635 SMESH_CATCH( SMESH::throwCorbaException );
4639 //=======================================================================
4640 //function : GetPointState
4641 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4642 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4643 //=======================================================================
4645 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4648 throw (SALOME::SALOME_Exception)
4651 theSearchersDeleter.Set( myMesh );
4652 if ( !theElementSearcher ) {
4653 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4655 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4657 SMESH_CATCH( SMESH::throwCorbaException );
4661 //=======================================================================
4662 //function : IsManifold
4663 //purpose : Check if a 2D mesh is manifold
4664 //=======================================================================
4666 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4667 throw (SALOME::SALOME_Exception)
4669 bool isManifold = true;
4672 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4673 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4675 /*closedOnly=*/true,
4677 SMESH_CATCH( SMESH::throwCorbaException );
4682 //=======================================================================
4683 //function : IsCoherentOrientation2D
4684 //purpose : Check if orientation of 2D elements is coherent
4685 //=======================================================================
4687 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4688 throw (SALOME::SALOME_Exception)
4690 bool isGoodOri = true;
4693 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4694 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4696 /*closedOnly=*/true,
4699 SMESH_CATCH( SMESH::throwCorbaException );
4704 //=======================================================================
4705 //function : FindFreeBorders
4706 //purpose : Returns all or only closed FreeBorder's.
4707 //=======================================================================
4709 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4710 throw (SALOME::SALOME_Exception)
4712 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4715 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4716 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4718 resBorders->length( foundFreeBordes.size() );
4719 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
4721 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
4722 SMESH::FreeBorder& bordOut = resBorders[i];
4723 bordOut.nodeIDs.length( bordNodes.size() );
4724 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
4725 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
4728 SMESH_CATCH( SMESH::throwCorbaException );
4730 return resBorders._retn();
4733 //=======================================================================
4734 //function : FillHole
4735 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
4736 //=======================================================================
4738 void SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole)
4739 throw (SALOME::SALOME_Exception)
4743 if ( theHole.nodeIDs.length() < 4 )
4744 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
4745 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
4746 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
4747 "First and last nodes must be same", SALOME::BAD_PARAM);
4749 SMESH_MeshAlgos::TFreeBorder bordNodes;
4750 bordNodes.resize( theHole.nodeIDs.length() );
4751 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
4753 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
4754 if ( !bordNodes[ iN ] )
4755 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
4756 << " does not exist", SALOME::BAD_PARAM);
4761 MeshEditor_I::TPreviewMesh* previewMesh = 0;
4762 SMDS_Mesh* meshDS = getMeshDS();
4763 if ( myIsPreviewMode )
4765 // copy faces sharing nodes of theHole
4766 TIDSortedElemSet holeFaces;
4767 previewMesh = getPreviewMesh( SMDSAbs_Face );
4768 for ( size_t i = 0; i < bordNodes.size(); ++i )
4770 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
4771 while ( fIt->more() )
4773 const SMDS_MeshElement* face = fIt->next();
4774 if ( holeFaces.insert( face ).second )
4775 previewMesh->Copy( face );
4777 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
4778 ASSERT( bordNodes[i] );
4780 meshDS = previewMesh->GetMeshDS();
4783 std::vector<const SMDS_MeshElement*> newFaces;
4784 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
4786 if ( myIsPreviewMode )
4788 previewMesh->Clear();
4789 for ( size_t i = 0; i < newFaces.size(); ++i )
4790 previewMesh->Copy( newFaces[i] );
4794 getEditor().ClearLastCreated();
4795 SMESH_SequenceOfElemPtr& aSeq =
4796 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
4797 aSeq.swap( newFaces );
4799 TPythonDump() << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
4802 SMESH_CATCH( SMESH::throwCorbaException );
4805 //=======================================================================
4806 //function : convError
4808 //=======================================================================
4810 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4812 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4816 RETCASE( SEW_BORDER1_NOT_FOUND );
4817 RETCASE( SEW_BORDER2_NOT_FOUND );
4818 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4819 RETCASE( SEW_BAD_SIDE_NODES );
4820 RETCASE( SEW_VOLUMES_TO_SPLIT );
4821 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4822 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4823 RETCASE( SEW_BAD_SIDE1_NODES );
4824 RETCASE( SEW_BAD_SIDE2_NODES );
4825 RETCASE( SEW_INTERNAL_ERROR );
4827 return SMESH::SMESH_MeshEditor::SEW_OK;
4830 //=======================================================================
4832 * Returns groups of FreeBorder's coincident within the given tolerance.
4833 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
4834 * to free borders being compared is used.
4836 //=======================================================================
4838 SMESH::CoincidentFreeBorders*
4839 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
4841 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
4845 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
4846 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
4848 // copy free borders
4849 aCFB->borders.length( cfb._borders.size() );
4850 for ( size_t i = 0; i < cfb._borders.size(); ++i )
4852 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
4853 SMESH::FreeBorder& aBRD = aCFB->borders[i];
4854 aBRD.nodeIDs.length( nodes.size() );
4855 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4856 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
4859 // copy coincident parts
4860 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
4861 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
4863 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
4864 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
4865 aGRP.length( grp.size() );
4866 for ( size_t iP = 0; iP < grp.size(); ++iP )
4868 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
4869 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4870 aPART.border = part._border;
4871 aPART.node1 = part._node1;
4872 aPART.node2 = part._node2;
4873 aPART.nodeLast = part._nodeLast;
4876 SMESH_CATCH( SMESH::doNothing );
4878 TPythonDump() << "CoincidentFreeBorders = "
4879 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
4881 return aCFB._retn();
4884 //=======================================================================
4886 * Sew FreeBorder's of each group
4888 //=======================================================================
4890 CORBA::Short SMESH_MeshEditor_i::
4891 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
4892 CORBA::Boolean createPolygons,
4893 CORBA::Boolean createPolyhedra)
4894 throw (SALOME::SALOME_Exception)
4896 CORBA::Short nbSewed = 0;
4898 SMESH_MeshAlgos::TFreeBorderVec groups;
4899 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
4901 // check the input and collect nodes
4902 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
4904 borderNodes.clear();
4905 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
4906 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
4908 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4909 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
4910 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
4912 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
4914 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
4915 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
4916 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
4917 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
4918 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
4919 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4921 // do not keep these nodes for further sewing as nodes can be removed by the sewing
4922 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
4923 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
4924 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
4926 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
4928 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
4930 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4932 borderNodes.push_back( n1 );
4933 borderNodes.push_back( n2 );
4934 borderNodes.push_back( n3 );
4936 groups.push_back( borderNodes );
4939 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
4940 // to get nodes that replace other nodes during merge we create 0D elements
4941 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
4944 vector< const SMDS_MeshElement* > tmp0Delems;
4945 for ( size_t i = 0; i < groups.size(); ++i )
4947 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4948 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4950 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
4952 tmp0Delems.push_back( it0D->next() );
4954 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
4958 // cout << endl << "INIT" << endl;
4959 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4961 // cout << i << " ";
4962 // if ( i % 3 == 0 ) cout << "^ ";
4963 // tmp0Delems[i]->GetNode(0)->Print( cout );
4968 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
4970 for ( size_t i = 0; i < groups.size(); ++i )
4972 bool isBordToBord = true;
4973 bool groupSewed = false;
4974 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4975 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
4977 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
4978 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
4979 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
4981 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
4982 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
4983 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
4985 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
4988 // TIDSortedElemSet emptySet, avoidSet;
4989 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
4991 // cout << "WRONG 2nd 1" << endl;
4992 // n0->Print( cout );
4993 // n1->Print( cout );
4995 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
4997 // cout << "WRONG 2nd 2" << endl;
4998 // n3->Print( cout );
4999 // n4->Print( cout );
5002 if ( !isBordToBord )
5004 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5005 n2 = 0; // and n2 is not used
5007 // 1st border moves to 2nd
5008 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5010 /*2ndIsFreeBorder=*/ isBordToBord,
5011 createPolygons, createPolyhedra);
5012 groupSewed = ( res == ok );
5014 isBordToBord = false;
5015 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5016 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5018 // cout << t << " ";
5019 // if ( t % 3 == 0 ) cout << "^ ";
5020 // tmp0Delems[t]->GetNode(0)->Print( cout );
5023 i0D += nodes.size();
5024 nbSewed += groupSewed;
5027 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5028 << freeBorders << ", "
5029 << createPolygons << ", "
5030 << createPolyhedra << " )";
5032 SMESH_CATCH( SMESH::doNothing );
5034 declareMeshModified( /*isReComputeSafe=*/false );
5036 // remove tmp 0D elements
5038 set< const SMDS_MeshElement* > removed0D;
5039 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5041 if ( removed0D.insert( tmp0Delems[i] ).second )
5042 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5044 SMESH_CATCH( SMESH::throwCorbaException );
5049 //=======================================================================
5050 //function : SewFreeBorders
5052 //=======================================================================
5054 SMESH::SMESH_MeshEditor::Sew_Error
5055 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5056 CORBA::Long SecondNodeID1,
5057 CORBA::Long LastNodeID1,
5058 CORBA::Long FirstNodeID2,
5059 CORBA::Long SecondNodeID2,
5060 CORBA::Long LastNodeID2,
5061 CORBA::Boolean CreatePolygons,
5062 CORBA::Boolean CreatePolyedrs)
5063 throw (SALOME::SALOME_Exception)
5068 SMESHDS_Mesh* aMesh = getMeshDS();
5070 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5071 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5072 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5073 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5074 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5075 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5077 if (!aBorderFirstNode ||
5078 !aBorderSecondNode||
5080 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5081 if (!aSide2FirstNode ||
5082 !aSide2SecondNode ||
5084 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5086 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5087 << FirstNodeID1 << ", "
5088 << SecondNodeID1 << ", "
5089 << LastNodeID1 << ", "
5090 << FirstNodeID2 << ", "
5091 << SecondNodeID2 << ", "
5092 << LastNodeID2 << ", "
5093 << CreatePolygons<< ", "
5094 << CreatePolyedrs<< " )";
5096 SMESH::SMESH_MeshEditor::Sew_Error error =
5097 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5108 declareMeshModified( /*isReComputeSafe=*/false );
5111 SMESH_CATCH( SMESH::throwCorbaException );
5112 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5116 //=======================================================================
5117 //function : SewConformFreeBorders
5119 //=======================================================================
5121 SMESH::SMESH_MeshEditor::Sew_Error
5122 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5123 CORBA::Long SecondNodeID1,
5124 CORBA::Long LastNodeID1,
5125 CORBA::Long FirstNodeID2,
5126 CORBA::Long SecondNodeID2)
5127 throw (SALOME::SALOME_Exception)
5132 SMESHDS_Mesh* aMesh = getMeshDS();
5134 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5135 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5136 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5137 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5138 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5139 const SMDS_MeshNode* aSide2ThirdNode = 0;
5141 if (!aBorderFirstNode ||
5142 !aBorderSecondNode||
5144 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5145 if (!aSide2FirstNode ||
5147 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5149 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5150 << FirstNodeID1 << ", "
5151 << SecondNodeID1 << ", "
5152 << LastNodeID1 << ", "
5153 << FirstNodeID2 << ", "
5154 << SecondNodeID2 << " )";
5156 SMESH::SMESH_MeshEditor::Sew_Error error =
5157 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5166 declareMeshModified( /*isReComputeSafe=*/false );
5169 SMESH_CATCH( SMESH::throwCorbaException );
5170 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5174 //=======================================================================
5175 //function : SewBorderToSide
5177 //=======================================================================
5179 SMESH::SMESH_MeshEditor::Sew_Error
5180 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5181 CORBA::Long SecondNodeIDOnFreeBorder,
5182 CORBA::Long LastNodeIDOnFreeBorder,
5183 CORBA::Long FirstNodeIDOnSide,
5184 CORBA::Long LastNodeIDOnSide,
5185 CORBA::Boolean CreatePolygons,
5186 CORBA::Boolean CreatePolyedrs)
5187 throw (SALOME::SALOME_Exception)
5192 SMESHDS_Mesh* aMesh = getMeshDS();
5194 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5195 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5196 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5197 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5198 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5199 const SMDS_MeshNode* aSide2ThirdNode = 0;
5201 if (!aBorderFirstNode ||
5202 !aBorderSecondNode||
5204 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5205 if (!aSide2FirstNode ||
5207 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5209 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5210 << FirstNodeIDOnFreeBorder << ", "
5211 << SecondNodeIDOnFreeBorder << ", "
5212 << LastNodeIDOnFreeBorder << ", "
5213 << FirstNodeIDOnSide << ", "
5214 << LastNodeIDOnSide << ", "
5215 << CreatePolygons << ", "
5216 << CreatePolyedrs << ") ";
5218 SMESH::SMESH_MeshEditor::Sew_Error error =
5219 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5229 declareMeshModified( /*isReComputeSafe=*/false );
5232 SMESH_CATCH( SMESH::throwCorbaException );
5233 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5237 //=======================================================================
5238 //function : SewSideElements
5240 //=======================================================================
5242 SMESH::SMESH_MeshEditor::Sew_Error
5243 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5244 const SMESH::long_array& IDsOfSide2Elements,
5245 CORBA::Long NodeID1OfSide1ToMerge,
5246 CORBA::Long NodeID1OfSide2ToMerge,
5247 CORBA::Long NodeID2OfSide1ToMerge,
5248 CORBA::Long NodeID2OfSide2ToMerge)
5249 throw (SALOME::SALOME_Exception)
5254 SMESHDS_Mesh* aMesh = getMeshDS();
5256 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5257 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5258 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5259 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5261 if (!aFirstNode1ToMerge ||
5262 !aFirstNode2ToMerge )
5263 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5264 if (!aSecondNode1ToMerge||
5265 !aSecondNode2ToMerge)
5266 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5268 TIDSortedElemSet aSide1Elems, aSide2Elems;
5269 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5270 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5272 TPythonDump() << "error = " << this << ".SewSideElements( "
5273 << IDsOfSide1Elements << ", "
5274 << IDsOfSide2Elements << ", "
5275 << NodeID1OfSide1ToMerge << ", "
5276 << NodeID1OfSide2ToMerge << ", "
5277 << NodeID2OfSide1ToMerge << ", "
5278 << NodeID2OfSide2ToMerge << ")";
5280 SMESH::SMESH_MeshEditor::Sew_Error error =
5281 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5284 aSecondNode1ToMerge,
5285 aSecondNode2ToMerge));
5287 declareMeshModified( /*isReComputeSafe=*/false );
5290 SMESH_CATCH( SMESH::throwCorbaException );
5291 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5294 //================================================================================
5296 * \brief Set new nodes for given element
5297 * \param ide - element id
5298 * \param newIDs - new node ids
5299 * \retval CORBA::Boolean - true if result is OK
5301 //================================================================================
5303 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5304 const SMESH::long_array& newIDs)
5305 throw (SALOME::SALOME_Exception)
5310 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5311 if(!elem) return false;
5313 int nbn = newIDs.length();
5315 vector<const SMDS_MeshNode*> aNodes(nbn);
5318 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5321 aNodes[nbn1] = aNode;
5324 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5325 << ide << ", " << newIDs << " )";
5327 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5329 declareMeshModified( /*isReComputeSafe=*/ !res );
5333 SMESH_CATCH( SMESH::throwCorbaException );
5337 //=======================================================================
5339 * \brief Makes a part of the mesh quadratic or bi-quadratic
5341 //=======================================================================
5343 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5344 CORBA::Boolean theToBiQuad,
5345 SMESH::SMESH_IDSource_ptr theObject)
5346 throw (SALOME::SALOME_Exception)
5351 TIDSortedElemSet elems;
5353 if ( !( elemsOK = CORBA::is_nil( theObject )))
5355 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5356 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5360 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5361 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5363 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5364 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5366 declareMeshModified( /*isReComputeSafe=*/false );
5369 SMESH_CATCH( SMESH::throwCorbaException );
5372 //=======================================================================
5373 //function : ConvertFromQuadratic
5375 //=======================================================================
5377 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5378 throw (SALOME::SALOME_Exception)
5383 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5384 TPythonDump() << this << ".ConvertFromQuadratic()";
5385 declareMeshModified( /*isReComputeSafe=*/!isDone );
5388 SMESH_CATCH( SMESH::throwCorbaException );
5392 //=======================================================================
5393 //function : ConvertToQuadratic
5395 //=======================================================================
5397 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5398 throw (SALOME::SALOME_Exception)
5400 convertToQuadratic( theForce3d, false );
5401 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5404 //================================================================================
5406 * \brief Makes a part of the mesh quadratic
5408 //================================================================================
5410 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5411 SMESH::SMESH_IDSource_ptr theObject)
5412 throw (SALOME::SALOME_Exception)
5414 convertToQuadratic( theForce3d, false, theObject );
5415 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5418 //================================================================================
5420 * \brief Makes a part of the mesh bi-quadratic
5422 //================================================================================
5424 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5425 SMESH::SMESH_IDSource_ptr theObject)
5426 throw (SALOME::SALOME_Exception)
5428 convertToQuadratic( theForce3d, true, theObject );
5429 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5432 //================================================================================
5434 * \brief Makes a part of the mesh linear
5436 //================================================================================
5438 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5439 throw (SALOME::SALOME_Exception)
5446 TIDSortedElemSet elems;
5447 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5449 if ( elems.empty() )
5451 ConvertFromQuadratic();
5453 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5455 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5459 getEditor().ConvertFromQuadratic(elems);
5462 declareMeshModified( /*isReComputeSafe=*/false );
5464 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5466 SMESH_CATCH( SMESH::throwCorbaException );
5469 //=======================================================================
5470 //function : makeMesh
5471 //purpose : create a named imported mesh
5472 //=======================================================================
5474 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5476 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5477 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5478 SALOMEDS::Study_var study = gen->GetCurrentStudy();
5479 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5480 gen->SetName( meshSO, theMeshName, "Mesh" );
5481 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5483 return mesh._retn();
5486 //=======================================================================
5487 //function : dumpGroupsList
5489 //=======================================================================
5491 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5492 const SMESH::ListOfGroups * theGroupList)
5494 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5495 if ( isDumpGroupList )
5496 theDumpPython << theGroupList << " = ";
5499 //================================================================================
5501 \brief Generates the unique group name.
5502 \param thePrefix name prefix
5505 //================================================================================
5507 std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix)
5509 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5510 set<std::string> groupNames;
5512 // Get existing group names
5513 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5514 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5515 if (CORBA::is_nil(aGroup))
5518 CORBA::String_var name = aGroup->GetName();
5519 groupNames.insert( name.in() );
5523 std::string name = thePrefix;
5526 while (!groupNames.insert(name).second)
5527 name = SMESH_Comment( thePrefix ) << "_" << index++;
5532 //================================================================================
5534 * \brief Prepare SMESH_IDSource for work
5536 //================================================================================
5538 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5540 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5542 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5543 filter->SetMesh( mesh );
5546 //================================================================================
5548 * \brief Retrieve elements of given type from SMESH_IDSource
5550 //================================================================================
5552 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5553 const SMESHDS_Mesh* theMeshDS,
5554 TIDSortedElemSet& theElemSet,
5555 const SMDSAbs_ElementType theType,
5556 const bool emptyIfIsMesh,
5557 IDSource_Error* error)
5560 if ( error ) *error = IDSource_OK;
5562 if ( CORBA::is_nil( theIDSource ))
5564 if ( error ) *error = IDSource_INVALID;
5567 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5569 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5570 *error = IDSource_EMPTY;
5573 prepareIdSource( theIDSource );
5574 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5575 if ( anIDs->length() == 0 )
5577 if ( error ) *error = IDSource_EMPTY;
5580 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5581 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5583 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5585 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5589 if ( error ) *error = IDSource_INVALID;
5595 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5596 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5598 if ( error ) *error = IDSource_INVALID;
5605 //================================================================================
5607 * \brief Duplicates given elements, i.e. creates new elements based on the
5608 * same nodes as the given ones.
5609 * \param theElements - container of elements to duplicate.
5610 * \param theGroupName - a name of group to contain the generated elements.
5611 * If a group with such a name already exists, the new elements
5612 * are added to the existing group, else a new group is created.
5613 * If \a theGroupName is empty, new elements are not added
5615 * \return a group where the new elements are added. NULL if theGroupName == "".
5618 //================================================================================
5620 SMESH::SMESH_Group_ptr
5621 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5622 const char* theGroupName)
5623 throw (SALOME::SALOME_Exception)
5625 SMESH::SMESH_Group_var newGroup;
5632 TIDSortedElemSet elems;
5633 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5635 getEditor().DoubleElements( elems );
5637 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5640 SMESH::ElementType type =
5641 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5642 // find existing group
5643 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5644 for ( size_t i = 0; i < groups->length(); ++i )
5645 if ( groups[i]->GetType() == type )
5647 CORBA::String_var name = groups[i]->GetName();
5648 if ( strcmp( name, theGroupName ) == 0 ) {
5649 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5653 // create a new group
5654 if ( newGroup->_is_nil() )
5655 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5657 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5659 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5660 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5661 for ( size_t i = 0; i <= aSeq.size(); i++ )
5662 groupDS->SMDSGroup().Add( aSeq[i] );
5667 if ( !newGroup->_is_nil() )
5668 pyDump << newGroup << " = ";
5669 pyDump << this << ".DoubleElements( "
5670 << theElements << ", " << "'" << theGroupName <<"')";
5672 SMESH_CATCH( SMESH::throwCorbaException );
5674 return newGroup._retn();
5677 //================================================================================
5679 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5680 \param theNodes - identifiers of nodes to be doubled
5681 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5682 nodes. If list of element identifiers is empty then nodes are doubled but
5683 they not assigned to elements
5684 \return TRUE if operation has been completed successfully, FALSE otherwise
5685 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5687 //================================================================================
5689 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5690 const SMESH::long_array& theModifiedElems )
5691 throw (SALOME::SALOME_Exception)
5696 list< int > aListOfNodes;
5698 for ( i = 0, n = theNodes.length(); i < n; i++ )
5699 aListOfNodes.push_back( theNodes[ i ] );
5701 list< int > aListOfElems;
5702 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5703 aListOfElems.push_back( theModifiedElems[ i ] );
5705 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5707 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5709 // Update Python script
5710 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5714 SMESH_CATCH( SMESH::throwCorbaException );
5718 //================================================================================
5720 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5721 This method provided for convenience works as DoubleNodes() described above.
5722 \param theNodeId - identifier of node to be doubled.
5723 \param theModifiedElems - identifiers of elements to be updated.
5724 \return TRUE if operation has been completed successfully, FALSE otherwise
5725 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5727 //================================================================================
5729 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5730 const SMESH::long_array& theModifiedElems )
5731 throw (SALOME::SALOME_Exception)
5734 SMESH::long_array_var aNodes = new SMESH::long_array;
5735 aNodes->length( 1 );
5736 aNodes[ 0 ] = theNodeId;
5738 TPythonDump pyDump; // suppress dump by the next line
5740 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5742 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5746 SMESH_CATCH( SMESH::throwCorbaException );
5750 //================================================================================
5752 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5753 This method provided for convenience works as DoubleNodes() described above.
5754 \param theNodes - group of nodes to be doubled.
5755 \param theModifiedElems - group of elements to be updated.
5756 \return TRUE if operation has been completed successfully, FALSE otherwise
5757 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5759 //================================================================================
5761 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5762 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5763 throw (SALOME::SALOME_Exception)
5766 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5769 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5770 SMESH::long_array_var aModifiedElems;
5771 if ( !CORBA::is_nil( theModifiedElems ) )
5772 aModifiedElems = theModifiedElems->GetListOfID();
5774 aModifiedElems = new SMESH::long_array;
5776 TPythonDump pyDump; // suppress dump by the next line
5778 bool done = DoubleNodes( aNodes, aModifiedElems );
5780 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5784 SMESH_CATCH( SMESH::throwCorbaException );
5788 //================================================================================
5790 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5791 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5792 * \param theNodes - group of nodes to be doubled.
5793 * \param theModifiedElems - group of elements to be updated.
5794 * \return a new group with newly created nodes
5795 * \sa DoubleNodeGroup()
5797 //================================================================================
5799 SMESH::SMESH_Group_ptr
5800 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5801 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5802 throw (SALOME::SALOME_Exception)
5805 SMESH::SMESH_Group_var aNewGroup;
5807 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5808 return aNewGroup._retn();
5811 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5812 SMESH::long_array_var aModifiedElems;
5813 if ( !CORBA::is_nil( theModifiedElems ) )
5814 aModifiedElems = theModifiedElems->GetListOfID();
5816 aModifiedElems = new SMESH::long_array;
5817 aModifiedElems->length( 0 );
5820 TPythonDump pyDump; // suppress dump by the next line
5822 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5825 // Create group with newly created nodes
5826 SMESH::long_array_var anIds = GetLastCreatedNodes();
5827 if (anIds->length() > 0) {
5828 std::string anUnindexedName (theNodes->GetName());
5829 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5830 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5831 aNewGroup->Add(anIds);
5832 pyDump << aNewGroup << " = ";
5836 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5837 << theModifiedElems << " )";
5839 return aNewGroup._retn();
5841 SMESH_CATCH( SMESH::throwCorbaException );
5845 //================================================================================
5847 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5848 This method provided for convenience works as DoubleNodes() described above.
5849 \param theNodes - list of groups of nodes to be doubled
5850 \param theModifiedElems - list of groups of elements to be updated.
5851 \return TRUE if operation has been completed successfully, FALSE otherwise
5852 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5854 //================================================================================
5856 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5857 const SMESH::ListOfGroups& theModifiedElems )
5858 throw (SALOME::SALOME_Exception)
5863 std::list< int > aNodes;
5865 for ( i = 0, n = theNodes.length(); i < n; i++ )
5867 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5868 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5870 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5871 for ( j = 0, m = aCurr->length(); j < m; j++ )
5872 aNodes.push_back( aCurr[ j ] );
5876 std::list< int > anElems;
5877 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5879 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5880 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5882 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5883 for ( j = 0, m = aCurr->length(); j < m; j++ )
5884 anElems.push_back( aCurr[ j ] );
5888 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5890 declareMeshModified( /*isReComputeSafe=*/false );
5892 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5896 SMESH_CATCH( SMESH::throwCorbaException );
5900 //================================================================================
5902 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5903 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5904 * \param theNodes - group of nodes to be doubled.
5905 * \param theModifiedElems - group of elements to be updated.
5906 * \return a new group with newly created nodes
5907 * \sa DoubleNodeGroups()
5909 //================================================================================
5911 SMESH::SMESH_Group_ptr
5912 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5913 const SMESH::ListOfGroups& theModifiedElems )
5914 throw (SALOME::SALOME_Exception)
5916 SMESH::SMESH_Group_var aNewGroup;
5918 TPythonDump pyDump; // suppress dump by the next line
5920 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5924 // Create group with newly created nodes
5925 SMESH::long_array_var anIds = GetLastCreatedNodes();
5926 if (anIds->length() > 0) {
5927 std::string anUnindexedName (theNodes[0]->GetName());
5928 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5929 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5930 aNewGroup->Add(anIds);
5931 pyDump << aNewGroup << " = ";
5935 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5936 << theModifiedElems << " )";
5938 return aNewGroup._retn();
5942 //================================================================================
5944 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5945 \param theElems - the list of elements (edges or faces) to be replicated
5946 The nodes for duplication could be found from these elements
5947 \param theNodesNot - list of nodes to NOT replicate
5948 \param theAffectedElems - the list of elements (cells and edges) to which the
5949 replicated nodes should be associated to.
5950 \return TRUE if operation has been completed successfully, FALSE otherwise
5951 \sa DoubleNodeGroup(), DoubleNodeGroups()
5953 //================================================================================
5955 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5956 const SMESH::long_array& theNodesNot,
5957 const SMESH::long_array& theAffectedElems )
5958 throw (SALOME::SALOME_Exception)
5963 SMESHDS_Mesh* aMeshDS = getMeshDS();
5964 TIDSortedElemSet anElems, aNodes, anAffected;
5965 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5966 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5967 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5969 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5971 // Update Python script
5972 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5973 << theNodesNot << ", " << theAffectedElems << " )";
5975 declareMeshModified( /*isReComputeSafe=*/false );
5978 SMESH_CATCH( SMESH::throwCorbaException );
5982 //================================================================================
5984 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5985 \param theElems - the list of elements (edges or faces) to be replicated
5986 The nodes for duplication could be found from these elements
5987 \param theNodesNot - list of nodes to NOT replicate
5988 \param theShape - shape to detect affected elements (element which geometric center
5989 located on or inside shape).
5990 The replicated nodes should be associated to affected elements.
5991 \return TRUE if operation has been completed successfully, FALSE otherwise
5992 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5994 //================================================================================
5996 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5997 const SMESH::long_array& theNodesNot,
5998 GEOM::GEOM_Object_ptr theShape )
5999 throw (SALOME::SALOME_Exception)
6005 SMESHDS_Mesh* aMeshDS = getMeshDS();
6006 TIDSortedElemSet anElems, aNodes;
6007 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6008 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6010 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6011 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6013 // Update Python script
6014 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6015 << theNodesNot << ", " << theShape << " )";
6017 declareMeshModified( /*isReComputeSafe=*/false );
6020 SMESH_CATCH( SMESH::throwCorbaException );
6024 //================================================================================
6026 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6027 \param theElems - group of of elements (edges or faces) to be replicated
6028 \param theNodesNot - group of nodes not to replicated
6029 \param theAffectedElems - group of elements to which the replicated nodes
6030 should be associated to.
6031 \return TRUE if operation has been completed successfully, FALSE otherwise
6032 \sa DoubleNodes(), DoubleNodeGroups()
6034 //================================================================================
6037 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6038 SMESH::SMESH_GroupBase_ptr theNodesNot,
6039 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6040 throw (SALOME::SALOME_Exception)
6043 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6049 SMESHDS_Mesh* aMeshDS = getMeshDS();
6050 TIDSortedElemSet anElems, aNodes, anAffected;
6051 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6052 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6053 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6055 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6057 // Update Python script
6058 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6059 << theNodesNot << ", " << theAffectedElems << " )";
6061 declareMeshModified( /*isReComputeSafe=*/false );
6064 SMESH_CATCH( SMESH::throwCorbaException );
6068 //================================================================================
6070 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6071 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6072 * \param theElems - group of of elements (edges or faces) to be replicated
6073 * \param theNodesNot - group of nodes not to replicated
6074 * \param theAffectedElems - group of elements to which the replicated nodes
6075 * should be associated to.
6076 * \return a new group with newly created elements
6077 * \sa DoubleNodeElemGroup()
6079 //================================================================================
6081 SMESH::SMESH_Group_ptr
6082 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6083 SMESH::SMESH_GroupBase_ptr theNodesNot,
6084 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6085 throw (SALOME::SALOME_Exception)
6088 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6092 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6093 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6095 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6097 << theNodesNot << ", "
6098 << theAffectedElems << " )";
6100 return elemGroup._retn();
6103 //================================================================================
6105 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6106 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6107 * \param theElems - group of of elements (edges or faces) to be replicated
6108 * \param theNodesNot - group of nodes not to replicated
6109 * \param theAffectedElems - group of elements to which the replicated nodes
6110 * should be associated to.
6111 * \return a new group with newly created elements
6112 * \sa DoubleNodeElemGroup()
6114 //================================================================================
6116 SMESH::ListOfGroups*
6117 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6118 SMESH::SMESH_GroupBase_ptr theNodesNot,
6119 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6120 CORBA::Boolean theElemGroupNeeded,
6121 CORBA::Boolean theNodeGroupNeeded)
6122 throw (SALOME::SALOME_Exception)
6125 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6126 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6127 aTwoGroups->length( 2 );
6129 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6130 return aTwoGroups._retn();
6135 SMESHDS_Mesh* aMeshDS = getMeshDS();
6136 TIDSortedElemSet anElems, aNodes, anAffected;
6137 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6138 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6139 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6142 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6144 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6150 // Create group with newly created elements
6151 CORBA::String_var elemGroupName = theElems->GetName();
6152 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6153 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6155 SMESH::long_array_var anIds = GetLastCreatedElems();
6156 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6157 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6158 aNewElemGroup->Add(anIds);
6160 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6162 SMESH::long_array_var anIds = GetLastCreatedNodes();
6163 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6164 aNewNodeGroup->Add(anIds);
6168 // Update Python script
6171 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6172 else pyDump << aNewElemGroup << ", ";
6173 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6174 else pyDump << aNewNodeGroup << " ] = ";
6176 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6177 << theNodesNot << ", "
6178 << theAffectedElems << ", "
6179 << theElemGroupNeeded << ", "
6180 << theNodeGroupNeeded <<" )";
6182 aTwoGroups[0] = aNewElemGroup._retn();
6183 aTwoGroups[1] = aNewNodeGroup._retn();
6184 return aTwoGroups._retn();
6186 SMESH_CATCH( SMESH::throwCorbaException );
6190 //================================================================================
6192 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6193 \param theElems - group of of elements (edges or faces) to be replicated
6194 \param theNodesNot - group of nodes not to replicated
6195 \param theShape - shape to detect affected elements (element which geometric center
6196 located on or inside shape).
6197 The replicated nodes should be associated to affected elements.
6198 \return TRUE if operation has been completed successfully, FALSE otherwise
6199 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6201 //================================================================================
6204 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6205 SMESH::SMESH_GroupBase_ptr theNodesNot,
6206 GEOM::GEOM_Object_ptr theShape )
6207 throw (SALOME::SALOME_Exception)
6210 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6216 SMESHDS_Mesh* aMeshDS = getMeshDS();
6217 TIDSortedElemSet anElems, aNodes, anAffected;
6218 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6219 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6221 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6222 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6225 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6227 // Update Python script
6228 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6229 << theNodesNot << ", " << theShape << " )";
6232 SMESH_CATCH( SMESH::throwCorbaException );
6236 //================================================================================
6238 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6239 * \param [in] theGrpList - groups
6240 * \param [in] theMeshDS - mesh
6241 * \param [out] theElemSet - set of elements
6242 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6244 //================================================================================
6246 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6247 SMESHDS_Mesh* theMeshDS,
6248 TIDSortedElemSet& theElemSet,
6249 const bool theIsNodeGrp)
6251 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6253 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6254 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6255 : aGrp->GetType() != SMESH::NODE ) )
6257 SMESH::long_array_var anIDs = aGrp->GetIDs();
6258 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6263 //================================================================================
6265 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6266 This method provided for convenience works as DoubleNodes() described above.
6267 \param theElems - list of groups of elements (edges or faces) to be replicated
6268 \param theNodesNot - list of groups of nodes not to replicated
6269 \param theAffectedElems - group of elements to which the replicated nodes
6270 should be associated to.
6271 \return TRUE if operation has been completed successfully, FALSE otherwise
6272 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6274 //================================================================================
6277 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6278 const SMESH::ListOfGroups& theNodesNot,
6279 const SMESH::ListOfGroups& theAffectedElems)
6280 throw (SALOME::SALOME_Exception)
6286 SMESHDS_Mesh* aMeshDS = getMeshDS();
6287 TIDSortedElemSet anElems, aNodes, anAffected;
6288 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6289 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6290 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6292 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6294 // Update Python script
6295 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6296 << &theNodesNot << ", " << &theAffectedElems << " )";
6298 declareMeshModified( /*isReComputeSafe=*/false );
6301 SMESH_CATCH( SMESH::throwCorbaException );
6305 //================================================================================
6307 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6308 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6309 \param theElems - list of groups of elements (edges or faces) to be replicated
6310 \param theNodesNot - list of groups of nodes not to replicated
6311 \param theAffectedElems - group of elements to which the replicated nodes
6312 should be associated to.
6313 * \return a new group with newly created elements
6314 * \sa DoubleNodeElemGroups()
6316 //================================================================================
6318 SMESH::SMESH_Group_ptr
6319 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6320 const SMESH::ListOfGroups& theNodesNot,
6321 const SMESH::ListOfGroups& theAffectedElems)
6322 throw (SALOME::SALOME_Exception)
6325 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6329 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6330 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6332 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6334 << theNodesNot << ", "
6335 << theAffectedElems << " )";
6337 return elemGroup._retn();
6340 //================================================================================
6342 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6343 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6344 \param theElems - list of groups of elements (edges or faces) to be replicated
6345 \param theNodesNot - list of groups of nodes not to replicated
6346 \param theAffectedElems - group of elements to which the replicated nodes
6347 should be associated to.
6348 * \return a new group with newly created elements
6349 * \sa DoubleNodeElemGroups()
6351 //================================================================================
6353 SMESH::ListOfGroups*
6354 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6355 const SMESH::ListOfGroups& theNodesNot,
6356 const SMESH::ListOfGroups& theAffectedElems,
6357 CORBA::Boolean theElemGroupNeeded,
6358 CORBA::Boolean theNodeGroupNeeded)
6359 throw (SALOME::SALOME_Exception)
6362 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6363 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6364 aTwoGroups->length( 2 );
6369 SMESHDS_Mesh* aMeshDS = getMeshDS();
6370 TIDSortedElemSet anElems, aNodes, anAffected;
6371 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6372 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6373 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6375 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6377 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6382 // Create group with newly created elements
6383 CORBA::String_var elemGroupName = theElems[0]->GetName();
6384 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6385 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6387 SMESH::long_array_var anIds = GetLastCreatedElems();
6388 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6389 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6390 aNewElemGroup->Add(anIds);
6392 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6394 SMESH::long_array_var anIds = GetLastCreatedNodes();
6395 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6396 aNewNodeGroup->Add(anIds);
6400 // Update Python script
6403 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6404 else pyDump << aNewElemGroup << ", ";
6405 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6406 else pyDump << aNewNodeGroup << " ] = ";
6408 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6409 << &theNodesNot << ", "
6410 << &theAffectedElems << ", "
6411 << theElemGroupNeeded << ", "
6412 << theNodeGroupNeeded << " )";
6414 aTwoGroups[0] = aNewElemGroup._retn();
6415 aTwoGroups[1] = aNewNodeGroup._retn();
6416 return aTwoGroups._retn();
6418 SMESH_CATCH( SMESH::throwCorbaException );
6422 //================================================================================
6424 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6425 This method provided for convenience works as DoubleNodes() described above.
6426 \param theElems - list of groups of elements (edges or faces) to be replicated
6427 \param theNodesNot - list of groups of nodes not to replicated
6428 \param theShape - shape to detect affected elements (element which geometric center
6429 located on or inside shape).
6430 The replicated nodes should be associated to affected elements.
6431 \return TRUE if operation has been completed successfully, FALSE otherwise
6432 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6434 //================================================================================
6437 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6438 const SMESH::ListOfGroups& theNodesNot,
6439 GEOM::GEOM_Object_ptr theShape )
6440 throw (SALOME::SALOME_Exception)
6446 SMESHDS_Mesh* aMeshDS = getMeshDS();
6447 TIDSortedElemSet anElems, aNodes;
6448 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6449 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6451 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6452 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6454 // Update Python script
6455 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6456 << &theNodesNot << ", " << theShape << " )";
6458 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6461 SMESH_CATCH( SMESH::throwCorbaException );
6465 //================================================================================
6467 \brief Identify the elements that will be affected by node duplication (actual
6468 duplication is not performed.
6469 This method is the first step of DoubleNodeElemGroupsInRegion.
6470 \param theElems - list of groups of elements (edges or faces) to be replicated
6471 \param theNodesNot - list of groups of nodes not to replicated
6472 \param theShape - shape to detect affected elements (element which geometric center
6473 located on or inside shape).
6474 The replicated nodes should be associated to affected elements.
6475 \return groups of affected elements
6476 \sa DoubleNodeElemGroupsInRegion()
6478 //================================================================================
6479 SMESH::ListOfGroups*
6480 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6481 const SMESH::ListOfGroups& theNodesNot,
6482 GEOM::GEOM_Object_ptr theShape )
6483 throw (SALOME::SALOME_Exception)
6486 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6487 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6488 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6489 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6493 ::SMESH_MeshEditor aMeshEditor(myMesh);
6495 SMESHDS_Mesh* aMeshDS = getMeshDS();
6496 TIDSortedElemSet anElems, aNodes;
6497 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6498 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6499 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6501 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6502 TIDSortedElemSet anAffected;
6503 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6505 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6508 if ( aResult && anAffected.size() > 0 )
6510 SMESH::long_array_var volumeIds = new SMESH::long_array;
6511 SMESH::long_array_var faceIds = new SMESH::long_array;
6512 SMESH::long_array_var edgeIds = new SMESH::long_array;
6513 volumeIds->length( anAffected.size() );
6514 faceIds ->length( anAffected.size() );
6515 edgeIds ->length( anAffected.size() );
6520 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6521 for (; eIt != anAffected.end(); ++eIt)
6523 const SMDS_MeshElement* anElem = *eIt;
6524 int elemId = anElem->GetID();
6525 switch ( anElem->GetType() ) {
6526 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6527 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6528 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6532 volumeIds->length(ivol);
6533 faceIds->length(iface);
6534 edgeIds->length(iedge);
6539 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6540 generateGroupName("affectedVolumes").c_str());
6541 aNewVolumeGroup->Add(volumeIds);
6542 aListOfGroups->length( nbGroups+1 );
6543 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6547 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6548 generateGroupName("affectedFaces").c_str());
6549 aNewFaceGroup->Add(faceIds);
6550 aListOfGroups->length( nbGroups+1 );
6551 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6555 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6556 generateGroupName("affectedEdges").c_str());
6557 aNewEdgeGroup->Add(edgeIds);
6558 aListOfGroups->length( nbGroups+1 );
6559 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6563 // Update Python script
6565 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6566 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6568 return aListOfGroups._retn();
6570 SMESH_CATCH( SMESH::throwCorbaException );
6574 //================================================================================
6576 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6577 The created 2D mesh elements based on nodes of free faces of boundary volumes
6578 \return TRUE if operation has been completed successfully, FALSE otherwise
6580 //================================================================================
6582 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6583 throw (SALOME::SALOME_Exception)
6588 bool aResult = getEditor().Make2DMeshFrom3D();
6590 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6592 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6595 SMESH_CATCH( SMESH::throwCorbaException );
6599 //================================================================================
6601 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6602 * The list of groups must contain at least two groups. The groups have to be disjoint:
6603 * no common element into two different groups.
6604 * The nodes of the internal faces at the boundaries of the groups are doubled.
6605 * Optionally, the internal faces are replaced by flat elements.
6606 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6607 * The flat elements are stored in groups of volumes.
6608 * These groups are named according to the position of the group in the list:
6609 * 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.
6610 * 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.
6611 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6612 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6613 * \param theDomains - list of groups of volumes
6614 * \param createJointElems - if TRUE, create the elements
6615 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6616 * the boundary between \a theDomains and the rest mesh
6617 * \return TRUE if operation has been completed successfully, FALSE otherwise
6619 //================================================================================
6622 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6623 CORBA::Boolean createJointElems,
6624 CORBA::Boolean onAllBoundaries )
6625 throw (SALOME::SALOME_Exception)
6632 SMESHDS_Mesh* aMeshDS = getMeshDS();
6634 // MESSAGE("theDomains.length = "<<theDomains.length());
6635 if ( theDomains.length() <= 1 && !onAllBoundaries )
6636 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6638 vector<TIDSortedElemSet> domains;
6639 domains.resize( theDomains.length() );
6641 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6643 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6644 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6646 // if ( aGrp->GetType() != SMESH::VOLUME )
6647 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6648 SMESH::long_array_var anIDs = aGrp->GetIDs();
6649 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6653 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6654 // TODO publish the groups of flat elements in study
6656 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6658 // Update Python script
6659 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6660 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6662 SMESH_CATCH( SMESH::throwCorbaException );
6664 myMesh_i->CreateGroupServants(); // publish created groups if any
6669 //================================================================================
6671 * \brief Double nodes on some external faces and create flat elements.
6672 * Flat elements are mainly used by some types of mechanic calculations.
6674 * Each group of the list must be constituted of faces.
6675 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6676 * @param theGroupsOfFaces - list of groups of faces
6677 * @return TRUE if operation has been completed successfully, FALSE otherwise
6679 //================================================================================
6682 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6683 throw (SALOME::SALOME_Exception)
6688 SMESHDS_Mesh* aMeshDS = getMeshDS();
6690 vector<TIDSortedElemSet> faceGroups;
6693 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6695 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6696 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6698 TIDSortedElemSet faceGroup;
6700 faceGroups.push_back(faceGroup);
6701 SMESH::long_array_var anIDs = aGrp->GetIDs();
6702 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6706 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6707 // TODO publish the groups of flat elements in study
6709 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6711 // Update Python script
6712 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6715 SMESH_CATCH( SMESH::throwCorbaException );
6719 //================================================================================
6721 * \brief Identify all the elements around a geom shape, get the faces delimiting
6724 * Build groups of volume to remove, groups of faces to replace on the skin of the
6725 * object, groups of faces to remove inside the object, (idem edges).
6726 * Build ordered list of nodes at the border of each group of faces to replace
6727 * (to be used to build a geom subshape).
6729 //================================================================================
6731 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6732 GEOM::GEOM_Object_ptr theShape,
6733 const char* groupName,
6734 const SMESH::double_array& theNodesCoords,
6735 SMESH::array_of_long_array_out GroupsOfNodes)
6736 throw (SALOME::SALOME_Exception)
6741 std::vector<std::vector<int> > aListOfListOfNodes;
6742 ::SMESH_MeshEditor aMeshEditor( myMesh );
6744 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6745 if ( !theNodeSearcher )
6746 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6748 vector<double> nodesCoords;
6749 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6751 nodesCoords.push_back( theNodesCoords[i] );
6754 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6755 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6756 nodesCoords, aListOfListOfNodes);
6758 GroupsOfNodes = new SMESH::array_of_long_array;
6759 GroupsOfNodes->length( aListOfListOfNodes.size() );
6760 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6761 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6763 vector<int>& aListOfNodes = *llIt;
6764 vector<int>::iterator lIt = aListOfNodes.begin();;
6765 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6766 aGroup.length( aListOfNodes.size() );
6767 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6768 aGroup[ j ] = (*lIt);
6770 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6773 << ", '" << groupName << "', "
6774 << theNodesCoords << " )";
6776 SMESH_CATCH( SMESH::throwCorbaException );
6779 // issue 20749 ===================================================================
6781 * \brief Creates missing boundary elements
6782 * \param elements - elements whose boundary is to be checked
6783 * \param dimension - defines type of boundary elements to create
6784 * \param groupName - a name of group to store created boundary elements in,
6785 * "" means not to create the group
6786 * \param meshName - a name of new mesh to store created boundary elements in,
6787 * "" means not to create the new mesh
6788 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6789 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6790 * boundary elements will be copied into the new mesh
6791 * \param group - returns the create group, if any
6792 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6794 // ================================================================================
6796 SMESH::SMESH_Mesh_ptr
6797 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6798 SMESH::Bnd_Dimension dim,
6799 const char* groupName,
6800 const char* meshName,
6801 CORBA::Boolean toCopyElements,
6802 CORBA::Boolean toCopyExistingBondary,
6803 SMESH::SMESH_Group_out group)
6804 throw (SALOME::SALOME_Exception)
6809 if ( dim > SMESH::BND_1DFROM2D )
6810 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6812 SMESHDS_Mesh* aMeshDS = getMeshDS();
6814 SMESH::SMESH_Mesh_var mesh_var;
6815 SMESH::SMESH_Group_var group_var;
6819 TIDSortedElemSet elements;
6820 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6821 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6825 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6826 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6828 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6830 // group of new boundary elements
6831 SMESH_Group* smesh_group = 0;
6832 if ( strlen(groupName) )
6834 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6835 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6836 smesh_group = group_i->GetSmeshGroup();
6840 getEditor().MakeBoundaryMesh( elements,
6841 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6845 toCopyExistingBondary);
6848 smesh_mesh->GetMeshDS()->Modified();
6851 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6853 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6854 if ( mesh_var->_is_nil() )
6855 pyDump << myMesh_i->_this() << ", ";
6857 pyDump << mesh_var << ", ";
6858 if ( group_var->_is_nil() )
6859 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6861 pyDump << group_var << " = ";
6862 pyDump << this << ".MakeBoundaryMesh( "
6864 << "SMESH." << dimName[int(dim)] << ", "
6865 << "'" << groupName << "', "
6866 << "'" << meshName<< "', "
6867 << toCopyElements << ", "
6868 << toCopyExistingBondary << ")";
6870 group = group_var._retn();
6871 return mesh_var._retn();
6873 SMESH_CATCH( SMESH::throwCorbaException );
6874 return SMESH::SMESH_Mesh::_nil();
6877 //================================================================================
6879 * \brief Creates missing boundary elements
6880 * \param dimension - defines type of boundary elements to create
6881 * \param groupName - a name of group to store all boundary elements in,
6882 * "" means not to create the group
6883 * \param meshName - a name of a new mesh, which is a copy of the initial
6884 * mesh + created boundary elements; "" means not to create the new mesh
6885 * \param toCopyAll - if true, the whole initial mesh will be copied into
6886 * the new mesh else only boundary elements will be copied into the new mesh
6887 * \param groups - optional groups of elements to make boundary around
6888 * \param mesh - returns the mesh where elements were added to
6889 * \param group - returns the created group, if any
6890 * \retval long - number of added boundary elements
6892 //================================================================================
6894 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6895 const char* groupName,
6896 const char* meshName,
6897 CORBA::Boolean toCopyAll,
6898 const SMESH::ListOfIDSources& groups,
6899 SMESH::SMESH_Mesh_out mesh,
6900 SMESH::SMESH_Group_out group)
6901 throw (SALOME::SALOME_Exception)
6906 if ( dim > SMESH::BND_1DFROM2D )
6907 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6909 // separate groups belonging to this and other mesh
6910 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6911 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6912 groupsOfThisMesh ->length( groups.length() );
6913 groupsOfOtherMesh->length( groups.length() );
6914 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6915 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
6917 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6918 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6919 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6921 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6922 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6923 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
6925 groupsOfThisMesh->length( nbGroups );
6926 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6931 if ( nbGroupsOfOtherMesh > 0 )
6933 // process groups belonging to another mesh
6934 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6935 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6936 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6937 groupsOfOtherMesh, mesh, group );
6940 SMESH::SMESH_Mesh_var mesh_var;
6941 SMESH::SMESH_Group_var group_var;
6944 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6945 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6949 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6951 /*toCopyGroups=*/false,
6952 /*toKeepIDs=*/true);
6954 mesh_var = makeMesh(meshName);
6956 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6957 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6960 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6961 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6963 // group of boundary elements
6964 SMESH_Group* smesh_group = 0;
6965 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6966 if ( strlen(groupName) )
6968 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6969 group_var = mesh_i->CreateGroup( groupType, groupName );
6970 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6971 smesh_group = group_i->GetSmeshGroup();
6974 TIDSortedElemSet elements;
6976 if ( groups.length() > 0 )
6978 for ( int i = 0; i < nbGroups; ++i )
6981 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6983 SMESH::Bnd_Dimension bdim =
6984 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6985 nbAdded += getEditor().MakeBoundaryMesh( elements,
6986 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6989 /*toCopyElements=*/false,
6990 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6991 /*toAddExistingBondary=*/true,
6992 /*aroundElements=*/true);
6998 nbAdded += getEditor().MakeBoundaryMesh( elements,
6999 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7002 /*toCopyElements=*/false,
7003 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7004 /*toAddExistingBondary=*/true);
7006 tgtMesh->GetMeshDS()->Modified();
7008 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7010 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7011 pyDump << "nbAdded, ";
7012 if ( mesh_var->_is_nil() )
7013 pyDump << myMesh_i->_this() << ", ";
7015 pyDump << mesh_var << ", ";
7016 if ( group_var->_is_nil() )
7017 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7019 pyDump << group_var << " = ";
7020 pyDump << this << ".MakeBoundaryElements( "
7021 << "SMESH." << dimName[int(dim)] << ", "
7022 << "'" << groupName << "', "
7023 << "'" << meshName<< "', "
7024 << toCopyAll << ", "
7027 mesh = mesh_var._retn();
7028 group = group_var._retn();
7031 SMESH_CATCH( SMESH::throwCorbaException );
7035 //================================================================================
7037 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7038 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7039 * plane passing through pairs of points specified by each PolySegment structure.
7040 * If there are several paths connecting a pair of points, the shortest path is
7041 * selected by the module. Position of the cutting plane is defined by the two
7042 * points and an optional vector lying on the plane specified by a PolySegment.
7043 * By default the vector is defined by Mesh module as following. A middle point
7044 * of the two given points is computed. The middle point is projected to the mesh.
7045 * The vector goes from the middle point to the projection point. In case of planar
7046 * mesh, the vector is normal to the mesh.
7047 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7048 * Return the used vector and position of the middle point.
7049 * \param [in] groupName - optional name of a group where created mesh segments will
7052 //================================================================================
7054 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7055 const char* theGroupName)
7056 throw (SALOME::SALOME_Exception)
7058 if ( theSegments.length() == 0 )
7059 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7060 if ( myMesh->NbFaces() == 0 )
7061 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7064 initData(/*deleteSearchers=*/false);
7066 SMESHDS_Group* groupDS = 0;
7067 SMESHDS_Mesh* meshDS = getMeshDS();
7068 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7070 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7071 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7072 while ( faceIt->more() )
7073 tmpMesh->Copy( faceIt->next() );
7074 meshDS = tmpMesh->GetMeshDS();
7076 else if ( theGroupName[0] ) // find/create a group of segments
7078 SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7079 while ( !groupDS && grpIt->more() )
7081 SMESH_Group* group = grpIt->next();
7082 if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7083 strcmp( group->GetName(), theGroupName ) == 0 )
7085 groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7090 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7092 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7093 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7097 // convert input polySegments
7098 ::SMESH_MeshEditor::TListOfPolySegments segments( theSegments.length() );
7099 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7101 SMESH::PolySegment& segIn = theSegments[ i ];
7102 ::SMESH_MeshEditor::PolySegment& segOut = segments[ i ];
7103 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7104 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7105 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7106 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7107 segOut.myVector.SetCoord( segIn.vector.PS.x,
7109 segIn.vector.PS.z );
7110 if ( !segOut.myNode1[0] )
7111 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node1ID1,
7112 SALOME::BAD_PARAM );
7113 if ( !segOut.myNode1[1] )
7114 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node2ID1,
7115 SALOME::BAD_PARAM );
7118 // get a static ElementSearcher
7119 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7120 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7121 if ( !theElementSearcher )
7122 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7125 getEditor().MakePolyLine( segments, groupDS, theElementSearcher );
7128 if ( myIsPreviewMode )
7130 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7132 SMESH::PolySegment& segOut = theSegments[ i ];
7133 ::SMESH_MeshEditor::PolySegment& segIn = segments[ i ];
7134 segOut.vector.PS.x = segIn.myVector.X();
7135 segOut.vector.PS.y = segIn.myVector.Y();
7136 segOut.vector.PS.z = segIn.myVector.Z();
7141 TPythonDump() << "_segments = []";
7142 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7144 SMESH::PolySegment& segIn = theSegments[ i ];
7145 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7146 << segIn.node1ID1 << ", "
7147 << segIn.node1ID2 << ", "
7148 << segIn.node2ID1 << ", "
7149 << segIn.node2ID2 << ", "
7150 << "smeshBuilder.MakeDirStruct( "
7151 << segIn.vector.PS.x << ", "
7152 << segIn.vector.PS.y << ", "
7153 << segIn.vector.PS.z << ")))";
7155 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7158 SMESH_CATCH( SMESH::throwCorbaException );