1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_SetIterator.hxx"
46 #include "SMDS_VolumeTool.hxx"
47 #include "SMESHDS_Group.hxx"
48 #include "SMESHDS_GroupOnGeom.hxx"
49 #include "SMESH_ControlsDef.hxx"
50 #include "SMESH_Filter_i.hxx"
51 #include "SMESH_Gen_i.hxx"
52 #include "SMESH_Group.hxx"
53 #include "SMESH_Group_i.hxx"
54 #include "SMESH_MeshAlgos.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PythonDump.hxx"
58 #include "SMESH_subMeshEventListener.hxx"
59 #include "SMESH_subMesh_i.hxx"
61 #include <utilities.h>
62 #include <Utils_ExceptHandlers.hxx>
63 #include <Utils_CorbaException.hxx>
64 #include <SALOMEDS_wrap.hxx>
65 #include <SALOME_GenericObj_i.hh>
67 #include <BRepAdaptor_Surface.hxx>
68 #include <BRep_Tool.hxx>
69 #include <TopExp_Explorer.hxx>
71 #include <TopoDS_Edge.hxx>
72 #include <TopoDS_Face.hxx>
77 #include <Standard_Failure.hxx>
78 #include <Standard_ErrorHandler.hxx>
83 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
85 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
88 using SMESH::TPythonDump;
91 namespace MeshEditor_I {
93 //=============================================================================
95 * \brief Mesh to apply modifications for preview purposes
97 //=============================================================================
99 struct TPreviewMesh: public SMESH_Mesh
101 SMDSAbs_ElementType myPreviewType; // type to show
103 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
104 _isShapeToMesh = (_id = 0);
105 _myMeshDS = new SMESHDS_Mesh( _id, true );
106 myPreviewType = previewElements;
108 //!< Copy a set of elements
109 void Copy(const TIDSortedElemSet & theElements,
110 TIDSortedElemSet& theCopyElements,
111 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
112 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
114 // loop on theIDsOfElements
115 TIDSortedElemSet::const_iterator eIt = theElements.begin();
116 for ( ; eIt != theElements.end(); ++eIt )
118 const SMDS_MeshElement* anElem = *eIt;
119 if ( !anElem ) continue;
120 SMDSAbs_ElementType type = anElem->GetType();
121 if ( type == theAvoidType ||
122 ( theSelectType != SMDSAbs_All && type != theSelectType ))
124 const SMDS_MeshElement* anElemCopy;
125 if ( type == SMDSAbs_Node)
126 anElemCopy = Copy( cast2Node(anElem) );
128 anElemCopy = Copy( anElem );
130 theCopyElements.insert( theCopyElements.end(), anElemCopy );
134 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
136 // copy element nodes
137 int anElemNbNodes = anElem->NbNodes();
138 vector< int > anElemNodesID( anElemNbNodes ) ;
139 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
140 for ( int i = 0; itElemNodes->more(); i++)
142 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
144 anElemNodesID[i] = anElemNode->GetID();
147 // creates a corresponding element on copied nodes
148 ::SMESH_MeshEditor::ElemFeatures elemType;
149 elemType.Init( anElem, /*basicOnly=*/false );
150 elemType.SetID( anElem->GetID() );
151 SMDS_MeshElement* anElemCopy =
152 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
156 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
158 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
159 anElemNode->GetID());
163 GetMeshDS()->ClearMesh();
165 void Remove( SMDSAbs_ElementType type )
167 Remove( GetMeshDS()->elementsIterator( type ));
169 void Remove( SMDS_ElemIteratorPtr eIt )
171 while ( eIt->more() )
172 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
174 };// struct TPreviewMesh
176 static SMESH_NodeSearcher * theNodeSearcher = 0;
177 static SMESH_ElementSearcher * theElementSearcher = 0;
179 //=============================================================================
181 * \brief Deleter of theNodeSearcher and theElementSearcher at any compute event occurred
183 //=============================================================================
185 struct TSearchersDeleter : public SMESH_subMeshEventListener
188 string myMeshPartIOR;
190 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
191 "SMESH_MeshEditor_i::TSearchersDeleter"),
193 //!< Delete theNodeSearcher
196 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
197 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
199 typedef map < int, SMESH_subMesh * > TDependsOnMap;
200 //!< The meshod called by submesh: do my main job
201 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
202 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
204 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
206 Unset( sm->GetFather() );
209 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
210 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
212 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
219 myMeshPartIOR = meshPartIOR;
220 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
221 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
222 while ( smIt->more() )
225 sm->SetEventListener( this, 0, sm );
229 //!< delete self from all submeshes
230 void Unset(SMESH_Mesh* mesh)
232 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
233 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
234 while ( smIt->more() )
235 smIt->next()->DeleteEventListener( this );
240 } theSearchersDeleter;
242 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
244 TCollection_AsciiString typeStr;
245 switch ( theMirrorType ) {
246 case SMESH::SMESH_MeshEditor::POINT:
247 typeStr = "SMESH.SMESH_MeshEditor.POINT";
249 case SMESH::SMESH_MeshEditor::AXIS:
250 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
253 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
257 //================================================================================
259 * \brief function for conversion of long_array to TIDSortedElemSet
260 * \param IDs - array of IDs
261 * \param aMesh - mesh
262 * \param aMap - collection to fill
263 * \param aType - element type
265 //================================================================================
267 void arrayToSet(const SMESH::long_array & IDs,
268 const SMESHDS_Mesh* aMesh,
269 TIDSortedElemSet& aMap,
270 const SMDSAbs_ElementType aType = SMDSAbs_All,
271 SMDS_MeshElement::Filter* aFilter = NULL)
273 SMDS_MeshElement::NonNullFilter filter1;
274 SMDS_MeshElement::TypeFilter filter2( aType );
276 if ( aFilter == NULL )
277 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
279 SMDS_MeshElement::Filter & filter = *aFilter;
281 if ( aType == SMDSAbs_Node )
282 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
283 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
285 aMap.insert( aMap.end(), elem );
288 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
289 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
291 aMap.insert( aMap.end(), elem );
295 //================================================================================
297 * \brief Retrieve nodes from SMESH_IDSource
299 //================================================================================
301 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
302 const SMESHDS_Mesh* theMeshDS,
303 TIDSortedNodeSet& theNodeSet)
306 if ( CORBA::is_nil( theObject ) )
308 SMESH::array_of_ElementType_var types = theObject->GetTypes();
309 SMESH::long_array_var aElementsId = theObject->GetIDs();
310 if ( types->length() == 1 && types[0] == SMESH::NODE)
312 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
313 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
314 theNodeSet.insert( theNodeSet.end(), n);
316 else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
318 SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
319 while ( nIt->more( ))
320 if ( const SMDS_MeshElement * elem = nIt->next() )
321 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
325 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
326 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
327 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
331 //================================================================================
333 * \brief Returns elements connected to the given elements
335 //================================================================================
337 void getElementsAround(const TIDSortedElemSet& theElements,
338 const SMESHDS_Mesh* theMeshDS,
339 TIDSortedElemSet& theElementsAround)
341 if ( theElements.empty() ) return;
343 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
344 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
346 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
347 return; // all the elements are in theElements
350 elemType = SMDSAbs_All;
352 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
354 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
355 for ( ; elemIt != theElements.end(); ++elemIt )
357 const SMDS_MeshElement* e = *elemIt;
358 int i = e->NbCornerNodes();
361 const SMDS_MeshNode* n = e->GetNode( i );
362 if ( !isNodeChecked[ n->GetID() ])
364 isNodeChecked[ n->GetID() ] = true;
365 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
366 while ( invIt->more() )
368 const SMDS_MeshElement* elemAround = invIt->next();
369 if ( !theElements.count( elemAround ))
370 theElementsAround.insert( elemAround );
377 //================================================================================
379 * \brief Return a string used to detect change of mesh part on which theElementSearcher
380 * is going to be used
382 //================================================================================
384 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type = SMESH::ALL )
386 if ( SMESH::DownCast<SMESH_Mesh_i*>( theMeshPart ))
388 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
389 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
390 // take into account passible group modification
391 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
392 partIOR += SMESH_Comment( type );
396 } // namespace MeshEditor_I
398 using namespace MeshEditor_I;
400 //=============================================================================
404 //=============================================================================
406 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
408 myMesh( &theMesh->GetImpl() ),
410 myIsPreviewMode ( isPreview ),
416 //================================================================================
420 //================================================================================
422 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
424 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
425 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
426 poa->deactivate_object(anObjectId.in());
428 //deleteAuxIDSources();
429 delete myPreviewMesh; myPreviewMesh = 0;
430 delete myPreviewEditor; myPreviewEditor = 0;
433 //================================================================================
435 * \brief Returns the mesh
437 //================================================================================
439 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
441 return myMesh_i->_this();
444 //================================================================================
446 * \brief Clear members
448 //================================================================================
450 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
452 if ( myIsPreviewMode ) {
453 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
456 if ( deleteSearchers )
457 TSearchersDeleter::Delete();
459 getEditor().GetError().reset();
460 getEditor().ClearLastCreated();
463 //================================================================================
465 * \brief Increment mesh modif time and optionally record that the performed
466 * modification may influence further mesh re-compute.
467 * \param [in] isReComputeSafe - true if the modification does not influence
468 * further mesh re-compute
470 //================================================================================
472 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
474 myMesh->GetMeshDS()->Modified();
475 if ( !isReComputeSafe )
476 myMesh->SetIsModified( true );
479 //================================================================================
481 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
482 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
484 //================================================================================
486 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
488 if ( myIsPreviewMode && !myPreviewEditor ) {
489 if ( !myPreviewMesh ) getPreviewMesh();
490 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
492 return myIsPreviewMode ? *myPreviewEditor : myEditor;
495 //================================================================================
497 * \brief Initialize and return myPreviewMesh
498 * \param previewElements - type of elements to show in preview
500 * WARNING: call it once per method!
502 //================================================================================
504 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
506 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
508 delete myPreviewEditor;
510 delete myPreviewMesh;
511 myPreviewMesh = new TPreviewMesh( previewElements );
513 myPreviewMesh->Clear();
514 return myPreviewMesh;
517 //================================================================================
519 * Return data of mesh edition preview
521 //================================================================================
523 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
524 throw (SALOME::SALOME_Exception)
527 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
529 if ( myIsPreviewMode || hasBadElems )
531 list<int> aNodesConnectivity;
532 typedef map<int, int> TNodesMap;
535 SMESHDS_Mesh* aMeshDS;
536 std::unique_ptr< SMESH_MeshPartDS > aMeshPartDS;
538 const list<const SMDS_MeshElement*>& badElems =
539 static_cast<SMESH_BadInputElements*>( getEditor().GetError().get() )->myBadElements;
540 aMeshPartDS.reset( new SMESH_MeshPartDS( badElems ));
541 aMeshDS = aMeshPartDS.get();
544 aMeshDS = getEditor().GetMeshDS();
546 myPreviewData = new SMESH::MeshPreviewStruct();
547 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
550 SMDSAbs_ElementType previewType = SMDSAbs_All;
552 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
553 previewType = aPreviewMesh->myPreviewType;
554 switch ( previewType ) {
555 case SMDSAbs_Edge : break;
556 case SMDSAbs_Face : break;
557 case SMDSAbs_Volume: break;
559 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
563 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
565 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
567 while ( itMeshElems->more() ) {
568 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
569 SMDS_NodeIteratorPtr itElemNodes =
570 (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
571 aMeshElem->interlacedNodesIterator() :
572 aMeshElem->nodeIterator() );
573 while ( itElemNodes->more() ) {
574 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
575 int aNodeID = aMeshNode->GetID();
576 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
577 if ( anIter == nodesMap.end() ) {
578 // filling the nodes coordinates
579 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
580 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
581 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
582 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
585 aNodesConnectivity.push_back(anIter->second);
588 // filling the elements types
589 SMDSAbs_ElementType aType = aMeshElem->GetType();
590 bool isPoly = aMeshElem->IsPoly();
591 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
592 myPreviewData->elementTypes[i].isPoly = isPoly;
593 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
596 myPreviewData->nodesXYZ.length( j );
598 // filling the elements connectivities
599 list<int>::iterator aConnIter = aNodesConnectivity.begin();
600 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
601 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
602 myPreviewData->elementConnectivities[i] = *aConnIter;
604 return myPreviewData._retn();
606 SMESH_CATCH( SMESH::throwCorbaException );
610 //================================================================================
612 * \brief Returns list of it's IDs of created nodes
613 * \retval SMESH::long_array* - list of node ID
615 //================================================================================
617 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
618 throw (SALOME::SALOME_Exception)
621 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
623 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
624 myLastCreatedNodes->length( aSeq.size() );
625 for ( size_t i = 0; i < aSeq.size(); i++)
626 myLastCreatedNodes[i] = aSeq[i]->GetID();
628 return myLastCreatedNodes._retn();
629 SMESH_CATCH( SMESH::throwCorbaException );
633 //================================================================================
635 * \brief Returns list of it's IDs of created elements
636 * \retval SMESH::long_array* - list of elements' ID
638 //================================================================================
640 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
641 throw (SALOME::SALOME_Exception)
644 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
646 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
647 myLastCreatedElems->length( aSeq.size() );
648 for ( size_t i = 0; i < aSeq.size(); i++ )
649 myLastCreatedElems[i] = aSeq[i]->GetID();
651 return myLastCreatedElems._retn();
652 SMESH_CATCH( SMESH::throwCorbaException );
656 //=======================================================================
657 //function : ClearLastCreated
658 //purpose : Clears sequences of last created elements and nodes
659 //=======================================================================
661 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
664 getEditor().ClearLastCreated();
665 SMESH_CATCH( SMESH::throwCorbaException );
668 //=======================================================================
670 * Returns description of an error/warning occurred during the last operation
671 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
673 //=======================================================================
675 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
676 throw (SALOME::SALOME_Exception)
679 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
680 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
681 if ( errIn && !errIn->IsOK() )
683 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
684 errOut->comment = errIn->myComment.c_str();
685 errOut->subShapeID = -1;
686 errOut->hasBadMesh = errIn->HasBadElems();
691 errOut->subShapeID = -1;
692 errOut->hasBadMesh = false;
695 return errOut._retn();
696 SMESH_CATCH( SMESH::throwCorbaException );
700 //=======================================================================
701 //function : MakeIDSource
702 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
703 // Call UnRegister() as you fininsh using it!!
704 //=======================================================================
706 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
707 public virtual SALOME::GenericObj_i
709 SMESH::long_array _ids;
710 SMESH::ElementType _type;
711 SMESH::SMESH_Mesh_ptr _mesh;
712 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
713 SMESH::long_array* GetMeshInfo() { return 0; }
714 SMESH::long_array* GetNbElementsByType()
716 SMESH::long_array_var aRes = new SMESH::long_array();
717 aRes->length(SMESH::NB_ELEMENT_TYPES);
718 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
719 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
722 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
723 bool IsMeshInfoCorrect() { return true; }
724 SMESH::array_of_ElementType* GetTypes()
726 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
727 if ( _ids.length() > 0 ) {
731 return types._retn();
733 SALOMEDS::TMPFile* GetVtkUgStream()
735 SALOMEDS::TMPFile_var SeqFile;
736 return SeqFile._retn();
740 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
741 SMESH::ElementType type)
743 _IDSource* idSrc = new _IDSource;
744 idSrc->_mesh = myMesh_i->_this();
747 if ( type == SMESH::ALL && ids.length() > 0 )
748 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
750 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
752 return anIDSourceVar._retn();
755 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
757 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
760 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
763 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
765 nbIds = (int) tmpIdSource->_ids.length();
766 return & tmpIdSource->_ids[0];
772 // void SMESH_MeshEditor_i::deleteAuxIDSources()
774 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
775 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
777 // myAuxIDSources.clear();
780 //=============================================================================
784 //=============================================================================
787 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
788 throw (SALOME::SALOME_Exception)
795 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
796 IdList.push_back( IDsOfElements[i] );
798 // Update Python script
799 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
802 bool ret = getEditor().Remove( IdList, false );
804 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
807 SMESH_CATCH( SMESH::throwCorbaException );
811 //=============================================================================
815 //=============================================================================
817 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
818 throw (SALOME::SALOME_Exception)
824 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
825 IdList.push_back( IDsOfNodes[i] );
827 // Update Python script
828 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
830 bool ret = getEditor().Remove( IdList, true );
832 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
835 SMESH_CATCH( SMESH::throwCorbaException );
839 //=============================================================================
843 //=============================================================================
845 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
846 throw (SALOME::SALOME_Exception)
851 // Update Python script
852 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
854 // Create filter to find all orphan nodes
855 SMESH::Controls::Filter::TIdSequence seq;
856 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
857 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
859 // remove orphan nodes (if there are any)
860 list< int > IdList( seq.begin(), seq.end() );
862 int nbNodesBefore = myMesh->NbNodes();
863 getEditor().Remove( IdList, true );
864 int nbNodesAfter = myMesh->NbNodes();
866 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
867 return nbNodesBefore - nbNodesAfter;
869 SMESH_CATCH( SMESH::throwCorbaException );
873 //=============================================================================
877 //=============================================================================
879 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
880 throw (SALOME::SALOME_Exception)
885 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
887 // Update Python script
888 TPythonDump() << "nodeID = " << this << ".AddNode( "
889 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
891 declareMeshModified( /*isReComputeSafe=*/false );
894 SMESH_CATCH( SMESH::throwCorbaException );
898 //=============================================================================
900 * Create 0D element on the given node.
902 //=============================================================================
904 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode,
905 CORBA::Boolean DuplicateElements)
906 throw (SALOME::SALOME_Exception)
911 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
912 SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
914 SMDS_MeshElement* elem = 0;
915 if ( DuplicateElements || !it0D->more() )
916 elem = getMeshDS()->Add0DElement(aNode);
918 // Update Python script
919 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
921 declareMeshModified( /*isReComputeSafe=*/false );
923 return elem ? elem->GetID() : 0;
925 SMESH_CATCH( SMESH::throwCorbaException );
929 //=============================================================================
931 * Create a ball element on the given node.
933 //=============================================================================
935 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
936 throw (SALOME::SALOME_Exception)
941 if ( diameter < std::numeric_limits<double>::min() )
942 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
944 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
945 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
947 // Update Python script
948 TPythonDump() << "ballElem = "
949 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
951 declareMeshModified( /*isReComputeSafe=*/false );
952 return elem ? elem->GetID() : 0;
954 SMESH_CATCH( SMESH::throwCorbaException );
958 //=============================================================================
960 * Create an edge, either linear and quadratic (this is determed
961 * by number of given nodes, two or three)
963 //=============================================================================
965 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
966 throw (SALOME::SALOME_Exception)
971 int NbNodes = IDsOfNodes.length();
972 SMDS_MeshElement* elem = 0;
975 CORBA::Long index1 = IDsOfNodes[0];
976 CORBA::Long index2 = IDsOfNodes[1];
977 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
978 getMeshDS()->FindNode(index2));
980 // Update Python script
981 TPythonDump() << "edge = " << this << ".AddEdge([ "
982 << index1 << ", " << index2 <<" ])";
985 CORBA::Long n1 = IDsOfNodes[0];
986 CORBA::Long n2 = IDsOfNodes[1];
987 CORBA::Long n12 = IDsOfNodes[2];
988 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
989 getMeshDS()->FindNode(n2),
990 getMeshDS()->FindNode(n12));
991 // Update Python script
992 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
993 <<n1<<", "<<n2<<", "<<n12<<" ])";
996 declareMeshModified( /*isReComputeSafe=*/false );
997 return elem ? elem->GetID() : 0;
999 SMESH_CATCH( SMESH::throwCorbaException );
1003 //=============================================================================
1007 //=============================================================================
1009 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1010 throw (SALOME::SALOME_Exception)
1015 int NbNodes = IDsOfNodes.length();
1021 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1022 for (int i = 0; i < NbNodes; i++)
1023 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1025 SMDS_MeshElement* elem = 0;
1027 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1028 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1029 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1030 nodes[4], nodes[5]); break;
1031 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1032 nodes[4], nodes[5], nodes[6]); break;
1033 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1034 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1035 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1036 nodes[4], nodes[5], nodes[6], nodes[7],
1038 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1041 // Update Python script
1042 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1044 declareMeshModified( /*isReComputeSafe=*/false );
1046 return elem ? elem->GetID() : 0;
1048 SMESH_CATCH( SMESH::throwCorbaException );
1052 //=============================================================================
1056 //=============================================================================
1058 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1059 throw (SALOME::SALOME_Exception)
1064 int NbNodes = IDsOfNodes.length();
1065 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1066 for (int i = 0; i < NbNodes; i++)
1067 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1070 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1072 // Update Python script
1073 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1075 declareMeshModified( /*isReComputeSafe=*/false );
1076 return elem ? elem->GetID() : 0;
1078 SMESH_CATCH( SMESH::throwCorbaException );
1082 //=============================================================================
1084 * AddQuadPolygonalFace
1086 //=============================================================================
1088 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1089 throw (SALOME::SALOME_Exception)
1094 int NbNodes = IDsOfNodes.length();
1095 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1096 for (int i = 0; i < NbNodes; i++)
1097 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1099 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1101 // Update Python script
1102 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1104 declareMeshModified( /*isReComputeSafe=*/false );
1105 return elem ? elem->GetID() : 0;
1107 SMESH_CATCH( SMESH::throwCorbaException );
1111 //=============================================================================
1113 * Create volume, either linear and quadratic (this is determed
1114 * by number of given nodes)
1116 //=============================================================================
1118 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1119 throw (SALOME::SALOME_Exception)
1124 int NbNodes = IDsOfNodes.length();
1125 vector< const SMDS_MeshNode*> n(NbNodes);
1126 for(int i=0;i<NbNodes;i++)
1127 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1129 SMDS_MeshElement* elem = 0;
1132 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1133 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1134 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1135 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1136 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1137 n[6],n[7],n[8],n[9]);
1139 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1140 n[6],n[7],n[8],n[9],n[10],n[11]);
1142 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1143 n[7],n[8],n[9],n[10],n[11],n[12]);
1145 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1146 n[9],n[10],n[11],n[12],n[13],n[14]);
1148 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1149 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1150 n[15],n[16],n[17],n[18],n[19]);
1152 case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1153 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1156 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1157 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1158 n[15],n[16],n[17],n[18],n[19],
1159 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1163 // Update Python script
1164 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1166 declareMeshModified( /*isReComputeSafe=*/false );
1167 return elem ? elem->GetID() : 0;
1169 SMESH_CATCH( SMESH::throwCorbaException );
1173 //=============================================================================
1175 * AddPolyhedralVolume
1177 //=============================================================================
1178 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1179 const SMESH::long_array & Quantities)
1180 throw (SALOME::SALOME_Exception)
1185 int NbNodes = IDsOfNodes.length();
1186 std::vector<const SMDS_MeshNode*> n (NbNodes);
1187 for (int i = 0; i < NbNodes; i++)
1189 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1190 if (!aNode) return 0;
1194 int NbFaces = Quantities.length();
1195 std::vector<int> q (NbFaces);
1196 for (int j = 0; j < NbFaces; j++)
1197 q[j] = Quantities[j];
1199 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1201 // Update Python script
1202 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1203 << IDsOfNodes << ", " << Quantities << " )";
1205 declareMeshModified( /*isReComputeSafe=*/false );
1206 return elem ? elem->GetID() : 0;
1208 SMESH_CATCH( SMESH::throwCorbaException );
1212 //=============================================================================
1214 * AddPolyhedralVolumeByFaces
1216 //=============================================================================
1218 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1219 throw (SALOME::SALOME_Exception)
1224 int NbFaces = IdsOfFaces.length();
1225 std::vector<const SMDS_MeshNode*> poly_nodes;
1226 std::vector<int> quantities (NbFaces);
1228 for (int i = 0; i < NbFaces; i++) {
1229 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1230 quantities[i] = aFace->NbNodes();
1232 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1233 while (It->more()) {
1234 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1238 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1240 // Update Python script
1241 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1242 << IdsOfFaces << " )";
1244 declareMeshModified( /*isReComputeSafe=*/false );
1245 return elem ? elem->GetID() : 0;
1247 SMESH_CATCH( SMESH::throwCorbaException );
1251 //=============================================================================
1253 // \brief Create 0D elements on all nodes of the given object.
1254 // \param theObject object on whose nodes 0D elements will be created.
1255 // \param theGroupName optional name of a group to add 0D elements created
1256 // and/or found on nodes of \a theObject.
1257 // \param DuplicateElements to add one more 0D element to a node or not.
1258 // \return an object (a new group or a temporary SMESH_IDSource) holding
1259 // ids of new and/or found 0D elements.
1261 //=============================================================================
1263 SMESH::SMESH_IDSource_ptr
1264 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1265 const char* theGroupName,
1266 CORBA::Boolean theDuplicateElements)
1267 throw (SALOME::SALOME_Exception)
1272 SMESH::SMESH_IDSource_var result;
1275 TIDSortedElemSet elements, elems0D;
1276 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1277 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1279 SMESH::long_array_var newElems = new SMESH::long_array;
1280 newElems->length( elems0D.size() );
1281 TIDSortedElemSet::iterator eIt = elems0D.begin();
1282 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1283 newElems[ i ] = (*eIt)->GetID();
1285 SMESH::SMESH_GroupBase_var groupToFill;
1286 if ( theGroupName && strlen( theGroupName ))
1288 // Get existing group named theGroupName
1289 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1290 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1291 SMESH::SMESH_GroupBase_var group = groups[i];
1292 if ( !group->_is_nil() ) {
1293 CORBA::String_var name = group->GetName();
1294 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1295 groupToFill = group;
1300 if ( groupToFill->_is_nil() )
1301 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1302 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1303 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1306 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1308 group_i->Add( newElems );
1309 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1310 pyDump << groupToFill;
1314 result = MakeIDSource( newElems, SMESH::ELEM0D );
1315 pyDump << "elem0DIDs";
1318 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1319 << theObject << ", '" << theGroupName << "' )";
1321 return result._retn();
1323 SMESH_CATCH( SMESH::throwCorbaException );
1327 //=============================================================================
1329 * \brief Bind a node to a vertex
1330 * \param NodeID - node ID
1331 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1332 * \retval boolean - false if NodeID or VertexID is invalid
1334 //=============================================================================
1336 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1337 throw (SALOME::SALOME_Exception)
1341 SMESHDS_Mesh * mesh = getMeshDS();
1342 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1344 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1346 if ( mesh->MaxShapeIndex() < VertexID )
1347 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1349 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1350 if ( shape.ShapeType() != TopAbs_VERTEX )
1351 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1353 mesh->SetNodeOnVertex( node, VertexID );
1355 myMesh->SetIsModified( true );
1357 SMESH_CATCH( SMESH::throwCorbaException );
1360 //=============================================================================
1362 * \brief Store node position on an edge
1363 * \param NodeID - node ID
1364 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1365 * \param paramOnEdge - parameter on edge where the node is located
1366 * \retval boolean - false if any parameter is invalid
1368 //=============================================================================
1370 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1371 CORBA::Double paramOnEdge)
1372 throw (SALOME::SALOME_Exception)
1376 SMESHDS_Mesh * mesh = getMeshDS();
1377 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1379 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1381 if ( mesh->MaxShapeIndex() < EdgeID )
1382 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1384 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1385 if ( shape.ShapeType() != TopAbs_EDGE )
1386 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1389 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1390 if ( paramOnEdge < f || paramOnEdge > l )
1391 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1393 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1395 myMesh->SetIsModified( true );
1397 SMESH_CATCH( SMESH::throwCorbaException );
1400 //=============================================================================
1402 * \brief Store node position on a face
1403 * \param NodeID - node ID
1404 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1405 * \param u - U parameter on face where the node is located
1406 * \param v - V parameter on face where the node is located
1407 * \retval boolean - false if any parameter is invalid
1409 //=============================================================================
1411 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1412 CORBA::Double u, CORBA::Double v)
1413 throw (SALOME::SALOME_Exception)
1416 SMESHDS_Mesh * mesh = getMeshDS();
1417 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1419 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1421 if ( mesh->MaxShapeIndex() < FaceID )
1422 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1424 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1425 if ( shape.ShapeType() != TopAbs_FACE )
1426 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1428 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1429 bool isOut = ( u < surf.FirstUParameter() ||
1430 u > surf.LastUParameter() ||
1431 v < surf.FirstVParameter() ||
1432 v > surf.LastVParameter() );
1436 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1437 << " u( " << surf.FirstUParameter()
1438 << "," << surf.LastUParameter()
1439 << ") v( " << surf.FirstVParameter()
1440 << "," << surf.LastVParameter() << ")" );
1442 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1445 mesh->SetNodeOnFace( node, FaceID, u, v );
1446 myMesh->SetIsModified( true );
1448 SMESH_CATCH( SMESH::throwCorbaException );
1451 //=============================================================================
1453 * \brief Bind a node to a solid
1454 * \param NodeID - node ID
1455 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1456 * \retval boolean - false if NodeID or SolidID is invalid
1458 //=============================================================================
1460 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1461 throw (SALOME::SALOME_Exception)
1464 SMESHDS_Mesh * mesh = getMeshDS();
1465 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1467 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1469 if ( mesh->MaxShapeIndex() < SolidID )
1470 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1472 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1473 if ( shape.ShapeType() != TopAbs_SOLID &&
1474 shape.ShapeType() != TopAbs_SHELL)
1475 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1477 mesh->SetNodeInVolume( node, SolidID );
1479 SMESH_CATCH( SMESH::throwCorbaException );
1482 //=============================================================================
1484 * \brief Bind an element to a shape
1485 * \param ElementID - element ID
1486 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1488 //=============================================================================
1490 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1491 CORBA::Long ShapeID)
1492 throw (SALOME::SALOME_Exception)
1495 SMESHDS_Mesh * mesh = getMeshDS();
1496 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1498 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1500 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1501 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1503 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1504 if ( shape.ShapeType() != TopAbs_EDGE &&
1505 shape.ShapeType() != TopAbs_FACE &&
1506 shape.ShapeType() != TopAbs_SOLID &&
1507 shape.ShapeType() != TopAbs_SHELL )
1508 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1510 mesh->SetMeshElementOnShape( elem, ShapeID );
1512 myMesh->SetIsModified( true );
1514 SMESH_CATCH( SMESH::throwCorbaException );
1517 //=============================================================================
1521 //=============================================================================
1523 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1524 CORBA::Long NodeID2)
1525 throw (SALOME::SALOME_Exception)
1530 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1531 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1535 // Update Python script
1536 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1537 << NodeID1 << ", " << NodeID2 << " )";
1539 int ret = getEditor().InverseDiag ( n1, n2 );
1541 declareMeshModified( /*isReComputeSafe=*/false );
1544 SMESH_CATCH( SMESH::throwCorbaException );
1548 //=============================================================================
1552 //=============================================================================
1554 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1555 CORBA::Long NodeID2)
1556 throw (SALOME::SALOME_Exception)
1561 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1562 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1566 // Update Python script
1567 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1568 << NodeID1 << ", " << NodeID2 << " )";
1571 bool stat = getEditor().DeleteDiag ( n1, n2 );
1573 declareMeshModified( /*isReComputeSafe=*/!stat );
1577 SMESH_CATCH( SMESH::throwCorbaException );
1581 //=============================================================================
1585 //=============================================================================
1587 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1588 throw (SALOME::SALOME_Exception)
1593 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1595 CORBA::Long index = IDsOfElements[i];
1596 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1598 getEditor().Reorient( elem );
1600 // Update Python script
1601 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1603 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1606 SMESH_CATCH( SMESH::throwCorbaException );
1610 //=============================================================================
1614 //=============================================================================
1616 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1617 throw (SALOME::SALOME_Exception)
1622 TPythonDump aTPythonDump; // suppress dump in Reorient()
1624 prepareIdSource( theObject );
1626 SMESH::long_array_var anElementsId = theObject->GetIDs();
1627 CORBA::Boolean isDone = Reorient(anElementsId);
1629 // Update Python script
1630 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1632 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1635 SMESH_CATCH( SMESH::throwCorbaException );
1639 //=======================================================================
1640 //function : Reorient2D
1641 //purpose : Reorient faces contained in \a the2Dgroup.
1642 // the2Dgroup - the mesh or its part to reorient
1643 // theDirection - desired direction of normal of \a theFace
1644 // theFace - ID of face whose orientation is checked.
1645 // It can be < 1 then \a thePoint is used to find a face.
1646 // thePoint - is used to find a face if \a theFace < 1.
1647 // return number of reoriented elements.
1648 //=======================================================================
1650 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1651 const SMESH::DirStruct& theDirection,
1652 CORBA::Long theFace,
1653 const SMESH::PointStruct& thePoint)
1654 throw (SALOME::SALOME_Exception)
1657 initData(/*deleteSearchers=*/false);
1659 TIDSortedElemSet elements;
1660 IDSource_Error error;
1661 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1662 if ( error == IDSource_EMPTY )
1664 if ( error == IDSource_INVALID )
1665 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1668 const SMDS_MeshElement* face = 0;
1671 face = getMeshDS()->FindElement( theFace );
1673 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1674 if ( face->GetType() != SMDSAbs_Face )
1675 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1679 // create theElementSearcher if needed
1680 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1681 if ( !theElementSearcher )
1683 if ( elements.empty() ) // search in the whole mesh
1685 if ( myMesh->NbFaces() == 0 )
1686 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1688 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1692 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1693 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1695 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1699 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1700 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1703 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1704 if ( !elements.empty() && !elements.count( face ))
1705 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1708 const SMESH::PointStruct * P = &theDirection.PS;
1709 gp_Vec dirVec( P->x, P->y, P->z );
1710 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1711 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1713 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1716 declareMeshModified( /*isReComputeSafe=*/false );
1718 TPythonDump() << this << ".Reorient2D( "
1719 << the2Dgroup << ", "
1720 << theDirection << ", "
1722 << thePoint << " )";
1726 SMESH_CATCH( SMESH::throwCorbaException );
1730 //=======================================================================
1731 //function : Reorient2DBy3D
1732 //purpose : Reorient faces basing on orientation of adjacent volumes.
1733 //=======================================================================
1735 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1736 SMESH::SMESH_IDSource_ptr volumeGroup,
1737 CORBA::Boolean outsideNormal)
1738 throw (SALOME::SALOME_Exception)
1743 TIDSortedElemSet volumes;
1744 IDSource_Error volsError;
1745 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1748 for ( size_t i = 0; i < faceGroups.length(); ++i )
1750 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1752 TIDSortedElemSet faces;
1753 IDSource_Error error;
1754 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1755 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1756 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1757 if ( error == IDSource_OK && volsError != IDSource_OK )
1758 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1760 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1762 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1767 declareMeshModified( /*isReComputeSafe=*/false );
1769 TPythonDump() << this << ".Reorient2DBy3D( "
1770 << faceGroups << ", "
1771 << volumeGroup << ", "
1772 << outsideNormal << " )";
1776 SMESH_CATCH( SMESH::throwCorbaException );
1780 //=============================================================================
1782 * \brief Fuse neighbour triangles into quadrangles.
1784 //=============================================================================
1786 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1787 SMESH::NumericalFunctor_ptr Criterion,
1788 CORBA::Double MaxAngle)
1789 throw (SALOME::SALOME_Exception)
1794 SMESHDS_Mesh* aMesh = getMeshDS();
1795 TIDSortedElemSet faces,copyFaces;
1796 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1797 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1798 TIDSortedElemSet* workElements = & faces;
1800 if ( myIsPreviewMode ) {
1801 SMDSAbs_ElementType select = SMDSAbs_Face;
1802 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1803 workElements = & copyFaces;
1806 SMESH::NumericalFunctor_i* aNumericalFunctor =
1807 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1808 SMESH::Controls::NumericalFunctorPtr aCrit;
1809 if ( !aNumericalFunctor )
1810 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1812 aCrit = aNumericalFunctor->GetNumericalFunctor();
1814 if ( !myIsPreviewMode ) {
1815 // Update Python script
1816 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1817 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1820 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1822 declareMeshModified( /*isReComputeSafe=*/!stat );
1825 SMESH_CATCH( SMESH::throwCorbaException );
1829 //=============================================================================
1831 * \brief Fuse neighbour triangles into quadrangles.
1833 //=============================================================================
1835 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1836 SMESH::NumericalFunctor_ptr Criterion,
1837 CORBA::Double MaxAngle)
1838 throw (SALOME::SALOME_Exception)
1843 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1845 prepareIdSource( theObject );
1846 SMESH::long_array_var anElementsId = theObject->GetIDs();
1847 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1849 if ( !myIsPreviewMode ) {
1850 SMESH::NumericalFunctor_i* aNumericalFunctor =
1851 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1853 // Update Python script
1854 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1855 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1860 SMESH_CATCH( SMESH::throwCorbaException );
1864 //=============================================================================
1866 * \brief Split quadrangles into triangles.
1868 //=============================================================================
1870 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1871 SMESH::NumericalFunctor_ptr Criterion)
1872 throw (SALOME::SALOME_Exception)
1877 SMESHDS_Mesh* aMesh = getMeshDS();
1878 TIDSortedElemSet faces;
1879 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1881 SMESH::NumericalFunctor_i* aNumericalFunctor =
1882 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1883 SMESH::Controls::NumericalFunctorPtr aCrit;
1884 if ( !aNumericalFunctor )
1885 aCrit.reset( new SMESH::Controls::AspectRatio() );
1887 aCrit = aNumericalFunctor->GetNumericalFunctor();
1890 // Update Python script
1891 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1893 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1895 declareMeshModified( /*isReComputeSafe=*/false );
1898 SMESH_CATCH( SMESH::throwCorbaException );
1902 //=============================================================================
1904 * \brief Split quadrangles into triangles.
1906 //=============================================================================
1908 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1909 SMESH::NumericalFunctor_ptr Criterion)
1910 throw (SALOME::SALOME_Exception)
1915 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1917 prepareIdSource( theObject );
1918 SMESH::long_array_var anElementsId = theObject->GetIDs();
1919 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1921 SMESH::NumericalFunctor_i* aNumericalFunctor =
1922 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1924 // Update Python script
1925 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1927 declareMeshModified( /*isReComputeSafe=*/false );
1930 SMESH_CATCH( SMESH::throwCorbaException );
1934 //================================================================================
1936 * \brief Split each of quadrangles into 4 triangles.
1937 * \param [in] theObject - theQuads Container of quadrangles to split.
1939 //================================================================================
1941 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1942 throw (SALOME::SALOME_Exception)
1947 TIDSortedElemSet faces;
1948 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1950 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1952 getEditor().QuadTo4Tri( faces );
1953 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1955 SMESH_CATCH( SMESH::throwCorbaException );
1958 //=============================================================================
1960 * \brief Split quadrangles into triangles.
1962 //=============================================================================
1964 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1965 CORBA::Boolean Diag13)
1966 throw (SALOME::SALOME_Exception)
1971 SMESHDS_Mesh* aMesh = getMeshDS();
1972 TIDSortedElemSet faces;
1973 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1975 // Update Python script
1976 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1977 << IDsOfElements << ", " << Diag13 << " )";
1979 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1981 declareMeshModified( /*isReComputeSafe=*/ !stat );
1984 SMESH_CATCH( SMESH::throwCorbaException );
1988 //=============================================================================
1990 * \brief Split quadrangles into triangles.
1992 //=============================================================================
1994 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1995 CORBA::Boolean Diag13)
1996 throw (SALOME::SALOME_Exception)
2001 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2003 prepareIdSource( theObject );
2004 SMESH::long_array_var anElementsId = theObject->GetIDs();
2005 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2007 // Update Python script
2008 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2009 << theObject << ", " << Diag13 << " )";
2011 declareMeshModified( /*isReComputeSafe=*/!isDone );
2014 SMESH_CATCH( SMESH::throwCorbaException );
2019 //=============================================================================
2021 * Find better splitting of the given quadrangle.
2022 * \param IDOfQuad ID of the quadrangle to be split.
2023 * \param Criterion A criterion to choose a diagonal for splitting.
2024 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2025 * diagonal is better, 0 if error occurs.
2027 //=============================================================================
2029 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2030 SMESH::NumericalFunctor_ptr Criterion)
2031 throw (SALOME::SALOME_Exception)
2036 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2037 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2039 SMESH::NumericalFunctor_i* aNumericalFunctor =
2040 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2041 SMESH::Controls::NumericalFunctorPtr aCrit;
2042 if (aNumericalFunctor)
2043 aCrit = aNumericalFunctor->GetNumericalFunctor();
2045 aCrit.reset(new SMESH::Controls::AspectRatio());
2047 int id = getEditor().BestSplit(quad, aCrit);
2048 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2052 SMESH_CATCH( SMESH::throwCorbaException );
2056 //================================================================================
2058 * \brief Split volumic elements into tetrahedrons
2060 //================================================================================
2062 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2063 CORBA::Short methodFlags)
2064 throw (SALOME::SALOME_Exception)
2069 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2070 const int noneFacet = -1;
2071 prepareIdSource( elems );
2072 if ( SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME ))
2073 while ( volIt->more() )
2074 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2076 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2077 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2079 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2080 << elems << ", " << methodFlags << " )";
2082 SMESH_CATCH( SMESH::throwCorbaException );
2085 //================================================================================
2087 * \brief Split hexahedra into triangular prisms
2088 * \param elems - elements to split
2089 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2090 * to split into triangles
2091 * \param methodFlags - flags passing splitting method:
2092 * 1 - split the hexahedron into 2 prisms
2093 * 2 - split the hexahedron into 4 prisms
2095 //================================================================================
2097 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2098 const SMESH::PointStruct & startHexPoint,
2099 const SMESH::DirStruct& facetToSplitNormal,
2100 CORBA::Short methodFlags,
2101 CORBA::Boolean allDomains)
2102 throw (SALOME::SALOME_Exception)
2106 prepareIdSource( elems );
2108 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2111 gp_Dir( facetToSplitNormal.PS.x,
2112 facetToSplitNormal.PS.y,
2113 facetToSplitNormal.PS.z ));
2114 TIDSortedElemSet elemSet;
2115 prepareIdSource( elems );
2116 SMESH::long_array_var anElementsId = elems->GetIDs();
2117 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2118 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2120 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2121 while ( !elemSet.empty() )
2123 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2127 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2128 for ( ; ef != elemFacets.end(); ++ef )
2129 elemSet.erase( ef->first );
2132 if ( methodFlags == 2 )
2133 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2135 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2137 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2138 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2140 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2142 << startHexPoint << ", "
2143 << facetToSplitNormal<< ", "
2144 << methodFlags<< ", "
2145 << allDomains << " )";
2147 SMESH_CATCH( SMESH::throwCorbaException );
2150 //================================================================================
2152 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2153 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2154 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2155 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2156 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2157 * will be split in order to keep the mesh conformal.
2158 * \param elems - elements to split
2160 //================================================================================
2162 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2163 throw (SALOME::SALOME_Exception)
2168 TIDSortedElemSet elemSet;
2169 for ( size_t i = 0; i < theElems.length(); ++i )
2171 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2172 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2173 if ( mesh->GetId() != myMesh_i->GetId() )
2174 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2176 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2178 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2180 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2182 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2183 << theElems << " )";
2185 SMESH_CATCH( SMESH::throwCorbaException );
2188 //=======================================================================
2191 //=======================================================================
2194 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2195 const SMESH::long_array & IDsOfFixedNodes,
2196 CORBA::Long MaxNbOfIterations,
2197 CORBA::Double MaxAspectRatio,
2198 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2199 throw (SALOME::SALOME_Exception)
2201 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2202 MaxAspectRatio, Method, false );
2206 //=======================================================================
2207 //function : SmoothParametric
2209 //=======================================================================
2212 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2213 const SMESH::long_array & IDsOfFixedNodes,
2214 CORBA::Long MaxNbOfIterations,
2215 CORBA::Double MaxAspectRatio,
2216 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2217 throw (SALOME::SALOME_Exception)
2219 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2220 MaxAspectRatio, Method, true );
2224 //=======================================================================
2225 //function : SmoothObject
2227 //=======================================================================
2230 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2231 const SMESH::long_array & IDsOfFixedNodes,
2232 CORBA::Long MaxNbOfIterations,
2233 CORBA::Double MaxAspectRatio,
2234 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2235 throw (SALOME::SALOME_Exception)
2237 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2238 MaxAspectRatio, Method, false);
2242 //=======================================================================
2243 //function : SmoothParametricObject
2245 //=======================================================================
2248 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2249 const SMESH::long_array & IDsOfFixedNodes,
2250 CORBA::Long MaxNbOfIterations,
2251 CORBA::Double MaxAspectRatio,
2252 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2253 throw (SALOME::SALOME_Exception)
2255 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2256 MaxAspectRatio, Method, true);
2260 //=============================================================================
2264 //=============================================================================
2267 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2268 const SMESH::long_array & IDsOfFixedNodes,
2269 CORBA::Long MaxNbOfIterations,
2270 CORBA::Double MaxAspectRatio,
2271 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2273 throw (SALOME::SALOME_Exception)
2278 SMESHDS_Mesh* aMesh = getMeshDS();
2280 TIDSortedElemSet elements;
2281 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2283 set<const SMDS_MeshNode*> fixedNodes;
2284 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2285 CORBA::Long index = IDsOfFixedNodes[i];
2286 const SMDS_MeshNode * node = aMesh->FindNode(index);
2288 fixedNodes.insert( node );
2290 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2291 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2292 method = ::SMESH_MeshEditor::CENTROIDAL;
2294 getEditor().Smooth(elements, fixedNodes, method,
2295 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2297 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2299 // Update Python script
2300 TPythonDump() << "isDone = " << this << "."
2301 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2302 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2303 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2304 << "SMESH.SMESH_MeshEditor."
2305 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2306 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2310 SMESH_CATCH( SMESH::throwCorbaException );
2314 //=============================================================================
2318 //=============================================================================
2321 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2322 const SMESH::long_array & IDsOfFixedNodes,
2323 CORBA::Long MaxNbOfIterations,
2324 CORBA::Double MaxAspectRatio,
2325 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2327 throw (SALOME::SALOME_Exception)
2332 TPythonDump aTPythonDump; // suppress dump in smooth()
2334 prepareIdSource( theObject );
2335 SMESH::long_array_var anElementsId = theObject->GetIDs();
2336 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2337 MaxAspectRatio, Method, IsParametric);
2339 // Update Python script
2340 aTPythonDump << "isDone = " << this << "."
2341 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2342 << theObject << ", " << IDsOfFixedNodes << ", "
2343 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2344 << "SMESH.SMESH_MeshEditor."
2345 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2346 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2350 SMESH_CATCH( SMESH::throwCorbaException );
2354 //=============================================================================
2358 //=============================================================================
2360 void SMESH_MeshEditor_i::RenumberNodes()
2361 throw (SALOME::SALOME_Exception)
2364 // Update Python script
2365 TPythonDump() << this << ".RenumberNodes()";
2367 getMeshDS()->Renumber( true );
2369 SMESH_CATCH( SMESH::throwCorbaException );
2372 //=============================================================================
2376 //=============================================================================
2378 void SMESH_MeshEditor_i::RenumberElements()
2379 throw (SALOME::SALOME_Exception)
2382 // Update Python script
2383 TPythonDump() << this << ".RenumberElements()";
2385 getMeshDS()->Renumber( false );
2387 SMESH_CATCH( SMESH::throwCorbaException );
2390 //=======================================================================
2392 * \brief Return groups by their IDs
2394 //=======================================================================
2396 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2397 throw (SALOME::SALOME_Exception)
2402 myMesh_i->CreateGroupServants();
2403 return myMesh_i->GetGroups( *groupIDs );
2405 SMESH_CATCH( SMESH::throwCorbaException );
2409 //=======================================================================
2410 //function : RotationSweepObjects
2412 //=======================================================================
2414 SMESH::ListOfGroups*
2415 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2416 const SMESH::ListOfIDSources & theEdges,
2417 const SMESH::ListOfIDSources & theFaces,
2418 const SMESH::AxisStruct & theAxis,
2419 CORBA::Double theAngleInRadians,
2420 CORBA::Long theNbOfSteps,
2421 CORBA::Double theTolerance,
2422 const bool theMakeGroups)
2423 throw (SALOME::SALOME_Exception)
2428 TIDSortedElemSet elemsNodes[2];
2429 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2430 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2431 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2433 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2434 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2435 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2436 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2438 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2439 bool makeWalls=true;
2440 if ( myIsPreviewMode )
2442 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2443 TPreviewMesh * tmpMesh = getPreviewMesh();
2444 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2445 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2446 workElements = & copyElements[0];
2447 //makeWalls = false; -- faces are needed for preview
2450 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2452 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2453 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2455 ::SMESH_MeshEditor::PGroupIDs groupIds =
2456 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2457 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2459 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2461 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2463 if ( !myIsPreviewMode )
2465 dumpGroupsList( aPythonDump, aGroups );
2466 aPythonDump << this<< ".RotationSweepObjects( "
2471 << TVar( theAngleInRadians ) << ", "
2472 << TVar( theNbOfSteps ) << ", "
2473 << TVar( theTolerance ) << ", "
2474 << theMakeGroups << " )";
2478 getPreviewMesh()->Remove( SMDSAbs_Volume );
2481 return aGroups ? aGroups : new SMESH::ListOfGroups;
2483 SMESH_CATCH( SMESH::throwCorbaException );
2487 namespace MeshEditor_I
2490 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2492 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2494 bool myIsExtrusionByNormal;
2496 static int makeFlags( CORBA::Boolean MakeGroups,
2497 CORBA::Boolean LinearVariation = false,
2498 CORBA::Boolean ByAverageNormal = false,
2499 CORBA::Boolean UseInputElemsOnly = false,
2500 CORBA::Long Flags = 0,
2501 CORBA::Boolean MakeBoundary = true )
2503 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2504 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2505 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2506 if ( LinearVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2507 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2511 ExtrusionParams(const SMESH::DirStruct & theDir,
2512 CORBA::Long theNbOfSteps,
2513 const SMESH::double_array & theScaleFactors,
2514 CORBA::Boolean theLinearVariation,
2515 const SMESH::double_array & theBasePoint,
2516 CORBA::Boolean theMakeGroups):
2517 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2521 toList( theScaleFactors ),
2522 TBasePoint( theBasePoint ),
2523 makeFlags( theMakeGroups, theLinearVariation )),
2524 myIsExtrusionByNormal( false )
2528 ExtrusionParams(const SMESH::DirStruct & theDir,
2529 CORBA::Long theNbOfSteps,
2530 CORBA::Boolean theMakeGroups,
2531 CORBA::Long theExtrFlags,
2532 CORBA::Double theSewTolerance):
2533 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2537 std::list<double>(),
2539 makeFlags( theMakeGroups, false, false, false,
2540 theExtrFlags, false ),
2542 myIsExtrusionByNormal( false )
2545 // params for extrusion by normal
2546 ExtrusionParams(CORBA::Double theStepSize,
2547 CORBA::Long theNbOfSteps,
2548 CORBA::Short theDim,
2549 CORBA::Boolean theByAverageNormal,
2550 CORBA::Boolean theUseInputElemsOnly,
2551 CORBA::Boolean theMakeGroups ):
2552 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2554 makeFlags( theMakeGroups, false,
2555 theByAverageNormal, theUseInputElemsOnly ),
2557 myIsExtrusionByNormal( true )
2563 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2568 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2570 std::list<double> scales;
2571 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2572 scales.push_back( theScaleFactors[i] );
2576 // structure used to convert SMESH::double_array to gp_XYZ*
2580 TBasePoint( const SMESH::double_array & theBasePoint )
2583 if ( theBasePoint.length() == 3 )
2585 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2589 operator const gp_XYZ*() const { return pp; }
2594 //=======================================================================
2596 * \brief Generate dim+1 elements by extrusion of elements along vector
2597 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2598 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2599 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2600 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2601 * \param [in] nbOfSteps - number of elements to generate from one element
2602 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2603 * corresponding to groups the input elements included in.
2604 * \return ListOfGroups - new groups created if \a toMakeGroups is true
2606 //=======================================================================
2608 SMESH::ListOfGroups*
2609 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2610 const SMESH::ListOfIDSources & theEdges,
2611 const SMESH::ListOfIDSources & theFaces,
2612 const SMESH::DirStruct & theStepVector,
2613 CORBA::Long theNbOfSteps,
2614 const SMESH::double_array & theScaleFactors,
2615 CORBA::Boolean theLinearVariation,
2616 const SMESH::double_array & theBasePoint,
2617 CORBA::Boolean theToMakeGroups)
2618 throw (SALOME::SALOME_Exception)
2623 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
2624 theLinearVariation, theBasePoint, theToMakeGroups );
2626 TIDSortedElemSet elemsNodes[2];
2627 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2628 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2629 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2631 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2632 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2633 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2634 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2636 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2637 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2638 if ( myIsPreviewMode )
2640 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2641 // previewType = SMDSAbs_Edge;
2643 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2644 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2645 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2646 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2647 workElements = & copyElements[0];
2649 params.SetNoGroups();
2651 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2653 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2654 ::SMESH_MeshEditor::PGroupIDs groupIds =
2655 getEditor().ExtrusionSweep( workElements, params, aHistory );
2657 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2659 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2661 if ( !myIsPreviewMode )
2663 dumpGroupsList( aPythonDump, aGroups );
2664 aPythonDump << this<< ".ExtrusionSweepObjects( "
2668 << theStepVector << ", "
2669 << TVar( theNbOfSteps ) << ", "
2670 << theToMakeGroups << " )";
2674 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2677 return aGroups ? aGroups : new SMESH::ListOfGroups;
2679 SMESH_CATCH( SMESH::throwCorbaException );
2683 //=======================================================================
2684 //function : ExtrusionByNormal
2686 //=======================================================================
2688 SMESH::ListOfGroups*
2689 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2690 CORBA::Double stepSize,
2691 CORBA::Long nbOfSteps,
2692 CORBA::Boolean byAverageNormal,
2693 CORBA::Boolean useInputElemsOnly,
2694 CORBA::Boolean makeGroups,
2696 throw (SALOME::SALOME_Exception)
2701 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2703 ExtrusionParams params( stepSize, nbOfSteps, dim,
2704 byAverageNormal, useInputElemsOnly, makeGroups );
2706 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2707 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2709 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2710 if (( elemTypes->length() == 1 ) &&
2711 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2712 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2715 TIDSortedElemSet elemsNodes[2];
2716 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2717 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2719 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2720 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2721 if ( myIsPreviewMode )
2723 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2724 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2725 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2726 workElements = & copyElements[0];
2728 params.SetNoGroups();
2731 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2732 ::SMESH_MeshEditor::PGroupIDs groupIds =
2733 getEditor().ExtrusionSweep( workElements, params, aHistory );
2735 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2737 if (!myIsPreviewMode) {
2738 dumpGroupsList(aPythonDump, aGroups);
2739 aPythonDump << this << ".ExtrusionByNormal( " << objects
2740 << ", " << TVar( stepSize )
2741 << ", " << TVar( nbOfSteps )
2742 << ", " << byAverageNormal
2743 << ", " << useInputElemsOnly
2744 << ", " << makeGroups
2750 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2753 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2755 return aGroups ? aGroups : new SMESH::ListOfGroups;
2757 SMESH_CATCH( SMESH::throwCorbaException );
2761 //=======================================================================
2762 //function : AdvancedExtrusion
2764 //=======================================================================
2766 SMESH::ListOfGroups*
2767 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2768 const SMESH::DirStruct & theStepVector,
2769 CORBA::Long theNbOfSteps,
2770 CORBA::Long theExtrFlags,
2771 CORBA::Double theSewTolerance,
2772 CORBA::Boolean theMakeGroups)
2773 throw (SALOME::SALOME_Exception)
2778 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2780 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2781 theExtrFlags, theSewTolerance );
2783 TIDSortedElemSet elemsNodes[2];
2784 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2786 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2787 ::SMESH_MeshEditor::PGroupIDs groupIds =
2788 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2790 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2792 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2794 if ( !myIsPreviewMode ) {
2795 dumpGroupsList(aPythonDump, aGroups);
2796 aPythonDump << this << ".AdvancedExtrusion( "
2797 << theIDsOfElements << ", "
2798 << theStepVector << ", "
2799 << theNbOfSteps << ", "
2800 << theExtrFlags << ", "
2801 << theSewTolerance << ", "
2802 << theMakeGroups << " )";
2806 getPreviewMesh()->Remove( SMDSAbs_Volume );
2809 return aGroups ? aGroups : new SMESH::ListOfGroups;
2811 SMESH_CATCH( SMESH::throwCorbaException );
2815 //================================================================================
2817 * \brief Convert extrusion error to IDL enum
2819 //================================================================================
2823 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2825 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2829 RETCASE( EXTR_NO_ELEMENTS );
2830 RETCASE( EXTR_PATH_NOT_EDGE );
2831 RETCASE( EXTR_BAD_PATH_SHAPE );
2832 RETCASE( EXTR_BAD_STARTING_NODE );
2833 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2834 RETCASE( EXTR_CANT_GET_TANGENT );
2836 return SMESH::SMESH_MeshEditor::EXTR_OK;
2840 //=======================================================================
2841 //function : extrusionAlongPath
2843 //=======================================================================
2844 SMESH::ListOfGroups*
2845 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2846 const SMESH::ListOfIDSources & theEdges,
2847 const SMESH::ListOfIDSources & theFaces,
2848 SMESH::SMESH_IDSource_ptr thePathMesh,
2849 GEOM::GEOM_Object_ptr thePathShape,
2850 CORBA::Long theNodeStart,
2851 CORBA::Boolean theHasAngles,
2852 const SMESH::double_array & theAngles,
2853 CORBA::Boolean theLinearVariation,
2854 CORBA::Boolean theHasRefPoint,
2855 const SMESH::PointStruct & theRefPoint,
2857 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2858 throw (SALOME::SALOME_Exception)
2863 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2865 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2866 if ( thePathMesh->_is_nil() )
2867 return aGroups._retn();
2870 SMESH_subMesh* aSubMesh = 0;
2871 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2872 if ( thePathShape->_is_nil() )
2874 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2875 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2877 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2878 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2879 if ( !aMeshImp ) return aGroups._retn();
2880 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2881 if ( !aSubMesh ) return aGroups._retn();
2883 else if ( !aMeshImp ||
2884 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2886 return aGroups._retn();
2891 if ( !aMeshImp ) return aGroups._retn();
2892 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2893 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2894 if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
2895 return aGroups._retn();
2898 SMDS_MeshNode* nodeStart =
2899 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2901 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2902 return aGroups._retn();
2905 TIDSortedElemSet elemsNodes[2];
2906 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2907 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2908 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2910 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2911 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2912 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2913 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2915 list<double> angles;
2916 for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) {
2917 angles.push_back( theAngles[i] );
2920 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2922 int nbOldGroups = myMesh->NbGroup();
2924 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2925 if ( myIsPreviewMode )
2927 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2928 TPreviewMesh * tmpMesh = getPreviewMesh();
2929 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2930 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2931 workElements = & copyElements[0];
2932 theMakeGroups = false;
2935 ::SMESH_MeshEditor::Extrusion_Error error;
2937 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2938 theHasAngles, angles, theLinearVariation,
2939 theHasRefPoint, refPnt, theMakeGroups );
2941 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2942 theHasAngles, angles, theLinearVariation,
2943 theHasRefPoint, refPnt, theMakeGroups );
2945 declareMeshModified( /*isReComputeSafe=*/true );
2946 theError = convExtrError( error );
2948 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2949 if ( theMakeGroups ) {
2950 list<int> groupIDs = myMesh->GetGroupIds();
2951 list<int>::iterator newBegin = groupIDs.begin();
2952 std::advance( newBegin, nbOldGroups ); // skip old groups
2953 groupIDs.erase( groupIDs.begin(), newBegin );
2954 aGroups = getGroups( & groupIDs );
2955 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2958 if ( !myIsPreviewMode ) {
2959 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2960 else aPythonDump << "(_noGroups, error) = ";
2961 aPythonDump << this << ".ExtrusionAlongPathObjects( "
2965 << thePathMesh << ", "
2966 << thePathShape << ", "
2967 << theNodeStart << ", "
2968 << theHasAngles << ", "
2969 << TVar( theAngles ) << ", "
2970 << theLinearVariation << ", "
2971 << theHasRefPoint << ", "
2972 << "SMESH.PointStruct( "
2973 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2974 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2975 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2976 << theMakeGroups << " )";
2980 getPreviewMesh()->Remove( SMDSAbs_Volume );
2983 return aGroups._retn();
2985 SMESH_CATCH( SMESH::throwCorbaException );
2989 //================================================================================
2991 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2992 * of given angles along path steps
2993 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2994 * which proceeds the extrusion
2995 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2996 * is used to define the sub-mesh for the path
2998 //================================================================================
3000 SMESH::double_array*
3001 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
3002 GEOM::GEOM_Object_ptr thePathShape,
3003 const SMESH::double_array & theAngles)
3005 SMESH::double_array_var aResult = new SMESH::double_array();
3006 int nbAngles = theAngles.length();
3007 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3009 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3010 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3011 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3012 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3013 return aResult._retn();
3014 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3015 if ( nbSteps == nbAngles )
3017 aResult.inout() = theAngles;
3021 aResult->length( nbSteps );
3022 double rAn2St = double( nbAngles ) / double( nbSteps );
3023 double angPrev = 0, angle;
3024 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3026 double angCur = rAn2St * ( iSt+1 );
3027 double angCurFloor = floor( angCur );
3028 double angPrevFloor = floor( angPrev );
3029 if ( angPrevFloor == angCurFloor )
3030 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3033 int iP = int( angPrevFloor );
3034 double angPrevCeil = ceil(angPrev);
3035 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3037 int iC = int( angCurFloor );
3038 if ( iC < nbAngles )
3039 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3041 iP = int( angPrevCeil );
3043 angle += theAngles[ iC ];
3045 aResult[ iSt ] = angle;
3050 // Update Python script
3051 TPythonDump() << "rotAngles = " << theAngles;
3052 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3053 << thePathMesh << ", "
3054 << thePathShape << ", "
3057 return aResult._retn();
3060 //=======================================================================
3063 //=======================================================================
3065 SMESH::ListOfGroups*
3066 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3067 const SMESH::AxisStruct & theAxis,
3068 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3069 CORBA::Boolean theCopy,
3071 ::SMESH_Mesh* theTargetMesh)
3072 throw (SALOME::SALOME_Exception)
3077 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3078 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3080 if ( theTargetMesh )
3084 switch ( theMirrorType ) {
3085 case SMESH::SMESH_MeshEditor::POINT:
3086 aTrsf.SetMirror( P );
3088 case SMESH::SMESH_MeshEditor::AXIS:
3089 aTrsf.SetMirror( gp_Ax1( P, V ));
3092 aTrsf.SetMirror( gp_Ax2( P, V ));
3095 TIDSortedElemSet copyElements;
3096 TIDSortedElemSet* workElements = & theElements;
3098 if ( myIsPreviewMode )
3100 TPreviewMesh * tmpMesh = getPreviewMesh();
3101 tmpMesh->Copy( theElements, copyElements);
3102 if ( !theCopy && !theTargetMesh )
3104 TIDSortedElemSet elemsAround, elemsAroundCopy;
3105 getElementsAround( theElements, getMeshDS(), elemsAround );
3106 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3108 workElements = & copyElements;
3109 theMakeGroups = false;
3112 ::SMESH_MeshEditor::PGroupIDs groupIds =
3113 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3115 if ( !myIsPreviewMode )
3117 if ( theTargetMesh )
3118 theTargetMesh->GetMeshDS()->Modified();
3120 declareMeshModified( /*isReComputeSafe=*/false );
3123 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3125 SMESH_CATCH( SMESH::throwCorbaException );
3129 //=======================================================================
3132 //=======================================================================
3134 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3135 const SMESH::AxisStruct & theAxis,
3136 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3137 CORBA::Boolean theCopy)
3138 throw (SALOME::SALOME_Exception)
3140 if ( !myIsPreviewMode ) {
3141 TPythonDump() << this << ".Mirror( "
3142 << theIDsOfElements << ", "
3144 << mirrorTypeName(theMirrorType) << ", "
3147 if ( theIDsOfElements.length() > 0 )
3149 TIDSortedElemSet elements;
3150 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3151 mirror(elements, theAxis, theMirrorType, theCopy, false);
3156 //=======================================================================
3157 //function : MirrorObject
3159 //=======================================================================
3161 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3162 const SMESH::AxisStruct & theAxis,
3163 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3164 CORBA::Boolean theCopy)
3165 throw (SALOME::SALOME_Exception)
3167 if ( !myIsPreviewMode ) {
3168 TPythonDump() << this << ".MirrorObject( "
3169 << theObject << ", "
3171 << mirrorTypeName(theMirrorType) << ", "
3174 TIDSortedElemSet elements;
3176 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3178 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3179 mirror(elements, theAxis, theMirrorType, theCopy, false);
3182 //=======================================================================
3183 //function : MirrorMakeGroups
3185 //=======================================================================
3187 SMESH::ListOfGroups*
3188 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3189 const SMESH::AxisStruct& theMirror,
3190 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3191 throw (SALOME::SALOME_Exception)
3193 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3195 SMESH::ListOfGroups * aGroups = 0;
3196 if ( theIDsOfElements.length() > 0 )
3198 TIDSortedElemSet elements;
3199 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3200 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3202 if (!myIsPreviewMode) {
3203 dumpGroupsList(aPythonDump, aGroups);
3204 aPythonDump << this << ".MirrorMakeGroups( "
3205 << theIDsOfElements << ", "
3206 << theMirror << ", "
3207 << mirrorTypeName(theMirrorType) << " )";
3212 //=======================================================================
3213 //function : MirrorObjectMakeGroups
3215 //=======================================================================
3217 SMESH::ListOfGroups*
3218 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3219 const SMESH::AxisStruct& theMirror,
3220 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3221 throw (SALOME::SALOME_Exception)
3223 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3225 SMESH::ListOfGroups * aGroups = 0;
3226 TIDSortedElemSet elements;
3227 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3228 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3230 if (!myIsPreviewMode)
3232 dumpGroupsList(aPythonDump,aGroups);
3233 aPythonDump << this << ".MirrorObjectMakeGroups( "
3234 << theObject << ", "
3235 << theMirror << ", "
3236 << mirrorTypeName(theMirrorType) << " )";
3241 //=======================================================================
3242 //function : MirrorMakeMesh
3244 //=======================================================================
3246 SMESH::SMESH_Mesh_ptr
3247 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3248 const SMESH::AxisStruct& theMirror,
3249 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3250 CORBA::Boolean theCopyGroups,
3251 const char* theMeshName)
3252 throw (SALOME::SALOME_Exception)
3254 SMESH_Mesh_i* mesh_i;
3255 SMESH::SMESH_Mesh_var mesh;
3256 { // open new scope to dump "MakeMesh" command
3257 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3259 TPythonDump pydump; // to prevent dump at mesh creation
3261 mesh = makeMesh( theMeshName );
3262 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3263 if (mesh_i && theIDsOfElements.length() > 0 )
3265 TIDSortedElemSet elements;
3266 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3267 mirror(elements, theMirror, theMirrorType,
3268 false, theCopyGroups, & mesh_i->GetImpl());
3269 mesh_i->CreateGroupServants();
3272 if (!myIsPreviewMode) {
3273 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3274 << theIDsOfElements << ", "
3275 << theMirror << ", "
3276 << mirrorTypeName(theMirrorType) << ", "
3277 << theCopyGroups << ", '"
3278 << theMeshName << "' )";
3283 if (!myIsPreviewMode && mesh_i)
3284 mesh_i->GetGroups();
3286 return mesh._retn();
3289 //=======================================================================
3290 //function : MirrorObjectMakeMesh
3292 //=======================================================================
3294 SMESH::SMESH_Mesh_ptr
3295 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3296 const SMESH::AxisStruct& theMirror,
3297 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3298 CORBA::Boolean theCopyGroups,
3299 const char* theMeshName)
3300 throw (SALOME::SALOME_Exception)
3302 SMESH_Mesh_i* mesh_i;
3303 SMESH::SMESH_Mesh_var mesh;
3304 { // open new scope to dump "MakeMesh" command
3305 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3307 TPythonDump pydump; // to prevent dump at mesh creation
3309 mesh = makeMesh( theMeshName );
3310 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3311 TIDSortedElemSet elements;
3313 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3315 mirror(elements, theMirror, theMirrorType,
3316 false, theCopyGroups, & mesh_i->GetImpl());
3317 mesh_i->CreateGroupServants();
3319 if (!myIsPreviewMode) {
3320 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3321 << theObject << ", "
3322 << theMirror << ", "
3323 << mirrorTypeName(theMirrorType) << ", "
3324 << theCopyGroups << ", '"
3325 << theMeshName << "' )";
3330 if (!myIsPreviewMode && mesh_i)
3331 mesh_i->GetGroups();
3333 return mesh._retn();
3336 //=======================================================================
3337 //function : translate
3339 //=======================================================================
3341 SMESH::ListOfGroups*
3342 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3343 const SMESH::DirStruct & theVector,
3344 CORBA::Boolean theCopy,
3346 ::SMESH_Mesh* theTargetMesh)
3347 throw (SALOME::SALOME_Exception)
3352 if ( theTargetMesh )
3356 const SMESH::PointStruct * P = &theVector.PS;
3357 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3359 TIDSortedElemSet copyElements;
3360 TIDSortedElemSet* workElements = &theElements;
3362 if ( myIsPreviewMode )
3364 TPreviewMesh * tmpMesh = getPreviewMesh();
3365 tmpMesh->Copy( theElements, copyElements);
3366 if ( !theCopy && !theTargetMesh )
3368 TIDSortedElemSet elemsAround, elemsAroundCopy;
3369 getElementsAround( theElements, getMeshDS(), elemsAround );
3370 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3372 workElements = & copyElements;
3373 theMakeGroups = false;
3376 ::SMESH_MeshEditor::PGroupIDs groupIds =
3377 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3379 if ( !myIsPreviewMode )
3381 if ( theTargetMesh )
3382 theTargetMesh->GetMeshDS()->Modified();
3384 declareMeshModified( /*isReComputeSafe=*/false );
3387 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3389 SMESH_CATCH( SMESH::throwCorbaException );
3393 //=======================================================================
3394 //function : Translate
3396 //=======================================================================
3398 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3399 const SMESH::DirStruct & theVector,
3400 CORBA::Boolean theCopy)
3401 throw (SALOME::SALOME_Exception)
3403 if (!myIsPreviewMode) {
3404 TPythonDump() << this << ".Translate( "
3405 << theIDsOfElements << ", "
3406 << theVector << ", "
3409 if (theIDsOfElements.length()) {
3410 TIDSortedElemSet elements;
3411 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3412 translate(elements, theVector, theCopy, false);
3416 //=======================================================================
3417 //function : TranslateObject
3419 //=======================================================================
3421 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3422 const SMESH::DirStruct & theVector,
3423 CORBA::Boolean theCopy)
3424 throw (SALOME::SALOME_Exception)
3426 if (!myIsPreviewMode) {
3427 TPythonDump() << this << ".TranslateObject( "
3428 << theObject << ", "
3429 << theVector << ", "
3432 TIDSortedElemSet elements;
3434 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3436 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3437 translate(elements, theVector, theCopy, false);
3440 //=======================================================================
3441 //function : TranslateMakeGroups
3443 //=======================================================================
3445 SMESH::ListOfGroups*
3446 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3447 const SMESH::DirStruct& theVector)
3448 throw (SALOME::SALOME_Exception)
3450 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3452 SMESH::ListOfGroups * aGroups = 0;
3453 if (theIDsOfElements.length()) {
3454 TIDSortedElemSet elements;
3455 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3456 aGroups = translate(elements,theVector,true,true);
3458 if (!myIsPreviewMode) {
3459 dumpGroupsList(aPythonDump, aGroups);
3460 aPythonDump << this << ".TranslateMakeGroups( "
3461 << theIDsOfElements << ", "
3462 << theVector << " )";
3467 //=======================================================================
3468 //function : TranslateObjectMakeGroups
3470 //=======================================================================
3472 SMESH::ListOfGroups*
3473 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3474 const SMESH::DirStruct& theVector)
3475 throw (SALOME::SALOME_Exception)
3477 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3479 SMESH::ListOfGroups * aGroups = 0;
3480 TIDSortedElemSet elements;
3481 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3482 aGroups = translate(elements, theVector, true, true);
3484 if (!myIsPreviewMode) {
3485 dumpGroupsList(aPythonDump, aGroups);
3486 aPythonDump << this << ".TranslateObjectMakeGroups( "
3487 << theObject << ", "
3488 << theVector << " )";
3493 //=======================================================================
3494 //function : TranslateMakeMesh
3496 //=======================================================================
3498 SMESH::SMESH_Mesh_ptr
3499 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3500 const SMESH::DirStruct& theVector,
3501 CORBA::Boolean theCopyGroups,
3502 const char* theMeshName)
3503 throw (SALOME::SALOME_Exception)
3505 SMESH_Mesh_i* mesh_i;
3506 SMESH::SMESH_Mesh_var mesh;
3508 { // open new scope to dump "MakeMesh" command
3509 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3511 TPythonDump pydump; // to prevent dump at mesh creation
3513 mesh = makeMesh( theMeshName );
3514 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3516 if ( mesh_i && theIDsOfElements.length() )
3518 TIDSortedElemSet elements;
3519 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3520 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3521 mesh_i->CreateGroupServants();
3524 if ( !myIsPreviewMode ) {
3525 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3526 << theIDsOfElements << ", "
3527 << theVector << ", "
3528 << theCopyGroups << ", '"
3529 << theMeshName << "' )";
3534 if (!myIsPreviewMode && mesh_i)
3535 mesh_i->GetGroups();
3537 return mesh._retn();
3540 //=======================================================================
3541 //function : TranslateObjectMakeMesh
3543 //=======================================================================
3545 SMESH::SMESH_Mesh_ptr
3546 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3547 const SMESH::DirStruct& theVector,
3548 CORBA::Boolean theCopyGroups,
3549 const char* theMeshName)
3550 throw (SALOME::SALOME_Exception)
3553 SMESH_Mesh_i* mesh_i;
3554 SMESH::SMESH_Mesh_var mesh;
3555 { // open new scope to dump "MakeMesh" command
3556 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3558 TPythonDump pydump; // to prevent dump at mesh creation
3559 mesh = makeMesh( theMeshName );
3560 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3562 TIDSortedElemSet elements;
3564 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3566 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3567 mesh_i->CreateGroupServants();
3569 if ( !myIsPreviewMode ) {
3570 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3571 << theObject << ", "
3572 << theVector << ", "
3573 << theCopyGroups << ", '"
3574 << theMeshName << "' )";
3579 if (!myIsPreviewMode && mesh_i)
3580 mesh_i->GetGroups();
3582 return mesh._retn();
3584 SMESH_CATCH( SMESH::throwCorbaException );
3588 //=======================================================================
3591 //=======================================================================
3593 SMESH::ListOfGroups*
3594 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3595 const SMESH::AxisStruct & theAxis,
3596 CORBA::Double theAngle,
3597 CORBA::Boolean theCopy,
3599 ::SMESH_Mesh* theTargetMesh)
3600 throw (SALOME::SALOME_Exception)
3605 if ( theTargetMesh )
3608 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3609 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3612 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3614 TIDSortedElemSet copyElements;
3615 TIDSortedElemSet* workElements = &theElements;
3616 if ( myIsPreviewMode ) {
3617 TPreviewMesh * tmpMesh = getPreviewMesh();
3618 tmpMesh->Copy( theElements, copyElements );
3619 if ( !theCopy && !theTargetMesh )
3621 TIDSortedElemSet elemsAround, elemsAroundCopy;
3622 getElementsAround( theElements, getMeshDS(), elemsAround );
3623 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3625 workElements = ©Elements;
3626 theMakeGroups = false;
3629 ::SMESH_MeshEditor::PGroupIDs groupIds =
3630 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3632 if ( !myIsPreviewMode)
3634 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3635 else declareMeshModified( /*isReComputeSafe=*/false );
3638 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3640 SMESH_CATCH( SMESH::throwCorbaException );
3644 //=======================================================================
3647 //=======================================================================
3649 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3650 const SMESH::AxisStruct & theAxis,
3651 CORBA::Double theAngle,
3652 CORBA::Boolean theCopy)
3653 throw (SALOME::SALOME_Exception)
3655 if (!myIsPreviewMode) {
3656 TPythonDump() << this << ".Rotate( "
3657 << theIDsOfElements << ", "
3659 << TVar( theAngle ) << ", "
3662 if (theIDsOfElements.length() > 0)
3664 TIDSortedElemSet elements;
3665 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3666 rotate(elements,theAxis,theAngle,theCopy,false);
3670 //=======================================================================
3671 //function : RotateObject
3673 //=======================================================================
3675 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3676 const SMESH::AxisStruct & theAxis,
3677 CORBA::Double theAngle,
3678 CORBA::Boolean theCopy)
3679 throw (SALOME::SALOME_Exception)
3681 if ( !myIsPreviewMode ) {
3682 TPythonDump() << this << ".RotateObject( "
3683 << theObject << ", "
3685 << TVar( theAngle ) << ", "
3688 TIDSortedElemSet elements;
3689 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3690 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3691 rotate(elements,theAxis,theAngle,theCopy,false);
3694 //=======================================================================
3695 //function : RotateMakeGroups
3697 //=======================================================================
3699 SMESH::ListOfGroups*
3700 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3701 const SMESH::AxisStruct& theAxis,
3702 CORBA::Double theAngle)
3703 throw (SALOME::SALOME_Exception)
3705 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3707 SMESH::ListOfGroups * aGroups = 0;
3708 if (theIDsOfElements.length() > 0)
3710 TIDSortedElemSet elements;
3711 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3712 aGroups = rotate(elements,theAxis,theAngle,true,true);
3714 if (!myIsPreviewMode) {
3715 dumpGroupsList(aPythonDump, aGroups);
3716 aPythonDump << this << ".RotateMakeGroups( "
3717 << theIDsOfElements << ", "
3719 << TVar( theAngle ) << " )";
3724 //=======================================================================
3725 //function : RotateObjectMakeGroups
3727 //=======================================================================
3729 SMESH::ListOfGroups*
3730 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3731 const SMESH::AxisStruct& theAxis,
3732 CORBA::Double theAngle)
3733 throw (SALOME::SALOME_Exception)
3735 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3737 SMESH::ListOfGroups * aGroups = 0;
3738 TIDSortedElemSet elements;
3739 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3740 aGroups = rotate(elements, theAxis, theAngle, true, true);
3742 if (!myIsPreviewMode) {
3743 dumpGroupsList(aPythonDump, aGroups);
3744 aPythonDump << this << ".RotateObjectMakeGroups( "
3745 << theObject << ", "
3747 << TVar( theAngle ) << " )";
3752 //=======================================================================
3753 //function : RotateMakeMesh
3755 //=======================================================================
3757 SMESH::SMESH_Mesh_ptr
3758 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3759 const SMESH::AxisStruct& theAxis,
3760 CORBA::Double theAngleInRadians,
3761 CORBA::Boolean theCopyGroups,
3762 const char* theMeshName)
3763 throw (SALOME::SALOME_Exception)
3766 SMESH::SMESH_Mesh_var mesh;
3767 SMESH_Mesh_i* mesh_i;
3769 { // open new scope to dump "MakeMesh" command
3770 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3772 TPythonDump pydump; // to prevent dump at mesh creation
3774 mesh = makeMesh( theMeshName );
3775 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3777 if ( mesh_i && theIDsOfElements.length() > 0 )
3779 TIDSortedElemSet elements;
3780 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3781 rotate(elements, theAxis, theAngleInRadians,
3782 false, theCopyGroups, & mesh_i->GetImpl());
3783 mesh_i->CreateGroupServants();
3785 if ( !myIsPreviewMode ) {
3786 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3787 << theIDsOfElements << ", "
3789 << TVar( theAngleInRadians ) << ", "
3790 << theCopyGroups << ", '"
3791 << theMeshName << "' )";
3796 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3797 mesh_i->GetGroups();
3799 return mesh._retn();
3801 SMESH_CATCH( SMESH::throwCorbaException );
3805 //=======================================================================
3806 //function : RotateObjectMakeMesh
3808 //=======================================================================
3810 SMESH::SMESH_Mesh_ptr
3811 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3812 const SMESH::AxisStruct& theAxis,
3813 CORBA::Double theAngleInRadians,
3814 CORBA::Boolean theCopyGroups,
3815 const char* theMeshName)
3816 throw (SALOME::SALOME_Exception)
3819 SMESH::SMESH_Mesh_var mesh;
3820 SMESH_Mesh_i* mesh_i;
3822 {// open new scope to dump "MakeMesh" command
3823 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3825 TPythonDump pydump; // to prevent dump at mesh creation
3826 mesh = makeMesh( theMeshName );
3827 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3829 TIDSortedElemSet elements;
3831 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3833 rotate(elements, theAxis, theAngleInRadians,
3834 false, theCopyGroups, & mesh_i->GetImpl());
3835 mesh_i->CreateGroupServants();
3837 if ( !myIsPreviewMode ) {
3838 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3839 << theObject << ", "
3841 << TVar( theAngleInRadians ) << ", "
3842 << theCopyGroups << ", '"
3843 << theMeshName << "' )";
3848 if (!myIsPreviewMode && mesh_i)
3849 mesh_i->GetGroups();
3851 return mesh._retn();
3853 SMESH_CATCH( SMESH::throwCorbaException );
3857 //=======================================================================
3860 //=======================================================================
3862 SMESH::ListOfGroups*
3863 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3864 const SMESH::PointStruct& thePoint,
3865 const SMESH::double_array& theScaleFact,
3866 CORBA::Boolean theCopy,
3868 ::SMESH_Mesh* theTargetMesh)
3869 throw (SALOME::SALOME_Exception)
3873 if ( theScaleFact.length() < 1 )
3874 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3875 if ( theScaleFact.length() == 2 )
3876 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3878 if ( theTargetMesh )
3881 TIDSortedElemSet elements;
3882 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3883 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3888 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3889 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3893 // fight against orthogonalization
3894 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3895 // 0, S[1], 0, thePoint.y * (1-S[1]),
3896 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3897 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3898 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3899 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3900 loc.SetCoord( thePoint.x * (1-S[0]),
3901 thePoint.y * (1-S[1]),
3902 thePoint.z * (1-S[2]));
3903 M.SetDiagonal( S[0], S[1], S[2] );
3905 TIDSortedElemSet copyElements;
3906 TIDSortedElemSet* workElements = &elements;
3907 if ( myIsPreviewMode )
3909 TPreviewMesh * tmpMesh = getPreviewMesh();
3910 tmpMesh->Copy( elements, copyElements);
3911 if ( !theCopy && !theTargetMesh )
3913 TIDSortedElemSet elemsAround, elemsAroundCopy;
3914 getElementsAround( elements, getMeshDS(), elemsAround );
3915 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3917 workElements = & copyElements;
3918 theMakeGroups = false;
3921 ::SMESH_MeshEditor::PGroupIDs groupIds =
3922 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3924 if ( !myIsPreviewMode )
3926 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3927 else declareMeshModified( /*isReComputeSafe=*/false );
3929 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3931 SMESH_CATCH( SMESH::throwCorbaException );
3935 //=======================================================================
3938 //=======================================================================
3940 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3941 const SMESH::PointStruct& thePoint,
3942 const SMESH::double_array& theScaleFact,
3943 CORBA::Boolean theCopy)
3944 throw (SALOME::SALOME_Exception)
3946 if ( !myIsPreviewMode ) {
3947 TPythonDump() << this << ".Scale( "
3948 << theObject << ", "
3950 << TVar( theScaleFact ) << ", "
3953 scale(theObject, thePoint, theScaleFact, theCopy, false);
3957 //=======================================================================
3958 //function : ScaleMakeGroups
3960 //=======================================================================
3962 SMESH::ListOfGroups*
3963 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3964 const SMESH::PointStruct& thePoint,
3965 const SMESH::double_array& theScaleFact)
3966 throw (SALOME::SALOME_Exception)
3968 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3970 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3971 if (!myIsPreviewMode) {
3972 dumpGroupsList(aPythonDump, aGroups);
3973 aPythonDump << this << ".Scale("
3976 << TVar( theScaleFact ) << ",True,True)";
3982 //=======================================================================
3983 //function : ScaleMakeMesh
3985 //=======================================================================
3987 SMESH::SMESH_Mesh_ptr
3988 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3989 const SMESH::PointStruct& thePoint,
3990 const SMESH::double_array& theScaleFact,
3991 CORBA::Boolean theCopyGroups,
3992 const char* theMeshName)
3993 throw (SALOME::SALOME_Exception)
3995 SMESH_Mesh_i* mesh_i;
3996 SMESH::SMESH_Mesh_var mesh;
3997 { // open new scope to dump "MakeMesh" command
3998 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4000 TPythonDump pydump; // to prevent dump at mesh creation
4001 mesh = makeMesh( theMeshName );
4002 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4006 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4007 mesh_i->CreateGroupServants();
4009 if ( !myIsPreviewMode )
4010 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4011 << theObject << ", "
4013 << TVar( theScaleFact ) << ", "
4014 << theCopyGroups << ", '"
4015 << theMeshName << "' )";
4019 if (!myIsPreviewMode && mesh_i)
4020 mesh_i->GetGroups();
4022 return mesh._retn();
4025 //================================================================================
4027 * \brief Make an offset mesh from a source 2D mesh
4028 * \param [inout] theObject - source mesh. New elements are added to this mesh
4029 * if \a theMeshName is empty.
4030 * \param [in] theValue - offset value
4031 * \param [in] theCopyGroups - to generate groups
4032 * \param [in] theMeshName - optional name of a new mesh
4033 * \param [out] theGroups - new groups
4034 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
4036 //================================================================================
4038 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4039 CORBA::Double theValue,
4040 CORBA::Boolean theCopyGroups,
4041 CORBA::Boolean theCopyElements,
4042 const char* theMeshName,
4043 SMESH::ListOfGroups_out theGroups)
4044 throw (SALOME::SALOME_Exception)
4049 SMESHDS_Mesh* aMeshDS = getMeshDS();
4051 SMESH::SMESH_Mesh_var mesh_var;
4052 ::SMESH_MeshEditor::PGroupIDs groupIds;
4056 TIDSortedElemSet elements, copyElements;
4057 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4058 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4061 SMESH_Mesh* tgtMesh = 0;
4062 if ( myIsPreviewMode )
4064 TPreviewMesh * tmpMesh = getPreviewMesh();
4066 tmpMesh->Copy( elements, copyElements );
4067 elements.swap( copyElements );
4068 theCopyGroups = false;
4069 theCopyElements = false;
4074 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4075 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4076 tgtMesh = & mesh_i->GetImpl();
4078 groupIds = getEditor().Offset( elements, theValue, tgtMesh,
4079 theCopyGroups, theCopyElements, !myIsPreviewMode );
4081 tgtMesh->GetMeshDS()->Modified();
4084 if ( myIsPreviewMode )
4086 //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4090 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4092 if ( *theMeshName && mesh_var->NbFaces() == 0 )
4094 // new mesh empty, remove it
4095 SALOMEDS::Study_var study = SMESH_Gen_i::getStudyServant();
4096 SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
4097 SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::ObjectToSObject( mesh_var );
4098 builder->RemoveObjectWithChildren( meshSO );
4099 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4102 // result of Offset() is a tuple (mesh, groups)
4103 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4104 else pyDump << mesh_var << ", ";
4105 pyDump << theGroups << " = " << this << ".Offset( "
4106 << theObject << ", "
4108 << theCopyGroups << ", "
4109 << theCopyElements << ", "
4110 << "'" << theMeshName<< "')";
4113 return mesh_var._retn();
4115 SMESH_CATCH( SMESH::throwCorbaException );
4116 return SMESH::SMESH_Mesh::_nil();
4119 //=======================================================================
4120 //function : findCoincidentNodes
4122 //=======================================================================
4124 void SMESH_MeshEditor_i::
4125 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4126 CORBA::Double Tolerance,
4127 SMESH::array_of_long_array_out GroupsOfNodes,
4128 CORBA::Boolean SeparateCornersAndMedium)
4130 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4131 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4133 GroupsOfNodes = new SMESH::array_of_long_array;
4134 GroupsOfNodes->length( aListOfListOfNodes.size() );
4135 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4136 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4138 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4139 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4140 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4141 aGroup.length( aListOfNodes.size() );
4142 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4143 aGroup[ j ] = (*lIt)->GetID();
4147 //=======================================================================
4148 //function : FindCoincidentNodes
4150 //=======================================================================
4152 void SMESH_MeshEditor_i::
4153 FindCoincidentNodes (CORBA::Double Tolerance,
4154 SMESH::array_of_long_array_out GroupsOfNodes,
4155 CORBA::Boolean SeparateCornersAndMedium)
4156 throw (SALOME::SALOME_Exception)
4161 TIDSortedNodeSet nodes; // no input nodes
4162 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4164 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4165 << Tolerance << ", "
4166 << SeparateCornersAndMedium << " )";
4168 SMESH_CATCH( SMESH::throwCorbaException );
4171 //=======================================================================
4172 //function : FindCoincidentNodesOnPart
4174 //=======================================================================
4176 void SMESH_MeshEditor_i::
4177 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4178 CORBA::Double Tolerance,
4179 SMESH::array_of_long_array_out GroupsOfNodes,
4180 CORBA::Boolean SeparateCornersAndMedium)
4181 throw (SALOME::SALOME_Exception)
4186 TIDSortedNodeSet nodes;
4187 prepareIdSource( theObject );
4188 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4190 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4192 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4194 << Tolerance << ", "
4195 << SeparateCornersAndMedium << " )";
4197 SMESH_CATCH( SMESH::throwCorbaException );
4200 //================================================================================
4202 * \brief Finds nodes coincident with Tolerance within Object excluding nodes within
4203 * ExceptSubMeshOrGroups
4205 //================================================================================
4207 void SMESH_MeshEditor_i::
4208 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4209 CORBA::Double theTolerance,
4210 SMESH::array_of_long_array_out theGroupsOfNodes,
4211 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4212 CORBA::Boolean theSeparateCornersAndMedium)
4213 throw (SALOME::SALOME_Exception)
4218 TIDSortedNodeSet nodes;
4219 prepareIdSource( theObject );
4220 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4222 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4224 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4226 while ( nodeIt->more() )
4227 nodes.erase( cast2Node( nodeIt->next() ));
4229 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4231 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4233 << theTolerance << ", "
4234 << theExceptSubMeshOrGroups << ", "
4235 << theSeparateCornersAndMedium << " )";
4237 SMESH_CATCH( SMESH::throwCorbaException );
4240 //=======================================================================
4241 //function : MergeNodes
4243 //=======================================================================
4245 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4246 const SMESH::ListOfIDSources& NodesToKeep,
4247 CORBA::Boolean AvoidMakingHoles)
4248 throw (SALOME::SALOME_Exception)
4253 SMESHDS_Mesh* aMesh = getMeshDS();
4255 TPythonDump aTPythonDump;
4256 aTPythonDump << this << ".MergeNodes([";
4258 TIDSortedNodeSet setOfNodesToKeep;
4259 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4261 prepareIdSource( NodesToKeep[i] );
4262 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ))
4263 while ( nodeIt->more() )
4264 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4267 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4268 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4270 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4271 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4272 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4273 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4275 CORBA::Long index = aNodeGroup[ j ];
4276 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4278 if ( setOfNodesToKeep.count( node ))
4279 aListOfNodes.push_front( node );
4281 aListOfNodes.push_back( node );
4284 if ( aListOfNodes.size() < 2 )
4285 aListOfListOfNodes.pop_back();
4287 if ( i > 0 ) aTPythonDump << ", ";
4288 aTPythonDump << aNodeGroup;
4291 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4293 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4295 declareMeshModified( /*isReComputeSafe=*/false );
4297 SMESH_CATCH( SMESH::throwCorbaException );
4300 //=======================================================================
4301 //function : FindEqualElements
4303 //=======================================================================
4305 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4306 SMESH::array_of_long_array_out GroupsOfElementsID)
4307 throw (SALOME::SALOME_Exception)
4312 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4313 if ( !( !group->_is_nil() && group->GetType() == SMESH::NODE ))
4315 TIDSortedElemSet elems;
4316 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4318 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4319 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4321 GroupsOfElementsID = new SMESH::array_of_long_array;
4322 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4324 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4325 aListOfListOfElementsID.begin();
4326 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4328 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4329 list<int>& listOfIDs = *arraysIt;
4330 aGroup.length( listOfIDs.size() );
4331 list<int>::iterator idIt = listOfIDs.begin();
4332 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4333 aGroup[ k ] = *idIt;
4336 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4340 SMESH_CATCH( SMESH::throwCorbaException );
4343 //=======================================================================
4344 //function : MergeElements
4346 //=======================================================================
4348 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4349 throw (SALOME::SALOME_Exception)
4354 TPythonDump aTPythonDump;
4355 aTPythonDump << this << ".MergeElements( [";
4357 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4359 for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) {
4360 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4361 aListOfListOfElementsID.push_back( list< int >() );
4362 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4363 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) {
4364 CORBA::Long id = anElemsIDGroup[ j ];
4365 aListOfElemsID.push_back( id );
4367 if ( aListOfElemsID.size() < 2 )
4368 aListOfListOfElementsID.pop_back();
4369 if ( i > 0 ) aTPythonDump << ", ";
4370 aTPythonDump << anElemsIDGroup;
4373 getEditor().MergeElements(aListOfListOfElementsID);
4375 declareMeshModified( /*isReComputeSafe=*/true );
4377 aTPythonDump << "] )";
4379 SMESH_CATCH( SMESH::throwCorbaException );
4382 //=======================================================================
4383 //function : MergeEqualElements
4385 //=======================================================================
4387 void SMESH_MeshEditor_i::MergeEqualElements()
4388 throw (SALOME::SALOME_Exception)
4393 getEditor().MergeEqualElements();
4395 declareMeshModified( /*isReComputeSafe=*/true );
4397 TPythonDump() << this << ".MergeEqualElements()";
4399 SMESH_CATCH( SMESH::throwCorbaException );
4402 //=============================================================================
4404 * Move the node to a given point
4406 //=============================================================================
4408 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4412 throw (SALOME::SALOME_Exception)
4415 initData(/*deleteSearchers=*/false);
4417 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4421 if ( theNodeSearcher )
4422 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4424 if ( myIsPreviewMode ) // make preview data
4426 // in a preview mesh, make edges linked to a node
4427 TPreviewMesh& tmpMesh = *getPreviewMesh();
4428 TIDSortedElemSet linkedNodes;
4429 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4430 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4431 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4432 for ( ; nIt != linkedNodes.end(); ++nIt )
4434 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4435 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4439 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4440 // fill preview data
4442 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4443 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4445 getMeshDS()->MoveNode(node, x, y, z);
4447 if ( !myIsPreviewMode )
4449 // Update Python script
4450 TPythonDump() << "isDone = " << this << ".MoveNode( "
4451 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4452 declareMeshModified( /*isReComputeSafe=*/false );
4455 SMESH_CATCH( SMESH::throwCorbaException );
4460 //================================================================================
4462 * \brief Return ID of node closest to a given point
4464 //================================================================================
4466 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4469 throw (SALOME::SALOME_Exception)
4472 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4474 if ( !theNodeSearcher ) {
4475 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4478 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4479 return node->GetID();
4481 SMESH_CATCH( SMESH::throwCorbaException );
4485 //================================================================================
4487 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4488 * move the node closest to the point to point's location and return ID of the node
4490 //================================================================================
4492 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4495 CORBA::Long theNodeID)
4496 throw (SALOME::SALOME_Exception)
4499 // We keep theNodeSearcher until any mesh modification:
4500 // 1) initData() deletes theNodeSearcher at any edition,
4501 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4503 initData(/*deleteSearchers=*/false);
4505 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4507 int nodeID = theNodeID;
4508 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4509 if ( !node ) // preview moving node
4511 if ( !theNodeSearcher ) {
4512 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4515 node = theNodeSearcher->FindClosestTo( p );
4518 nodeID = node->GetID();
4519 if ( myIsPreviewMode ) // make preview data
4521 // in a preview mesh, make edges linked to a node
4522 TPreviewMesh tmpMesh = *getPreviewMesh();
4523 TIDSortedElemSet linkedNodes;
4524 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4525 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4526 for ( ; nIt != linkedNodes.end(); ++nIt )
4528 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4529 tmpMesh.Copy( &edge );
4532 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4534 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4535 // fill preview data
4537 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4539 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4543 getMeshDS()->MoveNode(node, x, y, z);
4547 if ( !myIsPreviewMode )
4549 TPythonDump() << "nodeID = " << this
4550 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4551 << ", " << nodeID << " )";
4553 declareMeshModified( /*isReComputeSafe=*/false );
4558 SMESH_CATCH( SMESH::throwCorbaException );
4562 //=======================================================================
4564 * Return elements of given type where the given point is IN or ON.
4566 * 'ALL' type means elements of any type excluding nodes
4568 //=======================================================================
4570 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4573 SMESH::ElementType type)
4574 throw (SALOME::SALOME_Exception)
4577 SMESH::long_array_var res = new SMESH::long_array;
4578 vector< const SMDS_MeshElement* > foundElems;
4580 theSearchersDeleter.Set( myMesh );
4581 if ( !theElementSearcher ) {
4582 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4584 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4585 SMDSAbs_ElementType( type ),
4587 res->length( foundElems.size() );
4588 for ( size_t i = 0; i < foundElems.size(); ++i )
4589 res[i] = foundElems[i]->GetID();
4593 SMESH_CATCH( SMESH::throwCorbaException );
4597 //=======================================================================
4598 //function : FindAmongElementsByPoint
4599 //purpose : Searching among the given elements, return elements of given type
4600 // where the given point is IN or ON.
4601 // 'ALL' type means elements of any type excluding nodes
4602 //=======================================================================
4605 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4609 SMESH::ElementType type)
4610 throw (SALOME::SALOME_Exception)
4613 SMESH::long_array_var res = new SMESH::long_array;
4615 prepareIdSource( elementIDs );
4616 if ( type != SMESH::NODE )
4618 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4619 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4620 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4621 type != types[0] ) // but search of elements of dim > 0
4625 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4626 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4627 if ( mesh_i != myMesh_i )
4629 SMESH::SMESH_MeshEditor_var editor=
4630 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4631 return editor->FindAmongElementsByPoint( elementIDs, x,y,z, type );
4634 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4635 return FindElementsByPoint( x,y,z, type );
4637 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4639 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4640 if ( !theElementSearcher )
4642 // create a searcher from elementIDs
4643 SMDS_ElemIteratorPtr elemIt;
4644 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( elementIDs ))
4646 //prepareIdSource( elementIDs );
4647 elemIt = myMesh_i->GetElements( elementIDs, type );
4651 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4654 vector< const SMDS_MeshElement* > foundElems;
4656 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4657 SMDSAbs_ElementType( type ),
4659 res->length( foundElems.size() );
4660 for ( size_t i = 0; i < foundElems.size(); ++i )
4661 res[i] = foundElems[i]->GetID();
4665 SMESH_CATCH( SMESH::throwCorbaException );
4669 //=======================================================================
4670 //function : ProjectPoint
4671 //purpose : Project a point to a mesh object.
4672 // Return ID of an element of given type where the given point is projected
4673 // and coordinates of the projection point.
4674 // In the case if nothing found, return -1 and []
4675 //=======================================================================
4677 CORBA::Long SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
4680 SMESH::ElementType type,
4681 SMESH::SMESH_IDSource_ptr meshObject,
4682 SMESH::double_array_out projecton)
4683 throw (SALOME::SALOME_Exception)
4685 if ( CORBA::is_nil( meshObject ))
4686 THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
4690 SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
4691 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4692 if ( mesh_i != myMesh_i )
4694 SMESH::SMESH_MeshEditor_var editor=
4695 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4696 return editor->ProjectPoint( x,y,z, type, meshObject, projecton );
4700 theSearchersDeleter.Set( myMesh, getPartIOR( meshObject, type ));
4701 if ( !theElementSearcher )
4703 // create a searcher from meshObject
4705 SMDS_ElemIteratorPtr elemIt;
4706 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
4708 prepareIdSource( meshObject );
4709 elemIt = myMesh_i->GetElements( meshObject, type );
4713 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4716 const SMDS_MeshElement* elem = 0;
4717 gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
4718 SMDSAbs_ElementType( type ),
4721 projecton = new SMESH::double_array();
4722 if ( elem && !elem->IsNull() )
4724 projecton->length( 3 );
4725 projecton[0] = pProj.X();
4726 projecton[1] = pProj.Y();
4727 projecton[2] = pProj.Z();
4728 return elem->GetID();
4731 SMESH_CATCH( SMESH::throwCorbaException );
4735 //=======================================================================
4736 //function : GetPointState
4737 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4738 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4739 //=======================================================================
4741 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4744 throw (SALOME::SALOME_Exception)
4747 theSearchersDeleter.Set( myMesh );
4748 if ( !theElementSearcher ) {
4749 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4751 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4753 SMESH_CATCH( SMESH::throwCorbaException );
4757 //=======================================================================
4758 //function : IsManifold
4759 //purpose : Check if a 2D mesh is manifold
4760 //=======================================================================
4762 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4763 throw (SALOME::SALOME_Exception)
4765 bool isManifold = true;
4768 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4769 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4771 /*closedOnly=*/true,
4773 SMESH_CATCH( SMESH::throwCorbaException );
4778 //=======================================================================
4779 //function : IsCoherentOrientation2D
4780 //purpose : Check if orientation of 2D elements is coherent
4781 //=======================================================================
4783 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4784 throw (SALOME::SALOME_Exception)
4786 bool isGoodOri = true;
4789 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4790 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4792 /*closedOnly=*/true,
4795 SMESH_CATCH( SMESH::throwCorbaException );
4800 //=======================================================================
4801 //function : Get1DBranches
4802 //purpose : Partition given 1D elements into groups of contiguous edges.
4803 // A node where number of meeting edges != 2 is a group end.
4804 // An optional startNode is used to orient groups it belongs to.
4805 //return : a list of edge groups and a list of corresponding node groups.
4806 // If a group is closed, the first and last nodes of the group are same.
4807 //=======================================================================
4809 SMESH::array_of_long_array*
4810 SMESH_MeshEditor_i::Get1DBranches( SMESH::SMESH_IDSource_ptr theEdges,
4811 CORBA::Long theStartNode,
4812 SMESH::array_of_long_array_out theNodeGroups )
4813 throw (SALOME::SALOME_Exception)
4815 if ( CORBA::is_nil( theEdges ))
4816 THROW_SALOME_CORBA_EXCEPTION("Get1DBranches(): NULL group given", SALOME::BAD_PARAM);
4818 SMESH::array_of_long_array_var edgeGroupArray = new SMESH::array_of_long_array;
4819 theNodeGroups = new SMESH::array_of_long_array;
4823 prepareIdSource( theEdges );
4825 SMESH_MeshAlgos::TElemGroupVector edgeBranches;
4826 SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
4827 SMESH_MeshAlgos::Get1DBranches( SMESH_Mesh_i::GetElements( theEdges, SMESH::EDGE ),
4830 getMeshDS()->FindNode( theStartNode ));
4832 edgeGroupArray->length( edgeBranches.size() );
4833 for ( size_t iG = 0; iG < edgeBranches.size(); ++iG )
4835 edgeGroupArray[ iG ].length( edgeBranches[ iG ].size() );
4836 for ( size_t i = 0; i < edgeBranches[ iG ].size(); ++i )
4837 edgeGroupArray[ iG ][ i ] = edgeBranches[ iG ][ i ]->GetID();
4840 theNodeGroups->length( nodeBranches.size() );
4841 for ( size_t iG = 0; iG < nodeBranches.size(); ++iG )
4843 theNodeGroups[ iG ].length( nodeBranches[ iG ].size() );
4844 for ( size_t i = 0; i < nodeBranches[ iG ].size(); ++i )
4845 theNodeGroups[ iG ][ i ] = nodeBranches[ iG ][ i ]->GetID();
4848 SMESH_CATCH( SMESH::throwCorbaException );
4850 return edgeGroupArray._retn();
4853 //=======================================================================
4854 //function : FindSharpEdges
4855 //purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
4856 //=======================================================================
4858 SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
4859 CORBA::Boolean theAddExisting)
4860 throw (SALOME::SALOME_Exception)
4862 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
4867 std::vector< SMESH_MeshAlgos::Edge > edges =
4868 SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
4870 if ( myIsPreviewMode ) // fill a preview mesh with edges
4872 TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
4873 SMDS_Mesh* meshDS = mesh->GetMeshDS();
4874 for ( size_t i = 0; i < edges.size(); ++i )
4876 SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
4877 SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4878 SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
4879 if ( edges[i]._medium )
4881 xyz1.Set( edges[i]._medium );
4882 SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4883 mesh->GetMeshDS()->AddEdge( n1, n2, nm );
4887 mesh->GetMeshDS()->AddEdge( n1, n2 );
4893 resultEdges->length( edges.size() );
4894 for ( size_t i = 0; i < edges.size(); ++i )
4896 resultEdges[ i ].node1 = edges[i]._node1->GetID();
4897 resultEdges[ i ].node2 = edges[i]._node2->GetID();
4898 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
4901 SMESH_CATCH( SMESH::throwCorbaException );
4902 return resultEdges._retn();
4905 //=======================================================================
4906 //function : FindFreeBorders
4907 //purpose : Returns all or only closed FreeBorder's.
4908 //=======================================================================
4910 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4911 throw (SALOME::SALOME_Exception)
4913 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4916 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4917 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4919 resBorders->length( foundFreeBordes.size() );
4920 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
4922 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
4923 SMESH::FreeBorder& bordOut = resBorders[i];
4924 bordOut.nodeIDs.length( bordNodes.size() );
4925 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
4926 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
4929 SMESH_CATCH( SMESH::throwCorbaException );
4931 return resBorders._retn();
4934 //=======================================================================
4935 //function : FillHole
4936 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
4937 //=======================================================================
4939 SMESH::SMESH_Group_ptr
4940 SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole,
4941 const char* theGroupName)
4942 throw (SALOME::SALOME_Exception)
4946 if ( theHole.nodeIDs.length() < 4 )
4947 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
4948 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
4949 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
4950 "First and last nodes must be same", SALOME::BAD_PARAM);
4952 SMESH_MeshAlgos::TFreeBorder bordNodes;
4953 bordNodes.resize( theHole.nodeIDs.length() );
4954 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
4956 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
4957 if ( !bordNodes[ iN ] )
4958 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
4959 << " does not exist", SALOME::BAD_PARAM);
4964 // prepare a preview mesh
4965 MeshEditor_I::TPreviewMesh* previewMesh = 0;
4966 SMDS_Mesh* meshDS = getMeshDS();
4967 if ( myIsPreviewMode )
4969 // copy faces sharing nodes of theHole
4970 TIDSortedElemSet holeFaces;
4971 previewMesh = getPreviewMesh( SMDSAbs_Face );
4972 for ( size_t i = 0; i < bordNodes.size(); ++i )
4974 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
4975 while ( fIt->more() )
4977 const SMDS_MeshElement* face = fIt->next();
4978 if ( holeFaces.insert( face ).second )
4979 previewMesh->Copy( face );
4981 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
4982 ASSERT( bordNodes[i] );
4984 meshDS = previewMesh->GetMeshDS();
4988 std::vector<const SMDS_MeshElement*> newFaces;
4989 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
4991 if ( myIsPreviewMode )
4994 previewMesh->Clear();
4995 for ( size_t i = 0; i < newFaces.size(); ++i )
4996 previewMesh->Copy( newFaces[i] );
5000 // return new faces via a group
5001 SMESH::SMESH_Group_var group;
5002 if ( theGroupName && theGroupName[0] && !newFaces.empty() )
5004 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5005 for ( CORBA::ULong i = 0; i < groups->length(); ++i )
5007 SMESH::SMESH_GroupBase_var g = groups[ i ];
5008 if ( g->GetType() != SMESH::FACE ) continue;
5009 SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g );
5010 if ( standalone->_is_nil() ) continue;
5011 CORBA::String_var name = g->GetName();
5012 if ( strcmp( theGroupName, name.in() ) == 0 )
5018 if ( group->_is_nil() )
5019 group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName );
5021 if ( !group->_is_nil() )
5023 SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group );
5024 SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() );
5025 for ( size_t i = 0; i < newFaces.size(); ++i )
5026 grpDS->Add( newFaces[ i ]);
5031 getEditor().ClearLastCreated();
5032 SMESH_SequenceOfElemPtr& aSeq =
5033 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
5034 aSeq.swap( newFaces );
5037 if ( group->_is_nil() ) pyDump << "_group = ";
5038 else pyDump << group << " = ";
5039 pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
5041 return group._retn();
5044 SMESH_CATCH( SMESH::throwCorbaException );
5046 return SMESH::SMESH_Group::_nil();
5049 //=======================================================================
5050 //function : convError
5052 //=======================================================================
5054 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5056 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5060 RETCASE( SEW_BORDER1_NOT_FOUND );
5061 RETCASE( SEW_BORDER2_NOT_FOUND );
5062 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5063 RETCASE( SEW_BAD_SIDE_NODES );
5064 RETCASE( SEW_VOLUMES_TO_SPLIT );
5065 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5066 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5067 RETCASE( SEW_BAD_SIDE1_NODES );
5068 RETCASE( SEW_BAD_SIDE2_NODES );
5069 RETCASE( SEW_INTERNAL_ERROR );
5071 return SMESH::SMESH_MeshEditor::SEW_OK;
5074 //=======================================================================
5076 * Returns groups of FreeBorder's coincident within the given tolerance.
5077 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
5078 * to free borders being compared is used.
5080 //=======================================================================
5082 SMESH::CoincidentFreeBorders*
5083 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
5085 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
5089 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
5090 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
5092 // copy free borders
5093 aCFB->borders.length( cfb._borders.size() );
5094 for ( size_t i = 0; i < cfb._borders.size(); ++i )
5096 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
5097 SMESH::FreeBorder& aBRD = aCFB->borders[i];
5098 aBRD.nodeIDs.length( nodes.size() );
5099 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5100 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
5103 // copy coincident parts
5104 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
5105 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
5107 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
5108 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
5109 aGRP.length( grp.size() );
5110 for ( size_t iP = 0; iP < grp.size(); ++iP )
5112 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
5113 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5114 aPART.border = part._border;
5115 aPART.node1 = part._node1;
5116 aPART.node2 = part._node2;
5117 aPART.nodeLast = part._nodeLast;
5120 SMESH_CATCH( SMESH::doNothing );
5122 TPythonDump() << "CoincidentFreeBorders = "
5123 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
5125 return aCFB._retn();
5128 //=======================================================================
5130 * Sew FreeBorder's of each group
5132 //=======================================================================
5134 CORBA::Short SMESH_MeshEditor_i::
5135 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
5136 CORBA::Boolean createPolygons,
5137 CORBA::Boolean createPolyhedra)
5138 throw (SALOME::SALOME_Exception)
5140 CORBA::Short nbSewed = 0;
5142 SMESH_MeshAlgos::TFreeBorderVec groups;
5143 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
5145 // check the input and collect nodes
5146 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
5148 borderNodes.clear();
5149 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
5150 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
5152 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5153 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
5154 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
5156 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
5158 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
5159 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
5160 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
5161 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
5162 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
5163 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5165 // do not keep these nodes for further sewing as nodes can be removed by the sewing
5166 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
5167 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
5168 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
5170 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
5172 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
5174 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5176 borderNodes.push_back( n1 );
5177 borderNodes.push_back( n2 );
5178 borderNodes.push_back( n3 );
5180 groups.push_back( borderNodes );
5183 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
5184 // to get nodes that replace other nodes during merge we create 0D elements
5185 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
5188 vector< const SMDS_MeshElement* > tmp0Delems;
5189 for ( size_t i = 0; i < groups.size(); ++i )
5191 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5192 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5194 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
5196 tmp0Delems.push_back( it0D->next() );
5198 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
5202 // cout << endl << "INIT" << endl;
5203 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5205 // cout << i << " ";
5206 // if ( i % 3 == 0 ) cout << "^ ";
5207 // tmp0Delems[i]->GetNode(0)->Print( cout );
5212 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
5214 for ( size_t i = 0; i < groups.size(); ++i )
5216 bool isBordToBord = true;
5217 bool groupSewed = false;
5218 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5219 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
5221 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
5222 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
5223 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
5225 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
5226 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
5227 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
5229 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
5232 // TIDSortedElemSet emptySet, avoidSet;
5233 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
5235 // cout << "WRONG 2nd 1" << endl;
5236 // n0->Print( cout );
5237 // n1->Print( cout );
5239 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
5241 // cout << "WRONG 2nd 2" << endl;
5242 // n3->Print( cout );
5243 // n4->Print( cout );
5246 if ( !isBordToBord )
5248 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5249 n2 = 0; // and n2 is not used
5251 // 1st border moves to 2nd
5252 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5254 /*2ndIsFreeBorder=*/ isBordToBord,
5255 createPolygons, createPolyhedra);
5256 groupSewed = ( res == ok );
5258 isBordToBord = false;
5259 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5260 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5262 // cout << t << " ";
5263 // if ( t % 3 == 0 ) cout << "^ ";
5264 // tmp0Delems[t]->GetNode(0)->Print( cout );
5267 i0D += nodes.size();
5268 nbSewed += groupSewed;
5271 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5272 << freeBorders << ", "
5273 << createPolygons << ", "
5274 << createPolyhedra << " )";
5276 SMESH_CATCH( SMESH::doNothing );
5278 declareMeshModified( /*isReComputeSafe=*/false );
5280 // remove tmp 0D elements
5282 set< const SMDS_MeshElement* > removed0D;
5283 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5285 if ( removed0D.insert( tmp0Delems[i] ).second )
5286 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5288 SMESH_CATCH( SMESH::throwCorbaException );
5293 //=======================================================================
5294 //function : SewFreeBorders
5296 //=======================================================================
5298 SMESH::SMESH_MeshEditor::Sew_Error
5299 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5300 CORBA::Long SecondNodeID1,
5301 CORBA::Long LastNodeID1,
5302 CORBA::Long FirstNodeID2,
5303 CORBA::Long SecondNodeID2,
5304 CORBA::Long LastNodeID2,
5305 CORBA::Boolean CreatePolygons,
5306 CORBA::Boolean CreatePolyedrs)
5307 throw (SALOME::SALOME_Exception)
5312 SMESHDS_Mesh* aMesh = getMeshDS();
5314 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5315 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5316 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5317 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5318 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5319 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5321 if (!aBorderFirstNode ||
5322 !aBorderSecondNode||
5324 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5325 if (!aSide2FirstNode ||
5326 !aSide2SecondNode ||
5328 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5330 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5331 << FirstNodeID1 << ", "
5332 << SecondNodeID1 << ", "
5333 << LastNodeID1 << ", "
5334 << FirstNodeID2 << ", "
5335 << SecondNodeID2 << ", "
5336 << LastNodeID2 << ", "
5337 << CreatePolygons<< ", "
5338 << CreatePolyedrs<< " )";
5340 SMESH::SMESH_MeshEditor::Sew_Error error =
5341 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5352 declareMeshModified( /*isReComputeSafe=*/false );
5355 SMESH_CATCH( SMESH::throwCorbaException );
5356 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5360 //=======================================================================
5361 //function : SewConformFreeBorders
5363 //=======================================================================
5365 SMESH::SMESH_MeshEditor::Sew_Error
5366 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5367 CORBA::Long SecondNodeID1,
5368 CORBA::Long LastNodeID1,
5369 CORBA::Long FirstNodeID2,
5370 CORBA::Long SecondNodeID2)
5371 throw (SALOME::SALOME_Exception)
5376 SMESHDS_Mesh* aMesh = getMeshDS();
5378 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5379 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5380 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5381 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5382 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5383 const SMDS_MeshNode* aSide2ThirdNode = 0;
5385 if (!aBorderFirstNode ||
5386 !aBorderSecondNode||
5388 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5389 if (!aSide2FirstNode ||
5391 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5393 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5394 << FirstNodeID1 << ", "
5395 << SecondNodeID1 << ", "
5396 << LastNodeID1 << ", "
5397 << FirstNodeID2 << ", "
5398 << SecondNodeID2 << " )";
5400 SMESH::SMESH_MeshEditor::Sew_Error error =
5401 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5410 declareMeshModified( /*isReComputeSafe=*/false );
5413 SMESH_CATCH( SMESH::throwCorbaException );
5414 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5418 //=======================================================================
5419 //function : SewBorderToSide
5421 //=======================================================================
5423 SMESH::SMESH_MeshEditor::Sew_Error
5424 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5425 CORBA::Long SecondNodeIDOnFreeBorder,
5426 CORBA::Long LastNodeIDOnFreeBorder,
5427 CORBA::Long FirstNodeIDOnSide,
5428 CORBA::Long LastNodeIDOnSide,
5429 CORBA::Boolean CreatePolygons,
5430 CORBA::Boolean CreatePolyedrs)
5431 throw (SALOME::SALOME_Exception)
5436 SMESHDS_Mesh* aMesh = getMeshDS();
5438 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5439 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5440 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5441 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5442 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5443 const SMDS_MeshNode* aSide2ThirdNode = 0;
5445 if (!aBorderFirstNode ||
5446 !aBorderSecondNode||
5448 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5449 if (!aSide2FirstNode ||
5451 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5453 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5454 << FirstNodeIDOnFreeBorder << ", "
5455 << SecondNodeIDOnFreeBorder << ", "
5456 << LastNodeIDOnFreeBorder << ", "
5457 << FirstNodeIDOnSide << ", "
5458 << LastNodeIDOnSide << ", "
5459 << CreatePolygons << ", "
5460 << CreatePolyedrs << ") ";
5462 SMESH::SMESH_MeshEditor::Sew_Error error =
5463 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5473 declareMeshModified( /*isReComputeSafe=*/false );
5476 SMESH_CATCH( SMESH::throwCorbaException );
5477 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5481 //=======================================================================
5482 //function : SewSideElements
5484 //=======================================================================
5486 SMESH::SMESH_MeshEditor::Sew_Error
5487 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5488 const SMESH::long_array& IDsOfSide2Elements,
5489 CORBA::Long NodeID1OfSide1ToMerge,
5490 CORBA::Long NodeID1OfSide2ToMerge,
5491 CORBA::Long NodeID2OfSide1ToMerge,
5492 CORBA::Long NodeID2OfSide2ToMerge)
5493 throw (SALOME::SALOME_Exception)
5498 SMESHDS_Mesh* aMesh = getMeshDS();
5500 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5501 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5502 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5503 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5505 if (!aFirstNode1ToMerge ||
5506 !aFirstNode2ToMerge )
5507 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5508 if (!aSecondNode1ToMerge||
5509 !aSecondNode2ToMerge)
5510 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5512 TIDSortedElemSet aSide1Elems, aSide2Elems;
5513 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5514 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5516 TPythonDump() << "error = " << this << ".SewSideElements( "
5517 << IDsOfSide1Elements << ", "
5518 << IDsOfSide2Elements << ", "
5519 << NodeID1OfSide1ToMerge << ", "
5520 << NodeID1OfSide2ToMerge << ", "
5521 << NodeID2OfSide1ToMerge << ", "
5522 << NodeID2OfSide2ToMerge << ")";
5524 SMESH::SMESH_MeshEditor::Sew_Error error =
5525 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5528 aSecondNode1ToMerge,
5529 aSecondNode2ToMerge));
5531 declareMeshModified( /*isReComputeSafe=*/false );
5534 SMESH_CATCH( SMESH::throwCorbaException );
5535 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5538 //================================================================================
5540 * \brief Set new nodes for given element
5541 * \param ide - element id
5542 * \param newIDs - new node ids
5543 * \retval CORBA::Boolean - true if result is OK
5545 //================================================================================
5547 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5548 const SMESH::long_array& newIDs)
5549 throw (SALOME::SALOME_Exception)
5554 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5555 if(!elem) return false;
5557 int nbn = newIDs.length();
5559 vector<const SMDS_MeshNode*> aNodes(nbn);
5562 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5565 aNodes[nbn1] = aNode;
5568 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5569 << ide << ", " << newIDs << " )";
5571 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5573 declareMeshModified( /*isReComputeSafe=*/ !res );
5577 SMESH_CATCH( SMESH::throwCorbaException );
5581 //=======================================================================
5583 * \brief Makes a part of the mesh quadratic or bi-quadratic
5585 //=======================================================================
5587 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5588 CORBA::Boolean theToBiQuad,
5589 SMESH::SMESH_IDSource_ptr theObject)
5590 throw (SALOME::SALOME_Exception)
5595 TIDSortedElemSet elems;
5597 if ( !( elemsOK = CORBA::is_nil( theObject )))
5599 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5600 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5604 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5605 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5607 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5608 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5610 declareMeshModified( /*isReComputeSafe=*/false );
5613 SMESH_CATCH( SMESH::throwCorbaException );
5616 //=======================================================================
5617 //function : ConvertFromQuadratic
5619 //=======================================================================
5621 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5622 throw (SALOME::SALOME_Exception)
5627 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5628 TPythonDump() << this << ".ConvertFromQuadratic()";
5629 declareMeshModified( /*isReComputeSafe=*/!isDone );
5632 SMESH_CATCH( SMESH::throwCorbaException );
5636 //=======================================================================
5637 //function : ConvertToQuadratic
5639 //=======================================================================
5641 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5642 throw (SALOME::SALOME_Exception)
5644 convertToQuadratic( theForce3d, false );
5645 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5648 //================================================================================
5650 * \brief Makes a part of the mesh quadratic
5652 //================================================================================
5654 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5655 SMESH::SMESH_IDSource_ptr theObject)
5656 throw (SALOME::SALOME_Exception)
5658 convertToQuadratic( theForce3d, false, theObject );
5659 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5662 //================================================================================
5664 * \brief Makes a part of the mesh bi-quadratic
5666 //================================================================================
5668 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5669 SMESH::SMESH_IDSource_ptr theObject)
5670 throw (SALOME::SALOME_Exception)
5672 convertToQuadratic( theForce3d, true, theObject );
5673 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5676 //================================================================================
5678 * \brief Makes a part of the mesh linear
5680 //================================================================================
5682 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5683 throw (SALOME::SALOME_Exception)
5690 TIDSortedElemSet elems;
5691 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5693 if ( elems.empty() )
5695 ConvertFromQuadratic();
5697 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5699 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5703 getEditor().ConvertFromQuadratic(elems);
5706 declareMeshModified( /*isReComputeSafe=*/false );
5708 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5710 SMESH_CATCH( SMESH::throwCorbaException );
5713 //=======================================================================
5714 //function : makeMesh
5715 //purpose : create a named imported mesh
5716 //=======================================================================
5718 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5720 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5721 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5722 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5723 gen->SetName( meshSO, theMeshName, "Mesh" );
5724 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5726 return mesh._retn();
5729 //=======================================================================
5730 //function : dumpGroupsList
5732 //=======================================================================
5734 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5735 const SMESH::ListOfGroups * theGroupList)
5737 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5738 if ( isDumpGroupList )
5739 theDumpPython << theGroupList << " = ";
5742 //================================================================================
5744 \brief Generates the unique group name.
5745 \param thePrefix name prefix
5748 //================================================================================
5750 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5752 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5753 set<std::string> groupNames;
5755 // Get existing group names
5756 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5757 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5758 if (CORBA::is_nil(aGroup))
5761 CORBA::String_var name = aGroup->GetName();
5762 groupNames.insert( name.in() );
5766 std::string name = thePrefix;
5769 while (!groupNames.insert(name).second)
5770 name = SMESH_Comment( thePrefix ) << "_" << index++;
5775 //================================================================================
5777 * \brief Prepare SMESH_IDSource for work
5779 //================================================================================
5781 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5783 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5785 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5786 filter->SetMesh( mesh );
5789 //================================================================================
5791 * \brief Retrieve elements of given type from SMESH_IDSource
5793 //================================================================================
5795 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5796 const SMESHDS_Mesh* theMeshDS,
5797 TIDSortedElemSet& theElemSet,
5798 const SMDSAbs_ElementType theType,
5799 const bool emptyIfIsMesh,
5800 IDSource_Error* error)
5803 if ( error ) *error = IDSource_OK;
5805 if ( CORBA::is_nil( theIDSource ))
5807 if ( error ) *error = IDSource_INVALID;
5810 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5812 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5813 *error = IDSource_EMPTY;
5816 prepareIdSource( theIDSource );
5817 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5818 if ( anIDs->length() == 0 )
5820 if ( error ) *error = IDSource_EMPTY;
5823 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5824 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5826 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5828 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5832 if ( error ) *error = IDSource_INVALID;
5838 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5839 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5841 if ( error ) *error = IDSource_INVALID;
5848 //================================================================================
5850 * \brief Duplicates given elements, i.e. creates new elements based on the
5851 * same nodes as the given ones.
5852 * \param theElements - container of elements to duplicate.
5853 * \param theGroupName - a name of group to contain the generated elements.
5854 * If a group with such a name already exists, the new elements
5855 * are added to the existing group, else a new group is created.
5856 * If \a theGroupName is empty, new elements are not added
5858 * \return a group where the new elements are added. NULL if theGroupName == "".
5861 //================================================================================
5863 SMESH::SMESH_Group_ptr
5864 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5865 const char* theGroupName)
5866 throw (SALOME::SALOME_Exception)
5868 SMESH::SMESH_Group_var newGroup;
5875 TIDSortedElemSet elems;
5876 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5878 getEditor().DoubleElements( elems );
5880 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5883 SMESH::ElementType type =
5884 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5885 // find existing group
5886 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5887 for ( size_t i = 0; i < groups->length(); ++i )
5888 if ( groups[i]->GetType() == type )
5890 CORBA::String_var name = groups[i]->GetName();
5891 if ( strcmp( name, theGroupName ) == 0 ) {
5892 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5896 // create a new group
5897 if ( newGroup->_is_nil() )
5898 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5900 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5902 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5903 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5904 for ( size_t i = 0; i < aSeq.size(); i++ )
5905 groupDS->SMDSGroup().Add( aSeq[i] );
5910 if ( !newGroup->_is_nil() )
5911 pyDump << newGroup << " = ";
5912 pyDump << this << ".DoubleElements( "
5913 << theElements << ", " << "'" << theGroupName <<"')";
5915 SMESH_CATCH( SMESH::throwCorbaException );
5917 return newGroup._retn();
5920 //================================================================================
5922 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5923 \param theNodes - identifiers of nodes to be doubled
5924 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5925 nodes. If list of element identifiers is empty then nodes are doubled but
5926 they not assigned to elements
5927 \return TRUE if operation has been completed successfully, FALSE otherwise
5928 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5930 //================================================================================
5932 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5933 const SMESH::long_array& theModifiedElems )
5934 throw (SALOME::SALOME_Exception)
5939 list< int > aListOfNodes;
5941 for ( i = 0, n = theNodes.length(); i < n; i++ )
5942 aListOfNodes.push_back( theNodes[ i ] );
5944 list< int > aListOfElems;
5945 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5946 aListOfElems.push_back( theModifiedElems[ i ] );
5948 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5950 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5952 // Update Python script
5953 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5957 SMESH_CATCH( SMESH::throwCorbaException );
5961 //================================================================================
5963 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5964 This method provided for convenience works as DoubleNodes() described above.
5965 \param theNodeId - identifier of node to be doubled.
5966 \param theModifiedElems - identifiers of elements to be updated.
5967 \return TRUE if operation has been completed successfully, FALSE otherwise
5968 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5970 //================================================================================
5972 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5973 const SMESH::long_array& theModifiedElems )
5974 throw (SALOME::SALOME_Exception)
5977 SMESH::long_array_var aNodes = new SMESH::long_array;
5978 aNodes->length( 1 );
5979 aNodes[ 0 ] = theNodeId;
5981 TPythonDump pyDump; // suppress dump by the next line
5983 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5985 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5989 SMESH_CATCH( SMESH::throwCorbaException );
5993 //================================================================================
5995 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5996 This method provided for convenience works as DoubleNodes() described above.
5997 \param theNodes - group of nodes to be doubled.
5998 \param theModifiedElems - group of elements to be updated.
5999 \return TRUE if operation has been completed successfully, FALSE otherwise
6000 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
6002 //================================================================================
6004 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
6005 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6006 throw (SALOME::SALOME_Exception)
6009 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6012 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6013 SMESH::long_array_var aModifiedElems;
6014 if ( !CORBA::is_nil( theModifiedElems ) )
6015 aModifiedElems = theModifiedElems->GetListOfID();
6017 aModifiedElems = new SMESH::long_array;
6019 TPythonDump pyDump; // suppress dump by the next line
6021 bool done = DoubleNodes( aNodes, aModifiedElems );
6023 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6027 SMESH_CATCH( SMESH::throwCorbaException );
6031 //================================================================================
6033 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6034 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6035 * \param theNodes - group of nodes to be doubled.
6036 * \param theModifiedElems - group of elements to be updated.
6037 * \return a new group with newly created nodes
6038 * \sa DoubleNodeGroup()
6040 //================================================================================
6042 SMESH::SMESH_Group_ptr
6043 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6044 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6045 throw (SALOME::SALOME_Exception)
6048 SMESH::SMESH_Group_var aNewGroup;
6050 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6051 return aNewGroup._retn();
6054 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6055 SMESH::long_array_var aModifiedElems;
6056 if ( !CORBA::is_nil( theModifiedElems ) )
6057 aModifiedElems = theModifiedElems->GetListOfID();
6059 aModifiedElems = new SMESH::long_array;
6060 aModifiedElems->length( 0 );
6063 TPythonDump pyDump; // suppress dump by the next line
6065 bool aResult = DoubleNodes( aNodes, aModifiedElems );
6068 // Create group with newly created nodes
6069 SMESH::long_array_var anIds = GetLastCreatedNodes();
6070 if (anIds->length() > 0) {
6071 std::string anUnindexedName (theNodes->GetName());
6072 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6073 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6074 aNewGroup->Add(anIds);
6075 pyDump << aNewGroup << " = ";
6079 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6080 << theModifiedElems << " )";
6082 return aNewGroup._retn();
6084 SMESH_CATCH( SMESH::throwCorbaException );
6088 //================================================================================
6090 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6091 This method provided for convenience works as DoubleNodes() described above.
6092 \param theNodes - list of groups of nodes to be doubled
6093 \param theModifiedElems - list of groups of elements to be updated.
6094 \return TRUE if operation has been completed successfully, FALSE otherwise
6095 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6097 //================================================================================
6099 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6100 const SMESH::ListOfGroups& theModifiedElems )
6101 throw (SALOME::SALOME_Exception)
6106 std::list< int > aNodes;
6108 for ( i = 0, n = theNodes.length(); i < n; i++ )
6110 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6111 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6113 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6114 for ( j = 0, m = aCurr->length(); j < m; j++ )
6115 aNodes.push_back( aCurr[ j ] );
6119 std::list< int > anElems;
6120 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6122 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6123 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6125 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6126 for ( j = 0, m = aCurr->length(); j < m; j++ )
6127 anElems.push_back( aCurr[ j ] );
6131 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6133 declareMeshModified( /*isReComputeSafe=*/false );
6135 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6139 SMESH_CATCH( SMESH::throwCorbaException );
6143 //================================================================================
6145 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6146 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6147 * \param theNodes - group of nodes to be doubled.
6148 * \param theModifiedElems - group of elements to be updated.
6149 * \return a new group with newly created nodes
6150 * \sa DoubleNodeGroups()
6152 //================================================================================
6154 SMESH::SMESH_Group_ptr
6155 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6156 const SMESH::ListOfGroups& theModifiedElems )
6157 throw (SALOME::SALOME_Exception)
6159 SMESH::SMESH_Group_var aNewGroup;
6161 TPythonDump pyDump; // suppress dump by the next line
6163 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6167 // Create group with newly created nodes
6168 SMESH::long_array_var anIds = GetLastCreatedNodes();
6169 if (anIds->length() > 0) {
6170 std::string anUnindexedName (theNodes[0]->GetName());
6171 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6172 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6173 aNewGroup->Add(anIds);
6174 pyDump << aNewGroup << " = ";
6178 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6179 << theModifiedElems << " )";
6181 return aNewGroup._retn();
6185 //================================================================================
6187 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6188 \param theElems - the list of elements (edges or faces) to be replicated
6189 The nodes for duplication could be found from these elements
6190 \param theNodesNot - list of nodes to NOT replicate
6191 \param theAffectedElems - the list of elements (cells and edges) to which the
6192 replicated nodes should be associated to.
6193 \return TRUE if operation has been completed successfully, FALSE otherwise
6194 \sa DoubleNodeGroup(), DoubleNodeGroups()
6196 //================================================================================
6198 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6199 const SMESH::long_array& theNodesNot,
6200 const SMESH::long_array& theAffectedElems )
6201 throw (SALOME::SALOME_Exception)
6206 SMESHDS_Mesh* aMeshDS = getMeshDS();
6207 TIDSortedElemSet anElems, aNodes, anAffected;
6208 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6209 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6210 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6212 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6214 // Update Python script
6215 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6216 << theNodesNot << ", " << theAffectedElems << " )";
6218 declareMeshModified( /*isReComputeSafe=*/false );
6221 SMESH_CATCH( SMESH::throwCorbaException );
6225 //================================================================================
6227 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6228 \param theElems - the list of elements (edges or faces) to be replicated
6229 The nodes for duplication could be found from these elements
6230 \param theNodesNot - list of nodes to NOT replicate
6231 \param theShape - shape to detect affected elements (element which geometric center
6232 located on or inside shape).
6233 The replicated nodes should be associated to affected elements.
6234 \return TRUE if operation has been completed successfully, FALSE otherwise
6235 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6237 //================================================================================
6239 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6240 const SMESH::long_array& theNodesNot,
6241 GEOM::GEOM_Object_ptr theShape )
6242 throw (SALOME::SALOME_Exception)
6248 SMESHDS_Mesh* aMeshDS = getMeshDS();
6249 TIDSortedElemSet anElems, aNodes;
6250 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6251 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6253 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6254 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6256 // Update Python script
6257 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6258 << theNodesNot << ", " << theShape << " )";
6260 declareMeshModified( /*isReComputeSafe=*/false );
6263 SMESH_CATCH( SMESH::throwCorbaException );
6267 //================================================================================
6269 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6270 \param theElems - group of of elements (edges or faces) to be replicated
6271 \param theNodesNot - group of nodes not to replicated
6272 \param theAffectedElems - group of elements to which the replicated nodes
6273 should be associated to.
6274 \return TRUE if operation has been completed successfully, FALSE otherwise
6275 \sa DoubleNodes(), DoubleNodeGroups()
6277 //================================================================================
6280 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6281 SMESH::SMESH_GroupBase_ptr theNodesNot,
6282 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6283 throw (SALOME::SALOME_Exception)
6286 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6292 SMESHDS_Mesh* aMeshDS = getMeshDS();
6293 TIDSortedElemSet anElems, aNodes, anAffected;
6294 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6295 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6296 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6298 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6300 // Update Python script
6301 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6302 << theNodesNot << ", " << theAffectedElems << " )";
6304 declareMeshModified( /*isReComputeSafe=*/false );
6307 SMESH_CATCH( SMESH::throwCorbaException );
6311 //================================================================================
6313 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6314 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6315 * \param theElems - group of of elements (edges or faces) to be replicated
6316 * \param theNodesNot - group of nodes not to replicated
6317 * \param theAffectedElems - group of elements to which the replicated nodes
6318 * should be associated to.
6319 * \return a new group with newly created elements
6320 * \sa DoubleNodeElemGroup()
6322 //================================================================================
6324 SMESH::SMESH_Group_ptr
6325 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6326 SMESH::SMESH_GroupBase_ptr theNodesNot,
6327 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6328 throw (SALOME::SALOME_Exception)
6331 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6335 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6336 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6338 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6340 << theNodesNot << ", "
6341 << theAffectedElems << " )";
6343 return elemGroup._retn();
6346 //================================================================================
6348 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6349 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6350 * \param theElems - group of of elements (edges or faces) to be replicated
6351 * \param theNodesNot - group of nodes not to replicated
6352 * \param theAffectedElems - group of elements to which the replicated nodes
6353 * should be associated to.
6354 * \return a new group with newly created elements
6355 * \sa DoubleNodeElemGroup()
6357 //================================================================================
6359 SMESH::ListOfGroups*
6360 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6361 SMESH::SMESH_GroupBase_ptr theNodesNot,
6362 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6363 CORBA::Boolean theElemGroupNeeded,
6364 CORBA::Boolean theNodeGroupNeeded)
6365 throw (SALOME::SALOME_Exception)
6368 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6369 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6370 aTwoGroups->length( 2 );
6372 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6373 return aTwoGroups._retn();
6378 SMESHDS_Mesh* aMeshDS = getMeshDS();
6379 TIDSortedElemSet anElems, aNodes, anAffected;
6380 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6381 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6382 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6385 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6387 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6393 // Create group with newly created elements
6394 CORBA::String_var elemGroupName = theElems->GetName();
6395 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6396 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6398 SMESH::long_array_var anIds = GetLastCreatedElems();
6399 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6400 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6401 aNewElemGroup->Add(anIds);
6403 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6405 SMESH::long_array_var anIds = GetLastCreatedNodes();
6406 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6407 aNewNodeGroup->Add(anIds);
6411 // Update Python script
6414 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6415 else pyDump << aNewElemGroup << ", ";
6416 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6417 else pyDump << aNewNodeGroup << " ] = ";
6419 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6420 << theNodesNot << ", "
6421 << theAffectedElems << ", "
6422 << theElemGroupNeeded << ", "
6423 << theNodeGroupNeeded <<" )";
6425 aTwoGroups[0] = aNewElemGroup._retn();
6426 aTwoGroups[1] = aNewNodeGroup._retn();
6427 return aTwoGroups._retn();
6429 SMESH_CATCH( SMESH::throwCorbaException );
6433 //================================================================================
6435 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6436 \param theElems - group of of elements (edges or faces) to be replicated
6437 \param theNodesNot - group of nodes not to replicated
6438 \param theShape - shape to detect affected elements (element which geometric center
6439 located on or inside shape).
6440 The replicated nodes should be associated to affected elements.
6441 \return TRUE if operation has been completed successfully, FALSE otherwise
6442 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6444 //================================================================================
6447 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6448 SMESH::SMESH_GroupBase_ptr theNodesNot,
6449 GEOM::GEOM_Object_ptr theShape )
6450 throw (SALOME::SALOME_Exception)
6453 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6459 SMESHDS_Mesh* aMeshDS = getMeshDS();
6460 TIDSortedElemSet anElems, aNodes, anAffected;
6461 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6462 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6464 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6465 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6468 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6470 // Update Python script
6471 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6472 << theNodesNot << ", " << theShape << " )";
6475 SMESH_CATCH( SMESH::throwCorbaException );
6479 //================================================================================
6481 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6482 * \param [in] theGrpList - groups
6483 * \param [in] theMeshDS - mesh
6484 * \param [out] theElemSet - set of elements
6485 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6487 //================================================================================
6489 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6490 SMESHDS_Mesh* theMeshDS,
6491 TIDSortedElemSet& theElemSet,
6492 const bool theIsNodeGrp)
6494 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6496 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6497 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6498 : aGrp->GetType() != SMESH::NODE ) )
6500 SMESH::long_array_var anIDs = aGrp->GetIDs();
6501 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6506 //================================================================================
6508 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6509 This method provided for convenience works as DoubleNodes() described above.
6510 \param theElems - list of groups of elements (edges or faces) to be replicated
6511 \param theNodesNot - list of groups of nodes not to replicated
6512 \param theAffectedElems - group of elements to which the replicated nodes
6513 should be associated to.
6514 \return TRUE if operation has been completed successfully, FALSE otherwise
6515 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6517 //================================================================================
6520 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6521 const SMESH::ListOfGroups& theNodesNot,
6522 const SMESH::ListOfGroups& theAffectedElems)
6523 throw (SALOME::SALOME_Exception)
6529 SMESHDS_Mesh* aMeshDS = getMeshDS();
6530 TIDSortedElemSet anElems, aNodes, anAffected;
6531 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6532 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6533 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6535 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6537 // Update Python script
6538 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6539 << &theNodesNot << ", " << &theAffectedElems << " )";
6541 declareMeshModified( /*isReComputeSafe=*/false );
6544 SMESH_CATCH( SMESH::throwCorbaException );
6548 //================================================================================
6550 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6551 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6552 \param theElems - list of groups of elements (edges or faces) to be replicated
6553 \param theNodesNot - list of groups of nodes not to replicated
6554 \param theAffectedElems - group of elements to which the replicated nodes
6555 should be associated to.
6556 * \return a new group with newly created elements
6557 * \sa DoubleNodeElemGroups()
6559 //================================================================================
6561 SMESH::SMESH_Group_ptr
6562 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6563 const SMESH::ListOfGroups& theNodesNot,
6564 const SMESH::ListOfGroups& theAffectedElems)
6565 throw (SALOME::SALOME_Exception)
6568 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6572 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6573 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6575 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6577 << theNodesNot << ", "
6578 << theAffectedElems << " )";
6580 return elemGroup._retn();
6583 //================================================================================
6585 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6586 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6587 \param theElems - list of groups of elements (edges or faces) to be replicated
6588 \param theNodesNot - list of groups of nodes not to replicated
6589 \param theAffectedElems - group of elements to which the replicated nodes
6590 should be associated to.
6591 * \return a new group with newly created elements
6592 * \sa DoubleNodeElemGroups()
6594 //================================================================================
6596 SMESH::ListOfGroups*
6597 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6598 const SMESH::ListOfGroups& theNodesNot,
6599 const SMESH::ListOfGroups& theAffectedElems,
6600 CORBA::Boolean theElemGroupNeeded,
6601 CORBA::Boolean theNodeGroupNeeded)
6602 throw (SALOME::SALOME_Exception)
6605 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6606 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6607 aTwoGroups->length( 2 );
6612 SMESHDS_Mesh* aMeshDS = getMeshDS();
6613 TIDSortedElemSet anElems, aNodes, anAffected;
6614 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6615 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6616 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6618 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6620 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6625 // Create group with newly created elements
6626 CORBA::String_var elemGroupName = theElems[0]->GetName();
6627 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6628 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6630 SMESH::long_array_var anIds = GetLastCreatedElems();
6631 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6632 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6633 aNewElemGroup->Add(anIds);
6635 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6637 SMESH::long_array_var anIds = GetLastCreatedNodes();
6638 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6639 aNewNodeGroup->Add(anIds);
6643 // Update Python script
6646 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6647 else pyDump << aNewElemGroup << ", ";
6648 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6649 else pyDump << aNewNodeGroup << " ] = ";
6651 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6652 << &theNodesNot << ", "
6653 << &theAffectedElems << ", "
6654 << theElemGroupNeeded << ", "
6655 << theNodeGroupNeeded << " )";
6657 aTwoGroups[0] = aNewElemGroup._retn();
6658 aTwoGroups[1] = aNewNodeGroup._retn();
6659 return aTwoGroups._retn();
6661 SMESH_CATCH( SMESH::throwCorbaException );
6665 //================================================================================
6667 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6668 This method provided for convenience works as DoubleNodes() described above.
6669 \param theElems - list of groups of elements (edges or faces) to be replicated
6670 \param theNodesNot - list of groups of nodes not to replicated
6671 \param theShape - shape to detect affected elements (element which geometric center
6672 located on or inside shape).
6673 The replicated nodes should be associated to affected elements.
6674 \return TRUE if operation has been completed successfully, FALSE otherwise
6675 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6677 //================================================================================
6680 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6681 const SMESH::ListOfGroups& theNodesNot,
6682 GEOM::GEOM_Object_ptr theShape )
6683 throw (SALOME::SALOME_Exception)
6689 SMESHDS_Mesh* aMeshDS = getMeshDS();
6690 TIDSortedElemSet anElems, aNodes;
6691 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6692 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6694 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6695 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6697 // Update Python script
6698 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6699 << &theNodesNot << ", " << theShape << " )";
6701 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6704 SMESH_CATCH( SMESH::throwCorbaException );
6708 //================================================================================
6710 \brief Identify the elements that will be affected by node duplication (actual
6711 duplication is not performed.
6712 This method is the first step of DoubleNodeElemGroupsInRegion.
6713 \param theElems - list of groups of elements (edges or faces) to be replicated
6714 \param theNodesNot - list of groups of nodes not to replicated
6715 \param theShape - shape to detect affected elements (element which geometric center
6716 located on or inside shape).
6717 The replicated nodes should be associated to affected elements.
6718 \return groups of affected elements
6719 \sa DoubleNodeElemGroupsInRegion()
6721 //================================================================================
6722 SMESH::ListOfGroups*
6723 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6724 const SMESH::ListOfGroups& theNodesNot,
6725 GEOM::GEOM_Object_ptr theShape )
6726 throw (SALOME::SALOME_Exception)
6729 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6730 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6731 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6732 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6736 ::SMESH_MeshEditor aMeshEditor(myMesh);
6738 SMESHDS_Mesh* aMeshDS = getMeshDS();
6739 TIDSortedElemSet anElems, aNodes;
6740 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6741 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6742 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6744 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6745 TIDSortedElemSet anAffected;
6746 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6748 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6751 if ( aResult && anAffected.size() > 0 )
6753 SMESH::long_array_var volumeIds = new SMESH::long_array;
6754 SMESH::long_array_var faceIds = new SMESH::long_array;
6755 SMESH::long_array_var edgeIds = new SMESH::long_array;
6756 volumeIds->length( anAffected.size() );
6757 faceIds ->length( anAffected.size() );
6758 edgeIds ->length( anAffected.size() );
6763 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6764 for (; eIt != anAffected.end(); ++eIt)
6766 const SMDS_MeshElement* anElem = *eIt;
6767 int elemId = anElem->GetID();
6768 switch ( anElem->GetType() ) {
6769 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6770 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6771 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6775 volumeIds->length(ivol);
6776 faceIds->length(iface);
6777 edgeIds->length(iedge);
6782 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6783 GenerateGroupName("affectedVolumes").c_str());
6784 aNewVolumeGroup->Add(volumeIds);
6785 aListOfGroups->length( nbGroups+1 );
6786 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6790 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6791 GenerateGroupName("affectedFaces").c_str());
6792 aNewFaceGroup->Add(faceIds);
6793 aListOfGroups->length( nbGroups+1 );
6794 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6798 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6799 GenerateGroupName("affectedEdges").c_str());
6800 aNewEdgeGroup->Add(edgeIds);
6801 aListOfGroups->length( nbGroups+1 );
6802 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6806 // Update Python script
6808 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6809 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6811 return aListOfGroups._retn();
6813 SMESH_CATCH( SMESH::throwCorbaException );
6817 //================================================================================
6819 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6820 The created 2D mesh elements based on nodes of free faces of boundary volumes
6821 \return TRUE if operation has been completed successfully, FALSE otherwise
6823 //================================================================================
6825 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6826 throw (SALOME::SALOME_Exception)
6831 bool aResult = getEditor().Make2DMeshFrom3D();
6833 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6835 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6838 SMESH_CATCH( SMESH::throwCorbaException );
6842 //================================================================================
6844 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6845 * The list of groups must contain at least two groups. The groups have to be disjoint:
6846 * no common element into two different groups.
6847 * The nodes of the internal faces at the boundaries of the groups are doubled.
6848 * Optionally, the internal faces are replaced by flat elements.
6849 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6850 * The flat elements are stored in groups of volumes.
6851 * These groups are named according to the position of the group in the list:
6852 * 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.
6853 * 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.
6854 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6855 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6856 * \param theDomains - list of groups of volumes
6857 * \param createJointElems - if TRUE, create the elements
6858 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6859 * the boundary between \a theDomains and the rest mesh
6860 * \return TRUE if operation has been completed successfully, FALSE otherwise
6862 //================================================================================
6865 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6866 CORBA::Boolean createJointElems,
6867 CORBA::Boolean onAllBoundaries )
6868 throw (SALOME::SALOME_Exception)
6875 SMESHDS_Mesh* aMeshDS = getMeshDS();
6877 // MESSAGE("theDomains.length = "<<theDomains.length());
6878 if ( theDomains.length() <= 1 && !onAllBoundaries )
6879 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6881 vector<TIDSortedElemSet> domains;
6882 domains.resize( theDomains.length() );
6884 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6886 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6887 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6889 // if ( aGrp->GetType() != SMESH::VOLUME )
6890 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6891 SMESH::long_array_var anIDs = aGrp->GetIDs();
6892 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6896 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6897 // TODO publish the groups of flat elements in study
6899 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6901 // Update Python script
6902 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6903 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6905 SMESH_CATCH( SMESH::throwCorbaException );
6907 myMesh_i->CreateGroupServants(); // publish created groups if any
6912 //================================================================================
6914 * \brief Double nodes on some external faces and create flat elements.
6915 * Flat elements are mainly used by some types of mechanic calculations.
6917 * Each group of the list must be constituted of faces.
6918 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6919 * @param theGroupsOfFaces - list of groups of faces
6920 * @return TRUE if operation has been completed successfully, FALSE otherwise
6922 //================================================================================
6925 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6926 throw (SALOME::SALOME_Exception)
6931 SMESHDS_Mesh* aMeshDS = getMeshDS();
6933 vector<TIDSortedElemSet> faceGroups;
6936 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6938 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6939 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6941 TIDSortedElemSet faceGroup;
6943 faceGroups.push_back(faceGroup);
6944 SMESH::long_array_var anIDs = aGrp->GetIDs();
6945 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6949 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6950 // TODO publish the groups of flat elements in study
6952 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6954 // Update Python script
6955 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6958 SMESH_CATCH( SMESH::throwCorbaException );
6962 //================================================================================
6964 * \brief Identify all the elements around a geom shape, get the faces delimiting
6967 * Build groups of volume to remove, groups of faces to replace on the skin of the
6968 * object, groups of faces to remove inside the object, (idem edges).
6969 * Build ordered list of nodes at the border of each group of faces to replace
6970 * (to be used to build a geom subshape).
6972 //================================================================================
6974 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6975 GEOM::GEOM_Object_ptr theShape,
6976 const char* groupName,
6977 const SMESH::double_array& theNodesCoords,
6978 SMESH::array_of_long_array_out GroupsOfNodes)
6979 throw (SALOME::SALOME_Exception)
6984 std::vector<std::vector<int> > aListOfListOfNodes;
6985 ::SMESH_MeshEditor aMeshEditor( myMesh );
6987 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6988 if ( !theNodeSearcher )
6989 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6991 vector<double> nodesCoords;
6992 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6994 nodesCoords.push_back( theNodesCoords[i] );
6997 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6998 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6999 nodesCoords, aListOfListOfNodes);
7001 GroupsOfNodes = new SMESH::array_of_long_array;
7002 GroupsOfNodes->length( aListOfListOfNodes.size() );
7003 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
7004 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
7006 vector<int>& aListOfNodes = *llIt;
7007 vector<int>::iterator lIt = aListOfNodes.begin();;
7008 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
7009 aGroup.length( aListOfNodes.size() );
7010 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
7011 aGroup[ j ] = (*lIt);
7013 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
7016 << ", '" << groupName << "', "
7017 << theNodesCoords << " )";
7019 SMESH_CATCH( SMESH::throwCorbaException );
7022 // issue 20749 ===================================================================
7024 * \brief Creates missing boundary elements
7025 * \param elements - elements whose boundary is to be checked
7026 * \param dimension - defines type of boundary elements to create
7027 * \param groupName - a name of group to store created boundary elements in,
7028 * "" means not to create the group
7029 * \param meshName - a name of new mesh to store created boundary elements in,
7030 * "" means not to create the new mesh
7031 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
7032 * \param toCopyExistingBondary - if true, not only new but also pre-existing
7033 * boundary elements will be copied into the new mesh
7034 * \param group - returns the create group, if any
7035 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7037 // ================================================================================
7039 SMESH::SMESH_Mesh_ptr
7040 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7041 SMESH::Bnd_Dimension dim,
7042 const char* groupName,
7043 const char* meshName,
7044 CORBA::Boolean toCopyElements,
7045 CORBA::Boolean toCopyExistingBondary,
7046 SMESH::SMESH_Group_out group)
7047 throw (SALOME::SALOME_Exception)
7052 if ( dim > SMESH::BND_1DFROM2D )
7053 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7055 SMESHDS_Mesh* aMeshDS = getMeshDS();
7057 SMESH::SMESH_Mesh_var mesh_var;
7058 SMESH::SMESH_Group_var group_var;
7062 TIDSortedElemSet elements;
7063 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7064 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7068 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7069 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7071 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7073 // group of new boundary elements
7074 SMESH_Group* smesh_group = 0;
7075 if ( strlen(groupName) )
7077 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7078 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7079 smesh_group = group_i->GetSmeshGroup();
7083 getEditor().MakeBoundaryMesh( elements,
7084 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7088 toCopyExistingBondary);
7091 smesh_mesh->GetMeshDS()->Modified();
7094 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7096 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7097 if ( mesh_var->_is_nil() )
7098 pyDump << myMesh_i->_this() << ", ";
7100 pyDump << mesh_var << ", ";
7101 if ( group_var->_is_nil() )
7102 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7104 pyDump << group_var << " = ";
7105 pyDump << this << ".MakeBoundaryMesh( "
7107 << "SMESH." << dimName[int(dim)] << ", "
7108 << "'" << groupName << "', "
7109 << "'" << meshName<< "', "
7110 << toCopyElements << ", "
7111 << toCopyExistingBondary << ")";
7113 group = group_var._retn();
7114 return mesh_var._retn();
7116 SMESH_CATCH( SMESH::throwCorbaException );
7117 return SMESH::SMESH_Mesh::_nil();
7120 //================================================================================
7122 * \brief Creates missing boundary elements
7123 * \param dimension - defines type of boundary elements to create
7124 * \param groupName - a name of group to store all boundary elements in,
7125 * "" means not to create the group
7126 * \param meshName - a name of a new mesh, which is a copy of the initial
7127 * mesh + created boundary elements; "" means not to create the new mesh
7128 * \param toCopyAll - if true, the whole initial mesh will be copied into
7129 * the new mesh else only boundary elements will be copied into the new mesh
7130 * \param groups - optional groups of elements to make boundary around
7131 * \param mesh - returns the mesh where elements were added to
7132 * \param group - returns the created group, if any
7133 * \retval long - number of added boundary elements
7135 //================================================================================
7137 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7138 const char* groupName,
7139 const char* meshName,
7140 CORBA::Boolean toCopyAll,
7141 const SMESH::ListOfIDSources& groups,
7142 SMESH::SMESH_Mesh_out mesh,
7143 SMESH::SMESH_Group_out group)
7144 throw (SALOME::SALOME_Exception)
7149 if ( dim > SMESH::BND_1DFROM2D )
7150 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7152 // separate groups belonging to this and other mesh
7153 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7154 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7155 groupsOfThisMesh ->length( groups.length() );
7156 groupsOfOtherMesh->length( groups.length() );
7157 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7158 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7160 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7161 if ( !m->_is_nil() && myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7162 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7164 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7165 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7166 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7168 groupsOfThisMesh->length( nbGroups );
7169 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7174 if ( nbGroupsOfOtherMesh > 0 )
7176 // process groups belonging to another mesh
7177 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7178 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7179 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7180 groupsOfOtherMesh, mesh, group );
7183 SMESH::SMESH_Mesh_var mesh_var;
7184 SMESH::SMESH_Group_var group_var;
7187 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7188 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7192 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7194 /*toCopyGroups=*/false,
7195 /*toKeepIDs=*/true);
7197 mesh_var = makeMesh(meshName);
7199 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7200 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7203 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7204 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7206 // group of boundary elements
7207 SMESH_Group* smesh_group = 0;
7208 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7209 if ( strlen( groupName ))
7211 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7212 group_var = mesh_i->CreateGroup( groupType, groupName );
7213 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7214 smesh_group = group_i->GetSmeshGroup();
7217 TIDSortedElemSet elements;
7219 if ( groups.length() > 0 )
7221 for ( int i = 0; i < nbGroups; ++i )
7224 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7226 SMESH::Bnd_Dimension bdim =
7227 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7228 nbAdded += getEditor().MakeBoundaryMesh( elements,
7229 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7232 /*toCopyElements=*/false,
7233 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7234 /*toAddExistingBondary=*/true,
7235 /*aroundElements=*/true);
7241 nbAdded += getEditor().MakeBoundaryMesh( elements,
7242 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7245 /*toCopyElements=*/false,
7246 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7247 /*toAddExistingBondary=*/true);
7249 tgtMesh->GetMeshDS()->Modified();
7251 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7253 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7254 pyDump << "nbAdded, ";
7255 if ( mesh_var->_is_nil() )
7256 pyDump << myMesh_i->_this() << ", ";
7258 pyDump << mesh_var << ", ";
7259 if ( group_var->_is_nil() )
7260 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7262 pyDump << group_var << " = ";
7263 pyDump << this << ".MakeBoundaryElements( "
7264 << "SMESH." << dimName[int(dim)] << ", "
7265 << "'" << groupName << "', "
7266 << "'" << meshName<< "', "
7267 << toCopyAll << ", "
7270 mesh = mesh_var._retn();
7271 group = group_var._retn();
7274 SMESH_CATCH( SMESH::throwCorbaException );
7278 //================================================================================
7280 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7281 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7282 * plane passing through pairs of points specified by each PolySegment structure.
7283 * If there are several paths connecting a pair of points, the shortest path is
7284 * selected by the module. Position of the cutting plane is defined by the two
7285 * points and an optional vector lying on the plane specified by a PolySegment.
7286 * By default the vector is defined by Mesh module as following. A middle point
7287 * of the two given points is computed. The middle point is projected to the mesh.
7288 * The vector goes from the middle point to the projection point. In case of planar
7289 * mesh, the vector is normal to the mesh.
7290 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7291 * Return the used vector and position of the middle point.
7292 * \param [in] groupName - optional name of a group where created mesh segments will
7295 //================================================================================
7297 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7298 const char* theGroupName)
7299 throw (SALOME::SALOME_Exception)
7301 if ( theSegments.length() == 0 )
7302 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7303 if ( myMesh->NbFaces() == 0 )
7304 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7307 initData(/*deleteSearchers=*/false);
7309 SMESHDS_Group* groupDS = 0;
7310 SMESHDS_Mesh* meshDS = getMeshDS();
7311 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7313 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7314 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7315 while ( faceIt->more() )
7316 tmpMesh->Copy( faceIt->next() );
7317 meshDS = tmpMesh->GetMeshDS();
7319 else if ( theGroupName[0] ) // find/create a group of segments
7321 SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7322 while ( !groupDS && grpIt->more() )
7324 SMESH_Group* group = grpIt->next();
7325 if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7326 strcmp( group->GetName(), theGroupName ) == 0 )
7328 groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7333 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7335 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7336 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7340 // convert input polySegments
7341 SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() );
7342 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7344 SMESH::PolySegment& segIn = theSegments[ i ];
7345 SMESH_MeshAlgos::PolySegment& segOut = segments[ i ];
7346 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7347 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7348 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7349 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7350 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7353 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7356 segOut.myVector.SetCoord( segIn.vector.PS.x,
7358 segIn.vector.PS.z );
7361 // get a static ElementSearcher
7362 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7363 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7364 if ( !theElementSearcher )
7365 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7368 std::vector<const SMDS_MeshElement*> newEdges;
7369 std::vector<const SMDS_MeshNode*> newNodes;
7370 SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes,
7371 groupDS ? &groupDS->SMDSGroup() : 0,
7372 theElementSearcher );
7374 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ).
7376 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ).
7377 assign( newNodes.begin(), newNodes.end() );
7380 if ( myIsPreviewMode )
7382 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7384 SMESH::PolySegment& segOut = theSegments[ i ];
7385 SMESH_MeshAlgos::PolySegment& segIn = segments[ i ];
7386 segOut.vector.PS.x = segIn.myVector.X();
7387 segOut.vector.PS.y = segIn.myVector.Y();
7388 segOut.vector.PS.z = segIn.myVector.Z();
7393 TPythonDump() << "_segments = []";
7394 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7396 SMESH::PolySegment& segIn = theSegments[ i ];
7397 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7398 << segIn.node1ID1 << ", "
7399 << segIn.node1ID2 << ", "
7400 << segIn.node2ID1 << ", "
7401 << segIn.node2ID2 << ", "
7402 << "smeshBuilder.MakeDirStruct( "
7403 << segIn.vector.PS.x << ", "
7404 << segIn.vector.PS.y << ", "
7405 << segIn.vector.PS.z << ")))";
7407 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7410 SMESH_CATCH( SMESH::throwCorbaException );
7414 //================================================================================
7416 * \brief Create a slot of given width around given 1D elements lying on a triangle mesh.
7417 * The slot is consrtucted by cutting faces by cylindrical surfaces made
7418 * around each segment. Segments are expected to be created by MakePolyLine().
7419 * \return Edges located at the slot boundary
7421 //================================================================================
7423 SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments,
7424 CORBA::Double theWidth)
7425 throw (SALOME::SALOME_Exception)
7427 if ( CORBA::is_nil( theSegments ) ||
7428 theSegments->GetType() != SMESH::EDGE )
7429 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7430 if ( myMesh->NbFaces() == 0 )
7431 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7433 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
7436 initData(/*deleteSearchers=*/false);
7438 SMESHDS_Mesh* meshDS = getMeshDS();
7440 std::vector< SMESH_MeshAlgos::Edge > edges =
7441 SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ),
7444 resultEdges->length( edges.size() );
7445 for ( size_t i = 0; i < edges.size(); ++i )
7447 resultEdges[ i ].node1 = edges[i]._node1->GetID();
7448 resultEdges[ i ].node2 = edges[i]._node2->GetID();
7449 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
7453 SMESH_CATCH( SMESH::throwCorbaException );
7455 TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed
7457 return resultEdges._retn();