1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
46 #include "SMDS_SetIterator.hxx"
47 #include "SMDS_VolumeTool.hxx"
48 #include "SMESHDS_Group.hxx"
49 #include "SMESHDS_GroupOnGeom.hxx"
50 #include "SMESH_ControlsDef.hxx"
51 #include "SMESH_Filter_i.hxx"
52 #include "SMESH_Gen_i.hxx"
53 #include "SMESH_Group.hxx"
54 #include "SMESH_Group_i.hxx"
55 #include "SMESH_MeshAlgos.hxx"
56 #include "SMESH_MeshPartDS.hxx"
57 #include "SMESH_MesherHelper.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMeshEventListener.hxx"
60 #include "SMESH_subMesh_i.hxx"
62 #include <utilities.h>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <Utils_CorbaException.hxx>
65 #include <SALOMEDS_wrap.hxx>
66 #include <SALOME_GenericObj_i.hh>
67 #include <Basics_OCCTVersion.hxx>
69 #include <BRepAdaptor_Surface.hxx>
70 #include <BRep_Tool.hxx>
71 #include <TopExp_Explorer.hxx>
73 #include <TopoDS_Edge.hxx>
74 #include <TopoDS_Face.hxx>
79 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
83 #include <Standard_Failure.hxx>
86 #include <Standard_ErrorHandler.hxx>
92 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
94 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
97 using SMESH::TPythonDump;
100 namespace MeshEditor_I {
102 //=============================================================================
104 * \brief Mesh to apply modifications for preview purposes
106 //=============================================================================
108 struct TPreviewMesh: public SMESH_Mesh
110 SMDSAbs_ElementType myPreviewType; // type to show
112 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
113 _isShapeToMesh = (_id =_studyId = 0);
114 _myMeshDS = new SMESHDS_Mesh( _id, true );
115 myPreviewType = previewElements;
117 //!< Copy a set of elements
118 void Copy(const TIDSortedElemSet & theElements,
119 TIDSortedElemSet& theCopyElements,
120 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
121 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
123 // loop on theIDsOfElements
124 TIDSortedElemSet::const_iterator eIt = theElements.begin();
125 for ( ; eIt != theElements.end(); ++eIt )
127 const SMDS_MeshElement* anElem = *eIt;
128 if ( !anElem ) continue;
129 SMDSAbs_ElementType type = anElem->GetType();
130 if ( type == theAvoidType ||
131 ( theSelectType != SMDSAbs_All && type != theSelectType ))
133 const SMDS_MeshElement* anElemCopy;
134 if ( type == SMDSAbs_Node)
135 anElemCopy = Copy( cast2Node(anElem) );
137 anElemCopy = Copy( anElem );
139 theCopyElements.insert( theCopyElements.end(), anElemCopy );
143 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
145 // copy element nodes
146 int anElemNbNodes = anElem->NbNodes();
147 vector< int > anElemNodesID( anElemNbNodes ) ;
148 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
149 for ( int i = 0; itElemNodes->more(); i++)
151 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
153 anElemNodesID[i] = anElemNode->GetID();
156 // creates a corresponding element on copied nodes
157 ::SMESH_MeshEditor::ElemFeatures elemType;
158 elemType.Init( anElem, /*basicOnly=*/false );
159 elemType.SetID( anElem->GetID() );
160 SMDS_MeshElement* anElemCopy =
161 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
165 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
167 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
168 anElemNode->GetID());
172 GetMeshDS()->ClearMesh();
174 void Remove( SMDSAbs_ElementType type )
176 SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator( type );
177 while ( eIt->more() )
178 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
180 };// struct TPreviewMesh
182 static SMESH_NodeSearcher * theNodeSearcher = 0;
183 static SMESH_ElementSearcher * theElementSearcher = 0;
185 //=============================================================================
187 * \brief Deleter of theNodeSearcher at any compute event occurred
189 //=============================================================================
191 struct TSearchersDeleter : public SMESH_subMeshEventListener
194 string myMeshPartIOR;
196 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
197 "SMESH_MeshEditor_i::TSearchersDeleter"),
199 //!< Delete theNodeSearcher
202 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
203 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
205 typedef map < int, SMESH_subMesh * > TDependsOnMap;
206 //!< The meshod called by submesh: do my main job
207 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
208 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
210 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
212 Unset( sm->GetFather() );
215 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
216 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
218 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
225 myMeshPartIOR = meshPartIOR;
226 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
227 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
228 while ( smIt->more() )
231 sm->SetEventListener( this, 0, sm );
235 //!< delete self from all submeshes
236 void Unset(SMESH_Mesh* mesh)
238 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
239 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
240 while ( smIt->more() )
241 smIt->next()->DeleteEventListener( this );
246 } theSearchersDeleter;
248 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
250 TCollection_AsciiString typeStr;
251 switch ( theMirrorType ) {
252 case SMESH::SMESH_MeshEditor::POINT:
253 typeStr = "SMESH.SMESH_MeshEditor.POINT";
255 case SMESH::SMESH_MeshEditor::AXIS:
256 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
259 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
263 //================================================================================
265 * \brief function for conversion of long_array to TIDSortedElemSet
266 * \param IDs - array of IDs
267 * \param aMesh - mesh
268 * \param aMap - collection to fill
269 * \param aType - element type
271 //================================================================================
273 void arrayToSet(const SMESH::long_array & IDs,
274 const SMESHDS_Mesh* aMesh,
275 TIDSortedElemSet& aMap,
276 const SMDSAbs_ElementType aType = SMDSAbs_All,
277 SMDS_MeshElement::Filter* aFilter = NULL)
279 SMDS_MeshElement::NonNullFilter filter1;
280 SMDS_MeshElement::TypeFilter filter2( aType );
282 if ( aFilter == NULL )
283 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
285 SMDS_MeshElement::Filter & filter = *aFilter;
287 if ( aType == SMDSAbs_Node )
288 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
289 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
291 aMap.insert( aMap.end(), elem );
294 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
295 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
297 aMap.insert( aMap.end(), elem );
301 //================================================================================
303 * \brief Retrieve nodes from SMESH_IDSource
305 //================================================================================
307 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
308 const SMESHDS_Mesh* theMeshDS,
309 TIDSortedNodeSet& theNodeSet)
312 if ( CORBA::is_nil( theObject ) )
314 SMESH::array_of_ElementType_var types = theObject->GetTypes();
315 SMESH::long_array_var aElementsId = theObject->GetIDs();
316 if ( types->length() == 1 && types[0] == SMESH::NODE)
318 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
319 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
320 theNodeSet.insert( theNodeSet.end(), n);
322 else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
324 SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
325 while ( nIt->more( ))
326 if ( const SMDS_MeshElement * elem = nIt->next() )
327 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
331 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
332 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
333 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
337 //================================================================================
339 * \brief Returns elements connected to the given elements
341 //================================================================================
343 void getElementsAround(const TIDSortedElemSet& theElements,
344 const SMESHDS_Mesh* theMeshDS,
345 TIDSortedElemSet& theElementsAround)
347 if ( theElements.empty() ) return;
349 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
350 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
352 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
353 return; // all the elements are in theElements
356 elemType = SMDSAbs_All;
358 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
360 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
361 for ( ; elemIt != theElements.end(); ++elemIt )
363 const SMDS_MeshElement* e = *elemIt;
364 int i = e->NbCornerNodes();
367 const SMDS_MeshNode* n = e->GetNode( i );
368 if ( !isNodeChecked[ n->GetID() ])
370 isNodeChecked[ n->GetID() ] = true;
371 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
372 while ( invIt->more() )
374 const SMDS_MeshElement* elemAround = invIt->next();
375 if ( !theElements.count( elemAround ))
376 theElementsAround.insert( elemAround );
383 //================================================================================
385 * \brief Return a string used to detect change of mesh part on which theElementSearcher
386 * is going to be used
388 //================================================================================
390 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
392 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
393 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
394 // take into account passible group modification
395 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
396 partIOR += SMESH_Comment( type );
400 } // namespace MeshEditor_I
402 using namespace MeshEditor_I;
404 //=============================================================================
408 //=============================================================================
410 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
412 myMesh( &theMesh->GetImpl() ),
414 myIsPreviewMode ( isPreview ),
420 //================================================================================
424 //================================================================================
426 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
428 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
429 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
430 poa->deactivate_object(anObjectId.in());
432 //deleteAuxIDSources();
433 delete myPreviewMesh; myPreviewMesh = 0;
434 delete myPreviewEditor; myPreviewEditor = 0;
437 //================================================================================
439 * \brief Returns the mesh
441 //================================================================================
443 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
445 return myMesh_i->_this();
448 //================================================================================
450 * \brief Clear members
452 //================================================================================
454 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
456 if ( myIsPreviewMode ) {
457 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
460 if ( deleteSearchers )
461 TSearchersDeleter::Delete();
463 getEditor().GetError().reset();
464 getEditor().ClearLastCreated();
467 //================================================================================
469 * \brief Increment mesh modif time and optionally record that the performed
470 * modification may influence further mesh re-compute.
471 * \param [in] isReComputeSafe - true if the modification does not influence
472 * further mesh re-compute
474 //================================================================================
476 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
478 myMesh->GetMeshDS()->Modified();
479 if ( !isReComputeSafe )
480 myMesh->SetIsModified( true );
483 //================================================================================
485 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
486 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
488 //================================================================================
490 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
492 if ( myIsPreviewMode && !myPreviewEditor ) {
493 if ( !myPreviewMesh ) getPreviewMesh();
494 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
496 return myIsPreviewMode ? *myPreviewEditor : myEditor;
499 //================================================================================
501 * \brief Initialize and return myPreviewMesh
502 * \param previewElements - type of elements to show in preview
504 * WARNING: call it once per method!
506 //================================================================================
508 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
510 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
512 delete myPreviewEditor;
514 delete myPreviewMesh;
515 myPreviewMesh = new TPreviewMesh( previewElements );
517 myPreviewMesh->Clear();
518 return myPreviewMesh;
521 //================================================================================
523 * Return data of mesh edition preview
525 //================================================================================
527 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
528 throw (SALOME::SALOME_Exception)
531 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
533 if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
535 list<int> aNodesConnectivity;
536 typedef map<int, int> TNodesMap;
539 SMESHDS_Mesh* aMeshDS;
540 std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
542 aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
543 aMeshDS = aMeshPartDS.get();
546 aMeshDS = getEditor().GetMeshDS();
548 myPreviewData = new SMESH::MeshPreviewStruct();
549 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
552 SMDSAbs_ElementType previewType = SMDSAbs_All;
554 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
555 previewType = aPreviewMesh->myPreviewType;
556 switch ( previewType ) {
557 case SMDSAbs_Edge : break;
558 case SMDSAbs_Face : break;
559 case SMDSAbs_Volume: break;
561 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
565 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
567 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
569 while ( itMeshElems->more() ) {
570 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
571 SMDS_NodeIteratorPtr itElemNodes =
572 (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
573 aMeshElem->interlacedNodesIterator() :
574 aMeshElem->nodeIterator() );
575 while ( itElemNodes->more() ) {
576 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
577 int aNodeID = aMeshNode->GetID();
578 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
579 if ( anIter == nodesMap.end() ) {
580 // filling the nodes coordinates
581 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
582 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
583 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
584 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
587 aNodesConnectivity.push_back(anIter->second);
590 // filling the elements types
591 SMDSAbs_ElementType aType = aMeshElem->GetType();
592 bool isPoly = aMeshElem->IsPoly();
593 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
594 myPreviewData->elementTypes[i].isPoly = isPoly;
595 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
598 myPreviewData->nodesXYZ.length( j );
600 // filling the elements connectivities
601 list<int>::iterator aConnIter = aNodesConnectivity.begin();
602 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
603 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
604 myPreviewData->elementConnectivities[i] = *aConnIter;
606 return myPreviewData._retn();
608 SMESH_CATCH( SMESH::throwCorbaException );
612 //================================================================================
614 * \brief Returns list of it's IDs of created nodes
615 * \retval SMESH::long_array* - list of node ID
617 //================================================================================
619 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
620 throw (SALOME::SALOME_Exception)
623 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
625 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
626 myLastCreatedNodes->length( aSeq.Length() );
627 for (int i = 1; i <= aSeq.Length(); i++)
628 myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID();
630 return myLastCreatedNodes._retn();
631 SMESH_CATCH( SMESH::throwCorbaException );
635 //================================================================================
637 * \brief Returns list of it's IDs of created elements
638 * \retval SMESH::long_array* - list of elements' ID
640 //================================================================================
642 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
643 throw (SALOME::SALOME_Exception)
646 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
648 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
649 myLastCreatedElems->length( aSeq.Length() );
650 for ( int i = 1; i <= aSeq.Length(); i++ )
651 myLastCreatedElems[i-1] = aSeq.Value(i)->GetID();
653 return myLastCreatedElems._retn();
654 SMESH_CATCH( SMESH::throwCorbaException );
658 //=======================================================================
659 //function : ClearLastCreated
660 //purpose : Clears sequences of last created elements and nodes
661 //=======================================================================
663 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
666 getEditor().ClearLastCreated();
667 SMESH_CATCH( SMESH::throwCorbaException );
670 //=======================================================================
672 * Returns description of an error/warning occurred during the last operation
673 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
675 //=======================================================================
677 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
678 throw (SALOME::SALOME_Exception)
681 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
682 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
683 if ( errIn && !errIn->IsOK() )
685 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
686 errOut->comment = errIn->myComment.c_str();
687 errOut->subShapeID = -1;
688 errOut->hasBadMesh = !errIn->myBadElements.empty();
693 errOut->subShapeID = -1;
694 errOut->hasBadMesh = false;
697 return errOut._retn();
698 SMESH_CATCH( SMESH::throwCorbaException );
702 //=======================================================================
703 //function : MakeIDSource
704 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
705 // Call UnRegister() as you fininsh using it!!
706 //=======================================================================
708 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
709 public virtual SALOME::GenericObj_i
711 SMESH::long_array _ids;
712 SMESH::ElementType _type;
713 SMESH::SMESH_Mesh_ptr _mesh;
714 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
715 SMESH::long_array* GetMeshInfo() { return 0; }
716 SMESH::long_array* GetNbElementsByType()
718 SMESH::long_array_var aRes = new SMESH::long_array();
719 aRes->length(SMESH::NB_ELEMENT_TYPES);
720 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
721 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
724 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
725 bool IsMeshInfoCorrect() { return true; }
726 SMESH::array_of_ElementType* GetTypes()
728 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
729 if ( _ids.length() > 0 ) {
733 return types._retn();
735 SALOMEDS::TMPFile* GetVtkUgStream()
737 SALOMEDS::TMPFile_var SeqFile;
738 return SeqFile._retn();
742 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
743 SMESH::ElementType type)
745 _IDSource* idSrc = new _IDSource;
746 idSrc->_mesh = myMesh_i->_this();
749 if ( type == SMESH::ALL && ids.length() > 0 )
750 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
752 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
754 return anIDSourceVar._retn();
757 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
759 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
762 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
765 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
767 nbIds = (int) tmpIdSource->_ids.length();
768 return & tmpIdSource->_ids[0];
774 // void SMESH_MeshEditor_i::deleteAuxIDSources()
776 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
777 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
779 // myAuxIDSources.clear();
782 //=============================================================================
786 //=============================================================================
789 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
790 throw (SALOME::SALOME_Exception)
797 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
798 IdList.push_back( IDsOfElements[i] );
800 // Update Python script
801 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
804 bool ret = getEditor().Remove( IdList, false );
806 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
809 SMESH_CATCH( SMESH::throwCorbaException );
813 //=============================================================================
817 //=============================================================================
819 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
820 throw (SALOME::SALOME_Exception)
826 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
827 IdList.push_back( IDsOfNodes[i] );
829 // Update Python script
830 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
832 bool ret = getEditor().Remove( IdList, true );
834 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
837 SMESH_CATCH( SMESH::throwCorbaException );
841 //=============================================================================
845 //=============================================================================
847 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
848 throw (SALOME::SALOME_Exception)
853 // Update Python script
854 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
856 // Create filter to find all orphan nodes
857 SMESH::Controls::Filter::TIdSequence seq;
858 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
859 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
861 // remove orphan nodes (if there are any)
862 list< int > IdList( seq.begin(), seq.end() );
864 int nbNodesBefore = myMesh->NbNodes();
865 getEditor().Remove( IdList, true );
866 int nbNodesAfter = myMesh->NbNodes();
868 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
869 return nbNodesBefore - nbNodesAfter;
871 SMESH_CATCH( SMESH::throwCorbaException );
875 //=============================================================================
879 //=============================================================================
881 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
882 throw (SALOME::SALOME_Exception)
887 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
889 // Update Python script
890 TPythonDump() << "nodeID = " << this << ".AddNode( "
891 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
893 declareMeshModified( /*isReComputeSafe=*/false );
896 SMESH_CATCH( SMESH::throwCorbaException );
900 //=============================================================================
902 * Create 0D element on the given node.
904 //=============================================================================
906 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode,
907 CORBA::Boolean DuplicateElements)
908 throw (SALOME::SALOME_Exception)
913 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
914 SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
916 SMDS_MeshElement* elem = 0;
917 if ( DuplicateElements || !it0D->more() )
918 elem = getMeshDS()->Add0DElement(aNode);
920 // Update Python script
921 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
923 declareMeshModified( /*isReComputeSafe=*/false );
925 return elem ? elem->GetID() : 0;
927 SMESH_CATCH( SMESH::throwCorbaException );
931 //=============================================================================
933 * Create a ball element on the given node.
935 //=============================================================================
937 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
938 throw (SALOME::SALOME_Exception)
943 if ( diameter < std::numeric_limits<double>::min() )
944 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
946 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
947 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
949 // Update Python script
950 TPythonDump() << "ballElem = "
951 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
953 declareMeshModified( /*isReComputeSafe=*/false );
954 return elem ? elem->GetID() : 0;
956 SMESH_CATCH( SMESH::throwCorbaException );
960 //=============================================================================
962 * Create an edge, either linear and quadratic (this is determed
963 * by number of given nodes, two or three)
965 //=============================================================================
967 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
968 throw (SALOME::SALOME_Exception)
973 int NbNodes = IDsOfNodes.length();
974 SMDS_MeshElement* elem = 0;
977 CORBA::Long index1 = IDsOfNodes[0];
978 CORBA::Long index2 = IDsOfNodes[1];
979 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
980 getMeshDS()->FindNode(index2));
982 // Update Python script
983 TPythonDump() << "edge = " << this << ".AddEdge([ "
984 << index1 << ", " << index2 <<" ])";
987 CORBA::Long n1 = IDsOfNodes[0];
988 CORBA::Long n2 = IDsOfNodes[1];
989 CORBA::Long n12 = IDsOfNodes[2];
990 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
991 getMeshDS()->FindNode(n2),
992 getMeshDS()->FindNode(n12));
993 // Update Python script
994 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
995 <<n1<<", "<<n2<<", "<<n12<<" ])";
998 declareMeshModified( /*isReComputeSafe=*/false );
999 return elem ? elem->GetID() : 0;
1001 SMESH_CATCH( SMESH::throwCorbaException );
1005 //=============================================================================
1009 //=============================================================================
1011 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1012 throw (SALOME::SALOME_Exception)
1017 int NbNodes = IDsOfNodes.length();
1023 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1024 for (int i = 0; i < NbNodes; i++)
1025 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1027 SMDS_MeshElement* elem = 0;
1029 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1030 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1031 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1032 nodes[4], nodes[5]); break;
1033 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1034 nodes[4], nodes[5], nodes[6]); break;
1035 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1036 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1037 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1038 nodes[4], nodes[5], nodes[6], nodes[7],
1040 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1043 // Update Python script
1044 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1046 declareMeshModified( /*isReComputeSafe=*/false );
1048 return elem ? elem->GetID() : 0;
1050 SMESH_CATCH( SMESH::throwCorbaException );
1054 //=============================================================================
1058 //=============================================================================
1060 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1061 throw (SALOME::SALOME_Exception)
1066 int NbNodes = IDsOfNodes.length();
1067 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1068 for (int i = 0; i < NbNodes; i++)
1069 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1072 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1074 // Update Python script
1075 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1077 declareMeshModified( /*isReComputeSafe=*/false );
1078 return elem ? elem->GetID() : 0;
1080 SMESH_CATCH( SMESH::throwCorbaException );
1084 //=============================================================================
1086 * AddQuadPolygonalFace
1088 //=============================================================================
1090 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1091 throw (SALOME::SALOME_Exception)
1096 int NbNodes = IDsOfNodes.length();
1097 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1098 for (int i = 0; i < NbNodes; i++)
1099 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1101 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1103 // Update Python script
1104 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1106 declareMeshModified( /*isReComputeSafe=*/false );
1107 return elem ? elem->GetID() : 0;
1109 SMESH_CATCH( SMESH::throwCorbaException );
1113 //=============================================================================
1115 * Create volume, either linear and quadratic (this is determed
1116 * by number of given nodes)
1118 //=============================================================================
1120 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1121 throw (SALOME::SALOME_Exception)
1126 int NbNodes = IDsOfNodes.length();
1127 vector< const SMDS_MeshNode*> n(NbNodes);
1128 for(int i=0;i<NbNodes;i++)
1129 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1131 SMDS_MeshElement* elem = 0;
1134 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1135 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1136 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1137 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1138 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1139 n[6],n[7],n[8],n[9]);
1141 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1142 n[6],n[7],n[8],n[9],n[10],n[11]);
1144 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1145 n[7],n[8],n[9],n[10],n[11],n[12]);
1147 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1148 n[9],n[10],n[11],n[12],n[13],n[14]);
1150 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1151 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1152 n[15],n[16],n[17],n[18],n[19]);
1154 case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1155 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1158 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1159 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1160 n[15],n[16],n[17],n[18],n[19],
1161 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1165 // Update Python script
1166 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1168 declareMeshModified( /*isReComputeSafe=*/false );
1169 return elem ? elem->GetID() : 0;
1171 SMESH_CATCH( SMESH::throwCorbaException );
1175 //=============================================================================
1177 * AddPolyhedralVolume
1179 //=============================================================================
1180 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1181 const SMESH::long_array & Quantities)
1182 throw (SALOME::SALOME_Exception)
1187 int NbNodes = IDsOfNodes.length();
1188 std::vector<const SMDS_MeshNode*> n (NbNodes);
1189 for (int i = 0; i < NbNodes; i++)
1191 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1192 if (!aNode) return 0;
1196 int NbFaces = Quantities.length();
1197 std::vector<int> q (NbFaces);
1198 for (int j = 0; j < NbFaces; j++)
1199 q[j] = Quantities[j];
1201 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1203 // Update Python script
1204 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1205 << IDsOfNodes << ", " << Quantities << " )";
1207 declareMeshModified( /*isReComputeSafe=*/false );
1208 return elem ? elem->GetID() : 0;
1210 SMESH_CATCH( SMESH::throwCorbaException );
1214 //=============================================================================
1216 * AddPolyhedralVolumeByFaces
1218 //=============================================================================
1220 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1221 throw (SALOME::SALOME_Exception)
1226 int NbFaces = IdsOfFaces.length();
1227 std::vector<const SMDS_MeshNode*> poly_nodes;
1228 std::vector<int> quantities (NbFaces);
1230 for (int i = 0; i < NbFaces; i++) {
1231 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1232 quantities[i] = aFace->NbNodes();
1234 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1235 while (It->more()) {
1236 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1240 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1242 // Update Python script
1243 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1244 << IdsOfFaces << " )";
1246 declareMeshModified( /*isReComputeSafe=*/false );
1247 return elem ? elem->GetID() : 0;
1249 SMESH_CATCH( SMESH::throwCorbaException );
1253 //=============================================================================
1255 // \brief Create 0D elements on all nodes of the given object.
1256 // \param theObject object on whose nodes 0D elements will be created.
1257 // \param theGroupName optional name of a group to add 0D elements created
1258 // and/or found on nodes of \a theObject.
1259 // \param DuplicateElements to add one more 0D element to a node or not.
1260 // \return an object (a new group or a temporary SMESH_IDSource) holding
1261 // ids of new and/or found 0D elements.
1263 //=============================================================================
1265 SMESH::SMESH_IDSource_ptr
1266 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1267 const char* theGroupName,
1268 CORBA::Boolean theDuplicateElements)
1269 throw (SALOME::SALOME_Exception)
1274 SMESH::SMESH_IDSource_var result;
1277 TIDSortedElemSet elements, elems0D;
1278 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1279 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1281 SMESH::long_array_var newElems = new SMESH::long_array;
1282 newElems->length( elems0D.size() );
1283 TIDSortedElemSet::iterator eIt = elems0D.begin();
1284 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1285 newElems[ i ] = (*eIt)->GetID();
1287 SMESH::SMESH_GroupBase_var groupToFill;
1288 if ( theGroupName && strlen( theGroupName ))
1290 // Get existing group named theGroupName
1291 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1292 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1293 SMESH::SMESH_GroupBase_var group = groups[i];
1294 if ( !group->_is_nil() ) {
1295 CORBA::String_var name = group->GetName();
1296 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1297 groupToFill = group;
1302 if ( groupToFill->_is_nil() )
1303 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1304 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1305 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1308 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1310 group_i->Add( newElems );
1311 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1312 pyDump << groupToFill;
1316 result = MakeIDSource( newElems, SMESH::ELEM0D );
1317 pyDump << "elem0DIDs";
1320 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1321 << theObject << ", '" << theGroupName << "' )";
1323 return result._retn();
1325 SMESH_CATCH( SMESH::throwCorbaException );
1329 //=============================================================================
1331 * \brief Bind a node to a vertex
1332 * \param NodeID - node ID
1333 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1334 * \retval boolean - false if NodeID or VertexID is invalid
1336 //=============================================================================
1338 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1339 throw (SALOME::SALOME_Exception)
1343 SMESHDS_Mesh * mesh = getMeshDS();
1344 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1346 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1348 if ( mesh->MaxShapeIndex() < VertexID )
1349 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1351 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1352 if ( shape.ShapeType() != TopAbs_VERTEX )
1353 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1355 mesh->SetNodeOnVertex( node, VertexID );
1357 myMesh->SetIsModified( true );
1359 SMESH_CATCH( SMESH::throwCorbaException );
1362 //=============================================================================
1364 * \brief Store node position on an edge
1365 * \param NodeID - node ID
1366 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1367 * \param paramOnEdge - parameter on edge where the node is located
1368 * \retval boolean - false if any parameter is invalid
1370 //=============================================================================
1372 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1373 CORBA::Double paramOnEdge)
1374 throw (SALOME::SALOME_Exception)
1378 SMESHDS_Mesh * mesh = getMeshDS();
1379 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1381 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1383 if ( mesh->MaxShapeIndex() < EdgeID )
1384 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1386 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1387 if ( shape.ShapeType() != TopAbs_EDGE )
1388 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1391 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1392 if ( paramOnEdge < f || paramOnEdge > l )
1393 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1395 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1397 myMesh->SetIsModified( true );
1399 SMESH_CATCH( SMESH::throwCorbaException );
1402 //=============================================================================
1404 * \brief Store node position on a face
1405 * \param NodeID - node ID
1406 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1407 * \param u - U parameter on face where the node is located
1408 * \param v - V parameter on face where the node is located
1409 * \retval boolean - false if any parameter is invalid
1411 //=============================================================================
1413 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1414 CORBA::Double u, CORBA::Double v)
1415 throw (SALOME::SALOME_Exception)
1418 SMESHDS_Mesh * mesh = getMeshDS();
1419 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1421 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1423 if ( mesh->MaxShapeIndex() < FaceID )
1424 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1426 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1427 if ( shape.ShapeType() != TopAbs_FACE )
1428 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1430 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1431 bool isOut = ( u < surf.FirstUParameter() ||
1432 u > surf.LastUParameter() ||
1433 v < surf.FirstVParameter() ||
1434 v > surf.LastVParameter() );
1438 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1439 << " u( " << surf.FirstUParameter()
1440 << "," << surf.LastUParameter()
1441 << ") v( " << surf.FirstVParameter()
1442 << "," << surf.LastVParameter() << ")" );
1444 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1447 mesh->SetNodeOnFace( node, FaceID, u, v );
1448 myMesh->SetIsModified( true );
1450 SMESH_CATCH( SMESH::throwCorbaException );
1453 //=============================================================================
1455 * \brief Bind a node to a solid
1456 * \param NodeID - node ID
1457 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1458 * \retval boolean - false if NodeID or SolidID is invalid
1460 //=============================================================================
1462 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1463 throw (SALOME::SALOME_Exception)
1466 SMESHDS_Mesh * mesh = getMeshDS();
1467 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1469 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1471 if ( mesh->MaxShapeIndex() < SolidID )
1472 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1474 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1475 if ( shape.ShapeType() != TopAbs_SOLID &&
1476 shape.ShapeType() != TopAbs_SHELL)
1477 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1479 mesh->SetNodeInVolume( node, SolidID );
1481 SMESH_CATCH( SMESH::throwCorbaException );
1484 //=============================================================================
1486 * \brief Bind an element to a shape
1487 * \param ElementID - element ID
1488 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1490 //=============================================================================
1492 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1493 CORBA::Long ShapeID)
1494 throw (SALOME::SALOME_Exception)
1497 SMESHDS_Mesh * mesh = getMeshDS();
1498 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1500 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1502 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1503 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1505 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1506 if ( shape.ShapeType() != TopAbs_EDGE &&
1507 shape.ShapeType() != TopAbs_FACE &&
1508 shape.ShapeType() != TopAbs_SOLID &&
1509 shape.ShapeType() != TopAbs_SHELL )
1510 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1512 mesh->SetMeshElementOnShape( elem, ShapeID );
1514 myMesh->SetIsModified( true );
1516 SMESH_CATCH( SMESH::throwCorbaException );
1519 //=============================================================================
1523 //=============================================================================
1525 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1526 CORBA::Long NodeID2)
1527 throw (SALOME::SALOME_Exception)
1532 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1533 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1537 // Update Python script
1538 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1539 << NodeID1 << ", " << NodeID2 << " )";
1541 int ret = getEditor().InverseDiag ( n1, n2 );
1543 declareMeshModified( /*isReComputeSafe=*/false );
1546 SMESH_CATCH( SMESH::throwCorbaException );
1550 //=============================================================================
1554 //=============================================================================
1556 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1557 CORBA::Long NodeID2)
1558 throw (SALOME::SALOME_Exception)
1563 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1564 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1568 // Update Python script
1569 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1570 << NodeID1 << ", " << NodeID2 << " )";
1573 bool stat = getEditor().DeleteDiag ( n1, n2 );
1575 declareMeshModified( /*isReComputeSafe=*/!stat );
1579 SMESH_CATCH( SMESH::throwCorbaException );
1583 //=============================================================================
1587 //=============================================================================
1589 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1590 throw (SALOME::SALOME_Exception)
1595 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1597 CORBA::Long index = IDsOfElements[i];
1598 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1600 getEditor().Reorient( elem );
1602 // Update Python script
1603 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1605 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1608 SMESH_CATCH( SMESH::throwCorbaException );
1612 //=============================================================================
1616 //=============================================================================
1618 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1619 throw (SALOME::SALOME_Exception)
1624 TPythonDump aTPythonDump; // suppress dump in Reorient()
1626 prepareIdSource( theObject );
1628 SMESH::long_array_var anElementsId = theObject->GetIDs();
1629 CORBA::Boolean isDone = Reorient(anElementsId);
1631 // Update Python script
1632 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1634 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1637 SMESH_CATCH( SMESH::throwCorbaException );
1641 //=======================================================================
1642 //function : Reorient2D
1643 //purpose : Reorient faces contained in \a the2Dgroup.
1644 // the2Dgroup - the mesh or its part to reorient
1645 // theDirection - desired direction of normal of \a theFace
1646 // theFace - ID of face whose orientation is checked.
1647 // It can be < 1 then \a thePoint is used to find a face.
1648 // thePoint - is used to find a face if \a theFace < 1.
1649 // return number of reoriented elements.
1650 //=======================================================================
1652 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1653 const SMESH::DirStruct& theDirection,
1654 CORBA::Long theFace,
1655 const SMESH::PointStruct& thePoint)
1656 throw (SALOME::SALOME_Exception)
1659 initData(/*deleteSearchers=*/false);
1661 TIDSortedElemSet elements;
1662 IDSource_Error error;
1663 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1664 if ( error == IDSource_EMPTY )
1666 if ( error == IDSource_INVALID )
1667 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1670 const SMDS_MeshElement* face = 0;
1673 face = getMeshDS()->FindElement( theFace );
1675 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1676 if ( face->GetType() != SMDSAbs_Face )
1677 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1681 // create theElementSearcher if needed
1682 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1683 if ( !theElementSearcher )
1685 if ( elements.empty() ) // search in the whole mesh
1687 if ( myMesh->NbFaces() == 0 )
1688 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1690 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1694 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1695 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1697 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1701 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1702 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1705 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1706 if ( !elements.empty() && !elements.count( face ))
1707 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1710 const SMESH::PointStruct * P = &theDirection.PS;
1711 gp_Vec dirVec( P->x, P->y, P->z );
1712 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1713 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1715 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1718 declareMeshModified( /*isReComputeSafe=*/false );
1720 TPythonDump() << this << ".Reorient2D( "
1721 << the2Dgroup << ", "
1722 << theDirection << ", "
1724 << thePoint << " )";
1728 SMESH_CATCH( SMESH::throwCorbaException );
1732 //=======================================================================
1733 //function : Reorient2DBy3D
1734 //purpose : Reorient faces basing on orientation of adjacent volumes.
1735 //=======================================================================
1737 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1738 SMESH::SMESH_IDSource_ptr volumeGroup,
1739 CORBA::Boolean outsideNormal)
1740 throw (SALOME::SALOME_Exception)
1745 TIDSortedElemSet volumes;
1746 IDSource_Error volsError;
1747 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1750 for ( size_t i = 0; i < faceGroups.length(); ++i )
1752 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1754 TIDSortedElemSet faces;
1755 IDSource_Error error;
1756 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1757 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1758 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1759 if ( error == IDSource_OK && volsError != IDSource_OK )
1760 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1762 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1764 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1769 declareMeshModified( /*isReComputeSafe=*/false );
1771 TPythonDump() << this << ".Reorient2DBy3D( "
1772 << faceGroups << ", "
1773 << volumeGroup << ", "
1774 << outsideNormal << " )";
1778 SMESH_CATCH( SMESH::throwCorbaException );
1782 //=============================================================================
1784 * \brief Fuse neighbour triangles into quadrangles.
1786 //=============================================================================
1788 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1789 SMESH::NumericalFunctor_ptr Criterion,
1790 CORBA::Double MaxAngle)
1791 throw (SALOME::SALOME_Exception)
1796 SMESHDS_Mesh* aMesh = getMeshDS();
1797 TIDSortedElemSet faces,copyFaces;
1798 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1799 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1800 TIDSortedElemSet* workElements = & faces;
1802 if ( myIsPreviewMode ) {
1803 SMDSAbs_ElementType select = SMDSAbs_Face;
1804 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1805 workElements = & copyFaces;
1808 SMESH::NumericalFunctor_i* aNumericalFunctor =
1809 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1810 SMESH::Controls::NumericalFunctorPtr aCrit;
1811 if ( !aNumericalFunctor )
1812 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1814 aCrit = aNumericalFunctor->GetNumericalFunctor();
1816 if ( !myIsPreviewMode ) {
1817 // Update Python script
1818 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1819 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1822 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1824 declareMeshModified( /*isReComputeSafe=*/!stat );
1827 SMESH_CATCH( SMESH::throwCorbaException );
1831 //=============================================================================
1833 * \brief Fuse neighbour triangles into quadrangles.
1835 //=============================================================================
1837 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1838 SMESH::NumericalFunctor_ptr Criterion,
1839 CORBA::Double MaxAngle)
1840 throw (SALOME::SALOME_Exception)
1845 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1847 prepareIdSource( theObject );
1848 SMESH::long_array_var anElementsId = theObject->GetIDs();
1849 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1851 if ( !myIsPreviewMode ) {
1852 SMESH::NumericalFunctor_i* aNumericalFunctor =
1853 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1855 // Update Python script
1856 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1857 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1862 SMESH_CATCH( SMESH::throwCorbaException );
1866 //=============================================================================
1868 * \brief Split quadrangles into triangles.
1870 //=============================================================================
1872 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1873 SMESH::NumericalFunctor_ptr Criterion)
1874 throw (SALOME::SALOME_Exception)
1879 SMESHDS_Mesh* aMesh = getMeshDS();
1880 TIDSortedElemSet faces;
1881 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1883 SMESH::NumericalFunctor_i* aNumericalFunctor =
1884 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1885 SMESH::Controls::NumericalFunctorPtr aCrit;
1886 if ( !aNumericalFunctor )
1887 aCrit.reset( new SMESH::Controls::AspectRatio() );
1889 aCrit = aNumericalFunctor->GetNumericalFunctor();
1892 // Update Python script
1893 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1895 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1897 declareMeshModified( /*isReComputeSafe=*/false );
1900 SMESH_CATCH( SMESH::throwCorbaException );
1904 //=============================================================================
1906 * \brief Split quadrangles into triangles.
1908 //=============================================================================
1910 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1911 SMESH::NumericalFunctor_ptr Criterion)
1912 throw (SALOME::SALOME_Exception)
1917 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1919 prepareIdSource( theObject );
1920 SMESH::long_array_var anElementsId = theObject->GetIDs();
1921 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1923 SMESH::NumericalFunctor_i* aNumericalFunctor =
1924 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1926 // Update Python script
1927 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1929 declareMeshModified( /*isReComputeSafe=*/false );
1932 SMESH_CATCH( SMESH::throwCorbaException );
1936 //================================================================================
1938 * \brief Split each of quadrangles into 4 triangles.
1939 * \param [in] theObject - theQuads Container of quadrangles to split.
1941 //================================================================================
1943 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1944 throw (SALOME::SALOME_Exception)
1949 TIDSortedElemSet faces;
1950 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1952 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1954 getEditor().QuadTo4Tri( faces );
1955 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1957 SMESH_CATCH( SMESH::throwCorbaException );
1960 //=============================================================================
1962 * \brief Split quadrangles into triangles.
1964 //=============================================================================
1966 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1967 CORBA::Boolean Diag13)
1968 throw (SALOME::SALOME_Exception)
1973 SMESHDS_Mesh* aMesh = getMeshDS();
1974 TIDSortedElemSet faces;
1975 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1977 // Update Python script
1978 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1979 << IDsOfElements << ", " << Diag13 << " )";
1981 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1983 declareMeshModified( /*isReComputeSafe=*/ !stat );
1986 SMESH_CATCH( SMESH::throwCorbaException );
1990 //=============================================================================
1992 * \brief Split quadrangles into triangles.
1994 //=============================================================================
1996 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1997 CORBA::Boolean Diag13)
1998 throw (SALOME::SALOME_Exception)
2003 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2005 prepareIdSource( theObject );
2006 SMESH::long_array_var anElementsId = theObject->GetIDs();
2007 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2009 // Update Python script
2010 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2011 << theObject << ", " << Diag13 << " )";
2013 declareMeshModified( /*isReComputeSafe=*/!isDone );
2016 SMESH_CATCH( SMESH::throwCorbaException );
2021 //=============================================================================
2023 * Find better splitting of the given quadrangle.
2024 * \param IDOfQuad ID of the quadrangle to be splitted.
2025 * \param Criterion A criterion to choose a diagonal for splitting.
2026 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2027 * diagonal is better, 0 if error occurs.
2029 //=============================================================================
2031 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2032 SMESH::NumericalFunctor_ptr Criterion)
2033 throw (SALOME::SALOME_Exception)
2038 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2039 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2041 SMESH::NumericalFunctor_i* aNumericalFunctor =
2042 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2043 SMESH::Controls::NumericalFunctorPtr aCrit;
2044 if (aNumericalFunctor)
2045 aCrit = aNumericalFunctor->GetNumericalFunctor();
2047 aCrit.reset(new SMESH::Controls::AspectRatio());
2049 int id = getEditor().BestSplit(quad, aCrit);
2050 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2054 SMESH_CATCH( SMESH::throwCorbaException );
2058 //================================================================================
2060 * \brief Split volumic elements into tetrahedrons
2062 //================================================================================
2064 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2065 CORBA::Short methodFlags)
2066 throw (SALOME::SALOME_Exception)
2071 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2072 const int noneFacet = -1;
2073 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2074 while( volIt->more() )
2075 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2077 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2078 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2080 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2081 << elems << ", " << methodFlags << " )";
2083 SMESH_CATCH( SMESH::throwCorbaException );
2086 //================================================================================
2088 * \brief Split hexahedra into triangular prisms
2089 * \param elems - elements to split
2090 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2091 * to split into triangles
2092 * \param methodFlags - flags passing splitting method:
2093 * 1 - split the hexahedron into 2 prisms
2094 * 2 - split the hexahedron into 4 prisms
2096 //================================================================================
2098 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2099 const SMESH::PointStruct & startHexPoint,
2100 const SMESH::DirStruct& facetToSplitNormal,
2101 CORBA::Short methodFlags,
2102 CORBA::Boolean allDomains)
2103 throw (SALOME::SALOME_Exception)
2107 prepareIdSource( elems );
2109 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2112 gp_Dir( facetToSplitNormal.PS.x,
2113 facetToSplitNormal.PS.y,
2114 facetToSplitNormal.PS.z ));
2115 TIDSortedElemSet elemSet;
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 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 craeted 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 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 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 #if OCC_VERSION_LARGE > 0x06070100
3894 // fight against orthogonalization
3895 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3896 // 0, S[1], 0, thePoint.y * (1-S[1]),
3897 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3898 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3899 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3900 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3901 loc.SetCoord( thePoint.x * (1-S[0]),
3902 thePoint.y * (1-S[1]),
3903 thePoint.z * (1-S[2]));
3904 M.SetDiagonal( S[0], S[1], S[2] );
3907 double tol = std::numeric_limits<double>::max();
3908 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3909 0, S[1], 0, thePoint.y * (1-S[1]),
3910 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3913 TIDSortedElemSet copyElements;
3914 TIDSortedElemSet* workElements = &elements;
3915 if ( myIsPreviewMode )
3917 TPreviewMesh * tmpMesh = getPreviewMesh();
3918 tmpMesh->Copy( elements, copyElements);
3919 if ( !theCopy && !theTargetMesh )
3921 TIDSortedElemSet elemsAround, elemsAroundCopy;
3922 getElementsAround( elements, getMeshDS(), elemsAround );
3923 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3925 workElements = & copyElements;
3926 theMakeGroups = false;
3929 ::SMESH_MeshEditor::PGroupIDs groupIds =
3930 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3932 if ( !myIsPreviewMode )
3934 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3935 else declareMeshModified( /*isReComputeSafe=*/false );
3937 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3939 SMESH_CATCH( SMESH::throwCorbaException );
3943 //=======================================================================
3946 //=======================================================================
3948 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3949 const SMESH::PointStruct& thePoint,
3950 const SMESH::double_array& theScaleFact,
3951 CORBA::Boolean theCopy)
3952 throw (SALOME::SALOME_Exception)
3954 if ( !myIsPreviewMode ) {
3955 TPythonDump() << this << ".Scale( "
3956 << theObject << ", "
3958 << TVar( theScaleFact ) << ", "
3961 scale(theObject, thePoint, theScaleFact, theCopy, false);
3965 //=======================================================================
3966 //function : ScaleMakeGroups
3968 //=======================================================================
3970 SMESH::ListOfGroups*
3971 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3972 const SMESH::PointStruct& thePoint,
3973 const SMESH::double_array& theScaleFact)
3974 throw (SALOME::SALOME_Exception)
3976 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3978 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3979 if (!myIsPreviewMode) {
3980 dumpGroupsList(aPythonDump, aGroups);
3981 aPythonDump << this << ".Scale("
3984 << TVar( theScaleFact ) << ",True,True)";
3990 //=======================================================================
3991 //function : ScaleMakeMesh
3993 //=======================================================================
3995 SMESH::SMESH_Mesh_ptr
3996 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3997 const SMESH::PointStruct& thePoint,
3998 const SMESH::double_array& theScaleFact,
3999 CORBA::Boolean theCopyGroups,
4000 const char* theMeshName)
4001 throw (SALOME::SALOME_Exception)
4003 SMESH_Mesh_i* mesh_i;
4004 SMESH::SMESH_Mesh_var mesh;
4005 { // open new scope to dump "MakeMesh" command
4006 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4008 TPythonDump pydump; // to prevent dump at mesh creation
4009 mesh = makeMesh( theMeshName );
4010 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4014 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4015 mesh_i->CreateGroupServants();
4017 if ( !myIsPreviewMode )
4018 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4019 << theObject << ", "
4021 << TVar( theScaleFact ) << ", "
4022 << theCopyGroups << ", '"
4023 << theMeshName << "' )";
4027 if (!myIsPreviewMode && mesh_i)
4028 mesh_i->GetGroups();
4030 return mesh._retn();
4034 //=======================================================================
4035 //function : findCoincidentNodes
4037 //=======================================================================
4039 void SMESH_MeshEditor_i::
4040 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4041 CORBA::Double Tolerance,
4042 SMESH::array_of_long_array_out GroupsOfNodes,
4043 CORBA::Boolean SeparateCornersAndMedium)
4045 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4046 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4048 GroupsOfNodes = new SMESH::array_of_long_array;
4049 GroupsOfNodes->length( aListOfListOfNodes.size() );
4050 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4051 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4053 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4054 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4055 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4056 aGroup.length( aListOfNodes.size() );
4057 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4058 aGroup[ j ] = (*lIt)->GetID();
4062 //=======================================================================
4063 //function : FindCoincidentNodes
4065 //=======================================================================
4067 void SMESH_MeshEditor_i::
4068 FindCoincidentNodes (CORBA::Double Tolerance,
4069 SMESH::array_of_long_array_out GroupsOfNodes,
4070 CORBA::Boolean SeparateCornersAndMedium)
4071 throw (SALOME::SALOME_Exception)
4076 TIDSortedNodeSet nodes; // no input nodes
4077 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4079 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4080 << Tolerance << ", "
4081 << SeparateCornersAndMedium << " )";
4083 SMESH_CATCH( SMESH::throwCorbaException );
4086 //=======================================================================
4087 //function : FindCoincidentNodesOnPart
4089 //=======================================================================
4091 void SMESH_MeshEditor_i::
4092 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4093 CORBA::Double Tolerance,
4094 SMESH::array_of_long_array_out GroupsOfNodes,
4095 CORBA::Boolean SeparateCornersAndMedium)
4096 throw (SALOME::SALOME_Exception)
4101 TIDSortedNodeSet nodes;
4102 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4104 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4106 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4108 << Tolerance << ", "
4109 << SeparateCornersAndMedium << " )";
4111 SMESH_CATCH( SMESH::throwCorbaException );
4114 //================================================================================
4116 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4117 * ExceptSubMeshOrGroups
4119 //================================================================================
4121 void SMESH_MeshEditor_i::
4122 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4123 CORBA::Double theTolerance,
4124 SMESH::array_of_long_array_out theGroupsOfNodes,
4125 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4126 CORBA::Boolean theSeparateCornersAndMedium)
4127 throw (SALOME::SALOME_Exception)
4132 TIDSortedNodeSet nodes;
4133 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4135 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4137 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4139 while ( nodeIt->more() )
4140 nodes.erase( cast2Node( nodeIt->next() ));
4142 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4144 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4146 << theTolerance << ", "
4147 << theExceptSubMeshOrGroups << ", "
4148 << theSeparateCornersAndMedium << " )";
4150 SMESH_CATCH( SMESH::throwCorbaException );
4153 //=======================================================================
4154 //function : MergeNodes
4156 //=======================================================================
4158 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4159 const SMESH::ListOfIDSources& NodesToKeep,
4160 CORBA::Boolean AvoidMakingHoles)
4161 throw (SALOME::SALOME_Exception)
4166 SMESHDS_Mesh* aMesh = getMeshDS();
4168 TPythonDump aTPythonDump;
4169 aTPythonDump << this << ".MergeNodes([";
4171 TIDSortedNodeSet setOfNodesToKeep;
4172 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4174 prepareIdSource( NodesToKeep[i] );
4175 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
4176 while ( nodeIt->more() )
4177 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4180 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4181 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4183 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4184 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4185 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4186 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4188 CORBA::Long index = aNodeGroup[ j ];
4189 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4191 if ( setOfNodesToKeep.count( node ))
4192 aListOfNodes.push_front( node );
4194 aListOfNodes.push_back( node );
4197 if ( aListOfNodes.size() < 2 )
4198 aListOfListOfNodes.pop_back();
4200 if ( i > 0 ) aTPythonDump << ", ";
4201 aTPythonDump << aNodeGroup;
4204 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4206 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4208 declareMeshModified( /*isReComputeSafe=*/false );
4210 SMESH_CATCH( SMESH::throwCorbaException );
4213 //=======================================================================
4214 //function : FindEqualElements
4216 //=======================================================================
4218 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4219 SMESH::array_of_long_array_out GroupsOfElementsID)
4220 throw (SALOME::SALOME_Exception)
4225 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4226 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4228 TIDSortedElemSet elems;
4229 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4231 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4232 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4234 GroupsOfElementsID = new SMESH::array_of_long_array;
4235 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4237 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4238 aListOfListOfElementsID.begin();
4239 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4241 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4242 list<int>& listOfIDs = *arraysIt;
4243 aGroup.length( listOfIDs.size() );
4244 list<int>::iterator idIt = listOfIDs.begin();
4245 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4246 aGroup[ k ] = *idIt;
4249 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4253 SMESH_CATCH( SMESH::throwCorbaException );
4256 //=======================================================================
4257 //function : MergeElements
4259 //=======================================================================
4261 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4262 throw (SALOME::SALOME_Exception)
4267 TPythonDump aTPythonDump;
4268 aTPythonDump << this << ".MergeElements( [";
4270 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4272 for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) {
4273 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4274 aListOfListOfElementsID.push_back( list< int >() );
4275 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4276 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) {
4277 CORBA::Long id = anElemsIDGroup[ j ];
4278 aListOfElemsID.push_back( id );
4280 if ( aListOfElemsID.size() < 2 )
4281 aListOfListOfElementsID.pop_back();
4282 if ( i > 0 ) aTPythonDump << ", ";
4283 aTPythonDump << anElemsIDGroup;
4286 getEditor().MergeElements(aListOfListOfElementsID);
4288 declareMeshModified( /*isReComputeSafe=*/true );
4290 aTPythonDump << "] )";
4292 SMESH_CATCH( SMESH::throwCorbaException );
4295 //=======================================================================
4296 //function : MergeEqualElements
4298 //=======================================================================
4300 void SMESH_MeshEditor_i::MergeEqualElements()
4301 throw (SALOME::SALOME_Exception)
4306 getEditor().MergeEqualElements();
4308 declareMeshModified( /*isReComputeSafe=*/true );
4310 TPythonDump() << this << ".MergeEqualElements()";
4312 SMESH_CATCH( SMESH::throwCorbaException );
4315 //=============================================================================
4317 * Move the node to a given point
4319 //=============================================================================
4321 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4325 throw (SALOME::SALOME_Exception)
4328 initData(/*deleteSearchers=*/false);
4330 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4334 if ( theNodeSearcher )
4335 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4337 if ( myIsPreviewMode ) // make preview data
4339 // in a preview mesh, make edges linked to a node
4340 TPreviewMesh& tmpMesh = *getPreviewMesh();
4341 TIDSortedElemSet linkedNodes;
4342 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4343 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4344 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4345 for ( ; nIt != linkedNodes.end(); ++nIt )
4347 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4348 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4352 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4353 // fill preview data
4355 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4356 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4358 getMeshDS()->MoveNode(node, x, y, z);
4360 if ( !myIsPreviewMode )
4362 // Update Python script
4363 TPythonDump() << "isDone = " << this << ".MoveNode( "
4364 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4365 declareMeshModified( /*isReComputeSafe=*/false );
4368 SMESH_CATCH( SMESH::throwCorbaException );
4373 //================================================================================
4375 * \brief Return ID of node closest to a given point
4377 //================================================================================
4379 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4382 throw (SALOME::SALOME_Exception)
4385 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4387 if ( !theNodeSearcher ) {
4388 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4391 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4392 return node->GetID();
4394 SMESH_CATCH( SMESH::throwCorbaException );
4398 //================================================================================
4400 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4401 * move the node closest to the point to point's location and return ID of the node
4403 //================================================================================
4405 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4408 CORBA::Long theNodeID)
4409 throw (SALOME::SALOME_Exception)
4412 // We keep theNodeSearcher until any mesh modification:
4413 // 1) initData() deletes theNodeSearcher at any edition,
4414 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4416 initData(/*deleteSearchers=*/false);
4418 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4420 int nodeID = theNodeID;
4421 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4422 if ( !node ) // preview moving node
4424 if ( !theNodeSearcher ) {
4425 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4428 node = theNodeSearcher->FindClosestTo( p );
4431 nodeID = node->GetID();
4432 if ( myIsPreviewMode ) // make preview data
4434 // in a preview mesh, make edges linked to a node
4435 TPreviewMesh tmpMesh = *getPreviewMesh();
4436 TIDSortedElemSet linkedNodes;
4437 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4438 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4439 for ( ; nIt != linkedNodes.end(); ++nIt )
4441 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4442 tmpMesh.Copy( &edge );
4445 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4447 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4448 // fill preview data
4450 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4452 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4456 getMeshDS()->MoveNode(node, x, y, z);
4460 if ( !myIsPreviewMode )
4462 TPythonDump() << "nodeID = " << this
4463 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4464 << ", " << nodeID << " )";
4466 declareMeshModified( /*isReComputeSafe=*/false );
4471 SMESH_CATCH( SMESH::throwCorbaException );
4475 //=======================================================================
4477 * Return elements of given type where the given point is IN or ON.
4479 * 'ALL' type means elements of any type excluding nodes
4481 //=======================================================================
4483 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4486 SMESH::ElementType type)
4487 throw (SALOME::SALOME_Exception)
4490 SMESH::long_array_var res = new SMESH::long_array;
4491 vector< const SMDS_MeshElement* > foundElems;
4493 theSearchersDeleter.Set( myMesh );
4494 if ( !theElementSearcher ) {
4495 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4497 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4498 SMDSAbs_ElementType( type ),
4500 res->length( foundElems.size() );
4501 for ( size_t i = 0; i < foundElems.size(); ++i )
4502 res[i] = foundElems[i]->GetID();
4506 SMESH_CATCH( SMESH::throwCorbaException );
4510 //=======================================================================
4511 //function : FindAmongElementsByPoint
4512 //purpose : Searching among the given elements, return elements of given type
4513 // where the given point is IN or ON.
4514 // 'ALL' type means elements of any type excluding nodes
4515 //=======================================================================
4518 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4522 SMESH::ElementType type)
4523 throw (SALOME::SALOME_Exception)
4526 SMESH::long_array_var res = new SMESH::long_array;
4528 if ( type != SMESH::NODE )
4530 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4531 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4532 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4533 type != types[0] ) // but search of elements of dim > 0
4536 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4537 return FindElementsByPoint( x,y,z, type );
4539 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4541 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4542 if ( !theElementSearcher )
4544 // create a searcher from elementIDs
4545 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4546 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4548 if ( !idSourceToSet( elementIDs, meshDS, elements,
4549 ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ),
4550 /*emptyIfIsMesh=*/true))
4553 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4554 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4556 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4559 vector< const SMDS_MeshElement* > foundElems;
4561 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4562 SMDSAbs_ElementType( type ),
4564 res->length( foundElems.size() );
4565 for ( size_t i = 0; i < foundElems.size(); ++i )
4566 res[i] = foundElems[i]->GetID();
4570 SMESH_CATCH( SMESH::throwCorbaException );
4574 //=======================================================================
4575 //function : GetPointState
4576 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4577 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4578 //=======================================================================
4580 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4583 throw (SALOME::SALOME_Exception)
4586 theSearchersDeleter.Set( myMesh );
4587 if ( !theElementSearcher ) {
4588 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4590 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4592 SMESH_CATCH( SMESH::throwCorbaException );
4596 //=======================================================================
4597 //function : convError
4599 //=======================================================================
4601 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4603 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4607 RETCASE( SEW_BORDER1_NOT_FOUND );
4608 RETCASE( SEW_BORDER2_NOT_FOUND );
4609 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4610 RETCASE( SEW_BAD_SIDE_NODES );
4611 RETCASE( SEW_VOLUMES_TO_SPLIT );
4612 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4613 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4614 RETCASE( SEW_BAD_SIDE1_NODES );
4615 RETCASE( SEW_BAD_SIDE2_NODES );
4616 RETCASE( SEW_INTERNAL_ERROR );
4618 return SMESH::SMESH_MeshEditor::SEW_OK;
4621 //=======================================================================
4623 * Returns groups of FreeBorder's coincident within the given tolerance.
4624 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
4625 * to free borders being compared is used.
4627 //=======================================================================
4629 SMESH::CoincidentFreeBorders*
4630 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
4632 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
4636 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
4637 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
4639 // copy free borders
4640 aCFB->borders.length( cfb._borders.size() );
4641 for ( size_t i = 0; i < cfb._borders.size(); ++i )
4643 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
4644 SMESH::FreeBorder& aBRD = aCFB->borders[i];
4645 aBRD.nodeIDs.length( nodes.size() );
4646 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4647 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
4650 // copy coincident parts
4651 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
4652 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
4654 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
4655 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
4656 aGRP.length( grp.size() );
4657 for ( size_t iP = 0; iP < grp.size(); ++iP )
4659 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
4660 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4661 aPART.border = part._border;
4662 aPART.node1 = part._node1;
4663 aPART.node2 = part._node2;
4664 aPART.nodeLast = part._nodeLast;
4667 SMESH_CATCH( SMESH::doNothing );
4669 TPythonDump() << "CoincidentFreeBorders = "
4670 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
4672 return aCFB._retn();
4675 //=======================================================================
4677 * Sew FreeBorder's of each group
4679 //=======================================================================
4681 CORBA::Short SMESH_MeshEditor_i::
4682 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
4683 CORBA::Boolean createPolygons,
4684 CORBA::Boolean createPolyhedra)
4685 throw (SALOME::SALOME_Exception)
4687 CORBA::Short nbSewed = 0;
4689 SMESH_MeshAlgos::TFreeBorderVec groups;
4690 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
4692 // check the input and collect nodes
4693 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
4695 borderNodes.clear();
4696 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
4697 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
4699 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4700 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
4701 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
4703 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
4705 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
4706 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
4707 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
4708 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
4709 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
4710 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4712 // do not keep these nodes for further sewing as nodes can be removed by the sewing
4713 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
4714 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
4715 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
4717 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
4719 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
4721 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4723 borderNodes.push_back( n1 );
4724 borderNodes.push_back( n2 );
4725 borderNodes.push_back( n3 );
4727 groups.push_back( borderNodes );
4730 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
4731 // to get nodes that replace other nodes during merge we create 0D elements
4732 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
4735 vector< const SMDS_MeshElement* > tmp0Delems;
4736 for ( size_t i = 0; i < groups.size(); ++i )
4738 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4739 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4741 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
4743 tmp0Delems.push_back( it0D->next() );
4745 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
4749 // cout << endl << "INIT" << endl;
4750 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4752 // cout << i << " ";
4753 // if ( i % 3 == 0 ) cout << "^ ";
4754 // tmp0Delems[i]->GetNode(0)->Print( cout );
4759 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
4761 for ( size_t i = 0; i < groups.size(); ++i )
4763 bool isBordToBord = true;
4764 bool groupSewed = false;
4765 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4766 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
4768 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
4769 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
4770 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
4772 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
4773 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
4774 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
4776 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
4779 // TIDSortedElemSet emptySet, avoidSet;
4780 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
4782 // cout << "WRONG 2nd 1" << endl;
4783 // n0->Print( cout );
4784 // n1->Print( cout );
4786 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
4788 // cout << "WRONG 2nd 2" << endl;
4789 // n3->Print( cout );
4790 // n4->Print( cout );
4793 if ( !isBordToBord )
4795 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
4796 n2 = 0; // and n2 is not used
4798 // 1st border moves to 2nd
4799 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
4801 /*2ndIsFreeBorder=*/ isBordToBord,
4802 createPolygons, createPolyhedra);
4803 groupSewed = ( res == ok );
4805 isBordToBord = false;
4806 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
4807 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
4809 // cout << t << " ";
4810 // if ( t % 3 == 0 ) cout << "^ ";
4811 // tmp0Delems[t]->GetNode(0)->Print( cout );
4814 i0D += nodes.size();
4815 nbSewed += groupSewed;
4818 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
4819 << freeBorders << ", "
4820 << createPolygons << ", "
4821 << createPolyhedra << " )";
4823 SMESH_CATCH( SMESH::doNothing );
4825 declareMeshModified( /*isReComputeSafe=*/false );
4827 // remove tmp 0D elements
4829 set< const SMDS_MeshElement* > removed0D;
4830 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4832 if ( removed0D.insert( tmp0Delems[i] ).second )
4833 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
4835 SMESH_CATCH( SMESH::throwCorbaException );
4840 //=======================================================================
4841 //function : SewFreeBorders
4843 //=======================================================================
4845 SMESH::SMESH_MeshEditor::Sew_Error
4846 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4847 CORBA::Long SecondNodeID1,
4848 CORBA::Long LastNodeID1,
4849 CORBA::Long FirstNodeID2,
4850 CORBA::Long SecondNodeID2,
4851 CORBA::Long LastNodeID2,
4852 CORBA::Boolean CreatePolygons,
4853 CORBA::Boolean CreatePolyedrs)
4854 throw (SALOME::SALOME_Exception)
4859 SMESHDS_Mesh* aMesh = getMeshDS();
4861 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4862 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4863 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4864 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4865 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4866 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4868 if (!aBorderFirstNode ||
4869 !aBorderSecondNode||
4871 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4872 if (!aSide2FirstNode ||
4873 !aSide2SecondNode ||
4875 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4877 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4878 << FirstNodeID1 << ", "
4879 << SecondNodeID1 << ", "
4880 << LastNodeID1 << ", "
4881 << FirstNodeID2 << ", "
4882 << SecondNodeID2 << ", "
4883 << LastNodeID2 << ", "
4884 << CreatePolygons<< ", "
4885 << CreatePolyedrs<< " )";
4887 SMESH::SMESH_MeshEditor::Sew_Error error =
4888 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4899 declareMeshModified( /*isReComputeSafe=*/false );
4902 SMESH_CATCH( SMESH::throwCorbaException );
4903 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4907 //=======================================================================
4908 //function : SewConformFreeBorders
4910 //=======================================================================
4912 SMESH::SMESH_MeshEditor::Sew_Error
4913 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4914 CORBA::Long SecondNodeID1,
4915 CORBA::Long LastNodeID1,
4916 CORBA::Long FirstNodeID2,
4917 CORBA::Long SecondNodeID2)
4918 throw (SALOME::SALOME_Exception)
4923 SMESHDS_Mesh* aMesh = getMeshDS();
4925 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4926 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4927 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4928 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4929 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4930 const SMDS_MeshNode* aSide2ThirdNode = 0;
4932 if (!aBorderFirstNode ||
4933 !aBorderSecondNode||
4935 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4936 if (!aSide2FirstNode ||
4938 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4940 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4941 << FirstNodeID1 << ", "
4942 << SecondNodeID1 << ", "
4943 << LastNodeID1 << ", "
4944 << FirstNodeID2 << ", "
4945 << SecondNodeID2 << " )";
4947 SMESH::SMESH_MeshEditor::Sew_Error error =
4948 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4957 declareMeshModified( /*isReComputeSafe=*/false );
4960 SMESH_CATCH( SMESH::throwCorbaException );
4961 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4965 //=======================================================================
4966 //function : SewBorderToSide
4968 //=======================================================================
4970 SMESH::SMESH_MeshEditor::Sew_Error
4971 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4972 CORBA::Long SecondNodeIDOnFreeBorder,
4973 CORBA::Long LastNodeIDOnFreeBorder,
4974 CORBA::Long FirstNodeIDOnSide,
4975 CORBA::Long LastNodeIDOnSide,
4976 CORBA::Boolean CreatePolygons,
4977 CORBA::Boolean CreatePolyedrs)
4978 throw (SALOME::SALOME_Exception)
4983 SMESHDS_Mesh* aMesh = getMeshDS();
4985 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4986 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4987 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4988 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4989 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4990 const SMDS_MeshNode* aSide2ThirdNode = 0;
4992 if (!aBorderFirstNode ||
4993 !aBorderSecondNode||
4995 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4996 if (!aSide2FirstNode ||
4998 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5000 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5001 << FirstNodeIDOnFreeBorder << ", "
5002 << SecondNodeIDOnFreeBorder << ", "
5003 << LastNodeIDOnFreeBorder << ", "
5004 << FirstNodeIDOnSide << ", "
5005 << LastNodeIDOnSide << ", "
5006 << CreatePolygons << ", "
5007 << CreatePolyedrs << ") ";
5009 SMESH::SMESH_MeshEditor::Sew_Error error =
5010 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5020 declareMeshModified( /*isReComputeSafe=*/false );
5023 SMESH_CATCH( SMESH::throwCorbaException );
5024 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5028 //=======================================================================
5029 //function : SewSideElements
5031 //=======================================================================
5033 SMESH::SMESH_MeshEditor::Sew_Error
5034 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5035 const SMESH::long_array& IDsOfSide2Elements,
5036 CORBA::Long NodeID1OfSide1ToMerge,
5037 CORBA::Long NodeID1OfSide2ToMerge,
5038 CORBA::Long NodeID2OfSide1ToMerge,
5039 CORBA::Long NodeID2OfSide2ToMerge)
5040 throw (SALOME::SALOME_Exception)
5045 SMESHDS_Mesh* aMesh = getMeshDS();
5047 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5048 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5049 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5050 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5052 if (!aFirstNode1ToMerge ||
5053 !aFirstNode2ToMerge )
5054 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5055 if (!aSecondNode1ToMerge||
5056 !aSecondNode2ToMerge)
5057 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5059 TIDSortedElemSet aSide1Elems, aSide2Elems;
5060 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5061 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5063 TPythonDump() << "error = " << this << ".SewSideElements( "
5064 << IDsOfSide1Elements << ", "
5065 << IDsOfSide2Elements << ", "
5066 << NodeID1OfSide1ToMerge << ", "
5067 << NodeID1OfSide2ToMerge << ", "
5068 << NodeID2OfSide1ToMerge << ", "
5069 << NodeID2OfSide2ToMerge << ")";
5071 SMESH::SMESH_MeshEditor::Sew_Error error =
5072 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5075 aSecondNode1ToMerge,
5076 aSecondNode2ToMerge));
5078 declareMeshModified( /*isReComputeSafe=*/false );
5081 SMESH_CATCH( SMESH::throwCorbaException );
5082 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5085 //================================================================================
5087 * \brief Set new nodes for given element
5088 * \param ide - element id
5089 * \param newIDs - new node ids
5090 * \retval CORBA::Boolean - true if result is OK
5092 //================================================================================
5094 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5095 const SMESH::long_array& newIDs)
5096 throw (SALOME::SALOME_Exception)
5101 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5102 if(!elem) return false;
5104 int nbn = newIDs.length();
5106 vector<const SMDS_MeshNode*> aNodes(nbn);
5109 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5112 aNodes[nbn1] = aNode;
5115 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5116 << ide << ", " << newIDs << " )";
5118 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5120 declareMeshModified( /*isReComputeSafe=*/ !res );
5124 SMESH_CATCH( SMESH::throwCorbaException );
5128 //=======================================================================
5130 * \brief Makes a part of the mesh quadratic or bi-quadratic
5132 //=======================================================================
5134 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5135 CORBA::Boolean theToBiQuad,
5136 SMESH::SMESH_IDSource_ptr theObject)
5137 throw (SALOME::SALOME_Exception)
5142 TIDSortedElemSet elems;
5144 if ( !( elemsOK = CORBA::is_nil( theObject )))
5146 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5147 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5151 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5152 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5154 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5155 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5157 declareMeshModified( /*isReComputeSafe=*/false );
5160 SMESH_CATCH( SMESH::throwCorbaException );
5163 //=======================================================================
5164 //function : ConvertFromQuadratic
5166 //=======================================================================
5168 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5169 throw (SALOME::SALOME_Exception)
5174 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5175 TPythonDump() << this << ".ConvertFromQuadratic()";
5176 declareMeshModified( /*isReComputeSafe=*/!isDone );
5179 SMESH_CATCH( SMESH::throwCorbaException );
5183 //=======================================================================
5184 //function : ConvertToQuadratic
5186 //=======================================================================
5188 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5189 throw (SALOME::SALOME_Exception)
5191 convertToQuadratic( theForce3d, false );
5192 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5195 //================================================================================
5197 * \brief Makes a part of the mesh quadratic
5199 //================================================================================
5201 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5202 SMESH::SMESH_IDSource_ptr theObject)
5203 throw (SALOME::SALOME_Exception)
5205 convertToQuadratic( theForce3d, false, theObject );
5206 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5209 //================================================================================
5211 * \brief Makes a part of the mesh bi-quadratic
5213 //================================================================================
5215 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5216 SMESH::SMESH_IDSource_ptr theObject)
5217 throw (SALOME::SALOME_Exception)
5219 convertToQuadratic( theForce3d, true, theObject );
5220 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5223 //================================================================================
5225 * \brief Makes a part of the mesh linear
5227 //================================================================================
5229 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5230 throw (SALOME::SALOME_Exception)
5237 TIDSortedElemSet elems;
5238 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5240 if ( elems.empty() )
5242 ConvertFromQuadratic();
5244 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5246 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5250 getEditor().ConvertFromQuadratic(elems);
5253 declareMeshModified( /*isReComputeSafe=*/false );
5255 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5257 SMESH_CATCH( SMESH::throwCorbaException );
5260 //=======================================================================
5261 //function : makeMesh
5262 //purpose : create a named imported mesh
5263 //=======================================================================
5265 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5267 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5268 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5269 SALOMEDS::Study_var study = gen->GetCurrentStudy();
5270 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5271 gen->SetName( meshSO, theMeshName, "Mesh" );
5272 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5274 return mesh._retn();
5277 //=======================================================================
5278 //function : dumpGroupsList
5280 //=======================================================================
5282 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5283 const SMESH::ListOfGroups * theGroupList)
5285 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5286 if ( isDumpGroupList )
5287 theDumpPython << theGroupList << " = ";
5290 //================================================================================
5292 \brief Generates the unique group name.
5293 \param thePrefix name prefix
5296 //================================================================================
5298 std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix)
5300 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5301 set<std::string> groupNames;
5303 // Get existing group names
5304 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5305 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5306 if (CORBA::is_nil(aGroup))
5309 CORBA::String_var name = aGroup->GetName();
5310 groupNames.insert( name.in() );
5314 std::string name = thePrefix;
5317 while (!groupNames.insert(name).second)
5318 name = SMESH_Comment( thePrefix ) << "_" << index++;
5323 //================================================================================
5325 * \brief Prepare SMESH_IDSource for work
5327 //================================================================================
5329 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5331 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5333 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5334 filter->SetMesh( mesh );
5337 //================================================================================
5339 * \brief Retrieve elements of given type from SMESH_IDSource
5341 //================================================================================
5343 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5344 const SMESHDS_Mesh* theMeshDS,
5345 TIDSortedElemSet& theElemSet,
5346 const SMDSAbs_ElementType theType,
5347 const bool emptyIfIsMesh,
5348 IDSource_Error* error)
5351 if ( error ) *error = IDSource_OK;
5353 if ( CORBA::is_nil( theIDSource ))
5355 if ( error ) *error = IDSource_INVALID;
5358 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5360 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5361 *error = IDSource_EMPTY;
5364 prepareIdSource( theIDSource );
5365 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5366 if ( anIDs->length() == 0 )
5368 if ( error ) *error = IDSource_EMPTY;
5371 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5372 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5374 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5376 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5380 if ( error ) *error = IDSource_INVALID;
5386 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5387 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5389 if ( error ) *error = IDSource_INVALID;
5396 //================================================================================
5398 * \brief Duplicates given elements, i.e. creates new elements based on the
5399 * same nodes as the given ones.
5400 * \param theElements - container of elements to duplicate.
5401 * \param theGroupName - a name of group to contain the generated elements.
5402 * If a group with such a name already exists, the new elements
5403 * are added to the existng group, else a new group is created.
5404 * If \a theGroupName is empty, new elements are not added
5406 * \return a group where the new elements are added. NULL if theGroupName == "".
5409 //================================================================================
5411 SMESH::SMESH_Group_ptr
5412 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5413 const char* theGroupName)
5414 throw (SALOME::SALOME_Exception)
5416 SMESH::SMESH_Group_var newGroup;
5423 TIDSortedElemSet elems;
5424 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5426 getEditor().DoubleElements( elems );
5428 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5431 SMESH::ElementType type =
5432 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5433 // find existing group
5434 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5435 for ( size_t i = 0; i < groups->length(); ++i )
5436 if ( groups[i]->GetType() == type )
5438 CORBA::String_var name = groups[i]->GetName();
5439 if ( strcmp( name, theGroupName ) == 0 ) {
5440 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5444 // create a new group
5445 if ( newGroup->_is_nil() )
5446 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5448 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5450 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5451 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5452 for ( int i = 1; i <= aSeq.Length(); i++ )
5453 groupDS->SMDSGroup().Add( aSeq(i) );
5458 if ( !newGroup->_is_nil() )
5459 pyDump << newGroup << " = ";
5460 pyDump << this << ".DoubleElements( "
5461 << theElements << ", " << "'" << theGroupName <<"')";
5463 SMESH_CATCH( SMESH::throwCorbaException );
5465 return newGroup._retn();
5468 //================================================================================
5470 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5471 \param theNodes - identifiers of nodes to be doubled
5472 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5473 nodes. If list of element identifiers is empty then nodes are doubled but
5474 they not assigned to elements
5475 \return TRUE if operation has been completed successfully, FALSE otherwise
5476 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5478 //================================================================================
5480 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5481 const SMESH::long_array& theModifiedElems )
5482 throw (SALOME::SALOME_Exception)
5487 list< int > aListOfNodes;
5489 for ( i = 0, n = theNodes.length(); i < n; i++ )
5490 aListOfNodes.push_back( theNodes[ i ] );
5492 list< int > aListOfElems;
5493 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5494 aListOfElems.push_back( theModifiedElems[ i ] );
5496 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5498 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5500 // Update Python script
5501 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5505 SMESH_CATCH( SMESH::throwCorbaException );
5509 //================================================================================
5511 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5512 This method provided for convenience works as DoubleNodes() described above.
5513 \param theNodeId - identifier of node to be doubled.
5514 \param theModifiedElems - identifiers of elements to be updated.
5515 \return TRUE if operation has been completed successfully, FALSE otherwise
5516 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5518 //================================================================================
5520 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5521 const SMESH::long_array& theModifiedElems )
5522 throw (SALOME::SALOME_Exception)
5525 SMESH::long_array_var aNodes = new SMESH::long_array;
5526 aNodes->length( 1 );
5527 aNodes[ 0 ] = theNodeId;
5529 TPythonDump pyDump; // suppress dump by the next line
5531 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5533 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5537 SMESH_CATCH( SMESH::throwCorbaException );
5541 //================================================================================
5543 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5544 This method provided for convenience works as DoubleNodes() described above.
5545 \param theNodes - group of nodes to be doubled.
5546 \param theModifiedElems - group of elements to be updated.
5547 \return TRUE if operation has been completed successfully, FALSE otherwise
5548 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5550 //================================================================================
5552 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5553 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5554 throw (SALOME::SALOME_Exception)
5557 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5560 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5561 SMESH::long_array_var aModifiedElems;
5562 if ( !CORBA::is_nil( theModifiedElems ) )
5563 aModifiedElems = theModifiedElems->GetListOfID();
5566 aModifiedElems = new SMESH::long_array;
5567 aModifiedElems->length( 0 );
5570 TPythonDump pyDump; // suppress dump by the next line
5572 bool done = DoubleNodes( aNodes, aModifiedElems );
5574 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5578 SMESH_CATCH( SMESH::throwCorbaException );
5582 //================================================================================
5584 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5585 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5586 * \param theNodes - group of nodes to be doubled.
5587 * \param theModifiedElems - group of elements to be updated.
5588 * \return a new group with newly created nodes
5589 * \sa DoubleNodeGroup()
5591 //================================================================================
5593 SMESH::SMESH_Group_ptr
5594 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5595 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5596 throw (SALOME::SALOME_Exception)
5599 SMESH::SMESH_Group_var aNewGroup;
5601 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5602 return aNewGroup._retn();
5605 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5606 SMESH::long_array_var aModifiedElems;
5607 if ( !CORBA::is_nil( theModifiedElems ) )
5608 aModifiedElems = theModifiedElems->GetListOfID();
5610 aModifiedElems = new SMESH::long_array;
5611 aModifiedElems->length( 0 );
5614 TPythonDump pyDump; // suppress dump by the next line
5616 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5619 // Create group with newly created nodes
5620 SMESH::long_array_var anIds = GetLastCreatedNodes();
5621 if (anIds->length() > 0) {
5622 std::string anUnindexedName (theNodes->GetName());
5623 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5624 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5625 aNewGroup->Add(anIds);
5626 pyDump << aNewGroup << " = ";
5630 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5631 << theModifiedElems << " )";
5633 return aNewGroup._retn();
5635 SMESH_CATCH( SMESH::throwCorbaException );
5639 //================================================================================
5641 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5642 This method provided for convenience works as DoubleNodes() described above.
5643 \param theNodes - list of groups of nodes to be doubled
5644 \param theModifiedElems - list of groups of elements to be updated.
5645 \return TRUE if operation has been completed successfully, FALSE otherwise
5646 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5648 //================================================================================
5650 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5651 const SMESH::ListOfGroups& theModifiedElems )
5652 throw (SALOME::SALOME_Exception)
5657 std::list< int > aNodes;
5659 for ( i = 0, n = theNodes.length(); i < n; i++ )
5661 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5662 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5664 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5665 for ( j = 0, m = aCurr->length(); j < m; j++ )
5666 aNodes.push_back( aCurr[ j ] );
5670 std::list< int > anElems;
5671 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5673 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5674 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5676 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5677 for ( j = 0, m = aCurr->length(); j < m; j++ )
5678 anElems.push_back( aCurr[ j ] );
5682 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5684 declareMeshModified( /*isReComputeSafe=*/false );
5686 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5690 SMESH_CATCH( SMESH::throwCorbaException );
5694 //================================================================================
5696 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5697 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5698 * \param theNodes - group of nodes to be doubled.
5699 * \param theModifiedElems - group of elements to be updated.
5700 * \return a new group with newly created nodes
5701 * \sa DoubleNodeGroups()
5703 //================================================================================
5705 SMESH::SMESH_Group_ptr
5706 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5707 const SMESH::ListOfGroups& theModifiedElems )
5708 throw (SALOME::SALOME_Exception)
5710 SMESH::SMESH_Group_var aNewGroup;
5712 TPythonDump pyDump; // suppress dump by the next line
5714 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5718 // Create group with newly created nodes
5719 SMESH::long_array_var anIds = GetLastCreatedNodes();
5720 if (anIds->length() > 0) {
5721 std::string anUnindexedName (theNodes[0]->GetName());
5722 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5723 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5724 aNewGroup->Add(anIds);
5725 pyDump << aNewGroup << " = ";
5729 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5730 << theModifiedElems << " )";
5732 return aNewGroup._retn();
5736 //================================================================================
5738 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5739 \param theElems - the list of elements (edges or faces) to be replicated
5740 The nodes for duplication could be found from these elements
5741 \param theNodesNot - list of nodes to NOT replicate
5742 \param theAffectedElems - the list of elements (cells and edges) to which the
5743 replicated nodes should be associated to.
5744 \return TRUE if operation has been completed successfully, FALSE otherwise
5745 \sa DoubleNodeGroup(), DoubleNodeGroups()
5747 //================================================================================
5749 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5750 const SMESH::long_array& theNodesNot,
5751 const SMESH::long_array& theAffectedElems )
5752 throw (SALOME::SALOME_Exception)
5757 SMESHDS_Mesh* aMeshDS = getMeshDS();
5758 TIDSortedElemSet anElems, aNodes, anAffected;
5759 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5760 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5761 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5763 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5765 // Update Python script
5766 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5767 << theNodesNot << ", " << theAffectedElems << " )";
5769 declareMeshModified( /*isReComputeSafe=*/false );
5772 SMESH_CATCH( SMESH::throwCorbaException );
5776 //================================================================================
5778 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5779 \param theElems - the list of elements (edges or faces) to be replicated
5780 The nodes for duplication could be found from these elements
5781 \param theNodesNot - list of nodes to NOT replicate
5782 \param theShape - shape to detect affected elements (element which geometric center
5783 located on or inside shape).
5784 The replicated nodes should be associated to affected elements.
5785 \return TRUE if operation has been completed successfully, FALSE otherwise
5786 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5788 //================================================================================
5790 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5791 const SMESH::long_array& theNodesNot,
5792 GEOM::GEOM_Object_ptr theShape )
5793 throw (SALOME::SALOME_Exception)
5799 SMESHDS_Mesh* aMeshDS = getMeshDS();
5800 TIDSortedElemSet anElems, aNodes;
5801 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5802 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5804 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5805 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5807 // Update Python script
5808 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5809 << theNodesNot << ", " << theShape << " )";
5811 declareMeshModified( /*isReComputeSafe=*/false );
5814 SMESH_CATCH( SMESH::throwCorbaException );
5818 //================================================================================
5820 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5821 \param theElems - group of of elements (edges or faces) to be replicated
5822 \param theNodesNot - group of nodes not to replicated
5823 \param theAffectedElems - group of elements to which the replicated nodes
5824 should be associated to.
5825 \return TRUE if operation has been completed successfully, FALSE otherwise
5826 \sa DoubleNodes(), DoubleNodeGroups()
5828 //================================================================================
5831 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5832 SMESH::SMESH_GroupBase_ptr theNodesNot,
5833 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5834 throw (SALOME::SALOME_Exception)
5837 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5843 SMESHDS_Mesh* aMeshDS = getMeshDS();
5844 TIDSortedElemSet anElems, aNodes, anAffected;
5845 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5846 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5847 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5849 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5851 // Update Python script
5852 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5853 << theNodesNot << ", " << theAffectedElems << " )";
5855 declareMeshModified( /*isReComputeSafe=*/false );
5858 SMESH_CATCH( SMESH::throwCorbaException );
5862 //================================================================================
5864 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5865 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5866 * \param theElems - group of of elements (edges or faces) to be replicated
5867 * \param theNodesNot - group of nodes not to replicated
5868 * \param theAffectedElems - group of elements to which the replicated nodes
5869 * should be associated to.
5870 * \return a new group with newly created elements
5871 * \sa DoubleNodeElemGroup()
5873 //================================================================================
5875 SMESH::SMESH_Group_ptr
5876 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5877 SMESH::SMESH_GroupBase_ptr theNodesNot,
5878 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5879 throw (SALOME::SALOME_Exception)
5882 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5886 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5887 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5889 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5891 << theNodesNot << ", "
5892 << theAffectedElems << " )";
5894 return elemGroup._retn();
5897 //================================================================================
5899 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5900 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5901 * \param theElems - group of of elements (edges or faces) to be replicated
5902 * \param theNodesNot - group of nodes not to replicated
5903 * \param theAffectedElems - group of elements to which the replicated nodes
5904 * should be associated to.
5905 * \return a new group with newly created elements
5906 * \sa DoubleNodeElemGroup()
5908 //================================================================================
5910 SMESH::ListOfGroups*
5911 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5912 SMESH::SMESH_GroupBase_ptr theNodesNot,
5913 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5914 CORBA::Boolean theElemGroupNeeded,
5915 CORBA::Boolean theNodeGroupNeeded)
5916 throw (SALOME::SALOME_Exception)
5919 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5920 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5921 aTwoGroups->length( 2 );
5923 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5924 return aTwoGroups._retn();
5929 SMESHDS_Mesh* aMeshDS = getMeshDS();
5930 TIDSortedElemSet anElems, aNodes, anAffected;
5931 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5932 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5933 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5936 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5938 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5944 // Create group with newly created elements
5945 CORBA::String_var elemGroupName = theElems->GetName();
5946 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
5947 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5949 SMESH::long_array_var anIds = GetLastCreatedElems();
5950 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5951 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5952 aNewElemGroup->Add(anIds);
5954 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5956 SMESH::long_array_var anIds = GetLastCreatedNodes();
5957 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5958 aNewNodeGroup->Add(anIds);
5962 // Update Python script
5965 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5966 else pyDump << aNewElemGroup << ", ";
5967 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5968 else pyDump << aNewNodeGroup << " ] = ";
5970 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5971 << theNodesNot << ", "
5972 << theAffectedElems << ", "
5973 << theElemGroupNeeded << ", "
5974 << theNodeGroupNeeded <<" )";
5976 aTwoGroups[0] = aNewElemGroup._retn();
5977 aTwoGroups[1] = aNewNodeGroup._retn();
5978 return aTwoGroups._retn();
5980 SMESH_CATCH( SMESH::throwCorbaException );
5984 //================================================================================
5986 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5987 \param theElems - group of of elements (edges or faces) to be replicated
5988 \param theNodesNot - group of nodes not to replicated
5989 \param theShape - shape to detect affected elements (element which geometric center
5990 located on or inside shape).
5991 The replicated nodes should be associated to affected elements.
5992 \return TRUE if operation has been completed successfully, FALSE otherwise
5993 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5995 //================================================================================
5998 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5999 SMESH::SMESH_GroupBase_ptr theNodesNot,
6000 GEOM::GEOM_Object_ptr theShape )
6001 throw (SALOME::SALOME_Exception)
6004 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6010 SMESHDS_Mesh* aMeshDS = getMeshDS();
6011 TIDSortedElemSet anElems, aNodes, anAffected;
6012 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6013 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6015 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6016 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6019 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6021 // Update Python script
6022 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6023 << theNodesNot << ", " << theShape << " )";
6026 SMESH_CATCH( SMESH::throwCorbaException );
6030 //================================================================================
6032 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6033 * \param [in] theGrpList - groups
6034 * \param [in] theMeshDS - mesh
6035 * \param [out] theElemSet - set of elements
6036 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6038 //================================================================================
6040 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6041 SMESHDS_Mesh* theMeshDS,
6042 TIDSortedElemSet& theElemSet,
6043 const bool theIsNodeGrp)
6045 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6047 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6048 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6049 : aGrp->GetType() != SMESH::NODE ) )
6051 SMESH::long_array_var anIDs = aGrp->GetIDs();
6052 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6057 //================================================================================
6059 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6060 This method provided for convenience works as DoubleNodes() described above.
6061 \param theElems - list of groups of elements (edges or faces) to be replicated
6062 \param theNodesNot - list of groups of nodes not to replicated
6063 \param theAffectedElems - group of elements to which the replicated nodes
6064 should be associated to.
6065 \return TRUE if operation has been completed successfully, FALSE otherwise
6066 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6068 //================================================================================
6071 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6072 const SMESH::ListOfGroups& theNodesNot,
6073 const SMESH::ListOfGroups& theAffectedElems)
6074 throw (SALOME::SALOME_Exception)
6080 SMESHDS_Mesh* aMeshDS = getMeshDS();
6081 TIDSortedElemSet anElems, aNodes, anAffected;
6082 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6083 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6084 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6086 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6088 // Update Python script
6089 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6090 << &theNodesNot << ", " << &theAffectedElems << " )";
6092 declareMeshModified( /*isReComputeSafe=*/false );
6095 SMESH_CATCH( SMESH::throwCorbaException );
6099 //================================================================================
6101 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6102 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6103 \param theElems - list of groups of elements (edges or faces) to be replicated
6104 \param theNodesNot - list of groups of nodes not to replicated
6105 \param theAffectedElems - group of elements to which the replicated nodes
6106 should be associated to.
6107 * \return a new group with newly created elements
6108 * \sa DoubleNodeElemGroups()
6110 //================================================================================
6112 SMESH::SMESH_Group_ptr
6113 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6114 const SMESH::ListOfGroups& theNodesNot,
6115 const SMESH::ListOfGroups& theAffectedElems)
6116 throw (SALOME::SALOME_Exception)
6119 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6123 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6124 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6126 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6128 << theNodesNot << ", "
6129 << theAffectedElems << " )";
6131 return elemGroup._retn();
6134 //================================================================================
6136 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6137 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6138 \param theElems - list of groups of elements (edges or faces) to be replicated
6139 \param theNodesNot - list of groups of nodes not to replicated
6140 \param theAffectedElems - group of elements to which the replicated nodes
6141 should be associated to.
6142 * \return a new group with newly created elements
6143 * \sa DoubleNodeElemGroups()
6145 //================================================================================
6147 SMESH::ListOfGroups*
6148 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6149 const SMESH::ListOfGroups& theNodesNot,
6150 const SMESH::ListOfGroups& theAffectedElems,
6151 CORBA::Boolean theElemGroupNeeded,
6152 CORBA::Boolean theNodeGroupNeeded)
6153 throw (SALOME::SALOME_Exception)
6156 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6157 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6158 aTwoGroups->length( 2 );
6163 SMESHDS_Mesh* aMeshDS = getMeshDS();
6164 TIDSortedElemSet anElems, aNodes, anAffected;
6165 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6166 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6167 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6169 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6171 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6176 // Create group with newly created elements
6177 CORBA::String_var elemGroupName = theElems[0]->GetName();
6178 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6179 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6181 SMESH::long_array_var anIds = GetLastCreatedElems();
6182 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6183 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6184 aNewElemGroup->Add(anIds);
6186 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6188 SMESH::long_array_var anIds = GetLastCreatedNodes();
6189 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6190 aNewNodeGroup->Add(anIds);
6194 // Update Python script
6197 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6198 else pyDump << aNewElemGroup << ", ";
6199 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6200 else pyDump << aNewNodeGroup << " ] = ";
6202 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6203 << &theNodesNot << ", "
6204 << &theAffectedElems << ", "
6205 << theElemGroupNeeded << ", "
6206 << theNodeGroupNeeded << " )";
6208 aTwoGroups[0] = aNewElemGroup._retn();
6209 aTwoGroups[1] = aNewNodeGroup._retn();
6210 return aTwoGroups._retn();
6212 SMESH_CATCH( SMESH::throwCorbaException );
6216 //================================================================================
6218 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6219 This method provided for convenience works as DoubleNodes() described above.
6220 \param theElems - list of groups of elements (edges or faces) to be replicated
6221 \param theNodesNot - list of groups of nodes not to replicated
6222 \param theShape - shape to detect affected elements (element which geometric center
6223 located on or inside shape).
6224 The replicated nodes should be associated to affected elements.
6225 \return TRUE if operation has been completed successfully, FALSE otherwise
6226 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6228 //================================================================================
6231 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6232 const SMESH::ListOfGroups& theNodesNot,
6233 GEOM::GEOM_Object_ptr theShape )
6234 throw (SALOME::SALOME_Exception)
6240 SMESHDS_Mesh* aMeshDS = getMeshDS();
6241 TIDSortedElemSet anElems, aNodes;
6242 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6243 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6245 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6246 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6248 // Update Python script
6249 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6250 << &theNodesNot << ", " << theShape << " )";
6252 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6255 SMESH_CATCH( SMESH::throwCorbaException );
6259 //================================================================================
6261 \brief Identify the elements that will be affected by node duplication (actual
6262 duplication is not performed.
6263 This method is the first step of DoubleNodeElemGroupsInRegion.
6264 \param theElems - list of groups of elements (edges or faces) to be replicated
6265 \param theNodesNot - list of groups of nodes not to replicated
6266 \param theShape - shape to detect affected elements (element which geometric center
6267 located on or inside shape).
6268 The replicated nodes should be associated to affected elements.
6269 \return groups of affected elements
6270 \sa DoubleNodeElemGroupsInRegion()
6272 //================================================================================
6273 SMESH::ListOfGroups*
6274 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6275 const SMESH::ListOfGroups& theNodesNot,
6276 GEOM::GEOM_Object_ptr theShape )
6277 throw (SALOME::SALOME_Exception)
6280 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6281 bool isEdgeGroup = false;
6282 bool isFaceGroup = false;
6283 bool isVolumeGroup = false;
6284 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6285 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6286 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6290 ::SMESH_MeshEditor aMeshEditor(myMesh);
6292 SMESHDS_Mesh* aMeshDS = getMeshDS();
6293 TIDSortedElemSet anElems, aNodes;
6294 listOfGroupToSet(theElems, aMeshDS, anElems, false);
6295 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6297 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6298 TIDSortedElemSet anAffected;
6299 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6302 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6307 int lg = anAffected.size();
6308 SMESH::long_array_var volumeIds = new SMESH::long_array;
6309 volumeIds->length(lg);
6310 SMESH::long_array_var faceIds = new SMESH::long_array;
6311 faceIds->length(lg);
6312 SMESH::long_array_var edgeIds = new SMESH::long_array;
6313 edgeIds->length(lg);
6318 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6319 for (; eIt != anAffected.end(); ++eIt)
6321 const SMDS_MeshElement* anElem = *eIt;
6324 int elemId = anElem->GetID();
6325 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6326 volumeIds[ivol++] = elemId;
6327 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6328 faceIds[iface++] = elemId;
6329 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6330 edgeIds[iedge++] = elemId;
6332 volumeIds->length(ivol);
6333 faceIds->length(iface);
6334 edgeIds->length(iedge);
6336 aNewVolumeGroup->Add(volumeIds);
6337 aNewFaceGroup->Add(faceIds);
6338 aNewEdgeGroup->Add(edgeIds);
6339 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6340 isFaceGroup = (aNewFaceGroup->Size() > 0);
6341 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6345 if (isEdgeGroup) nbGroups++;
6346 if (isFaceGroup) nbGroups++;
6347 if (isVolumeGroup) nbGroups++;
6348 aListOfGroups->length(nbGroups);
6351 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6352 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6353 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6355 // Update Python script
6358 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6359 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6360 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6362 pyDump << this << ".AffectedElemGroupsInRegion( "
6363 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6365 return aListOfGroups._retn();
6367 SMESH_CATCH( SMESH::throwCorbaException );
6371 //================================================================================
6373 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6374 The created 2D mesh elements based on nodes of free faces of boundary volumes
6375 \return TRUE if operation has been completed successfully, FALSE otherwise
6377 //================================================================================
6379 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6380 throw (SALOME::SALOME_Exception)
6385 bool aResult = getEditor().Make2DMeshFrom3D();
6387 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6389 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6392 SMESH_CATCH( SMESH::throwCorbaException );
6396 //================================================================================
6398 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6399 * The list of groups must contain at least two groups. The groups have to be disjoint:
6400 * no common element into two different groups.
6401 * The nodes of the internal faces at the boundaries of the groups are doubled.
6402 * Optionally, the internal faces are replaced by flat elements.
6403 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6404 * The flat elements are stored in groups of volumes.
6405 * These groups are named according to the position of the group in the list:
6406 * 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.
6407 * 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.
6408 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6409 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6410 * \param theDomains - list of groups of volumes
6411 * \param createJointElems - if TRUE, create the elements
6412 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6413 * the boundary between \a theDomains and the rest mesh
6414 * \return TRUE if operation has been completed successfully, FALSE otherwise
6416 //================================================================================
6419 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6420 CORBA::Boolean createJointElems,
6421 CORBA::Boolean onAllBoundaries )
6422 throw (SALOME::SALOME_Exception)
6429 SMESHDS_Mesh* aMeshDS = getMeshDS();
6431 // MESSAGE("theDomains.length = "<<theDomains.length());
6432 if ( theDomains.length() <= 1 && !onAllBoundaries )
6433 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6435 vector<TIDSortedElemSet> domains;
6436 domains.resize( theDomains.length() );
6438 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6440 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6441 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6443 // if ( aGrp->GetType() != SMESH::VOLUME )
6444 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6445 SMESH::long_array_var anIDs = aGrp->GetIDs();
6446 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6450 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6451 // TODO publish the groups of flat elements in study
6453 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6455 // Update Python script
6456 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6457 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6459 SMESH_CATCH( SMESH::throwCorbaException );
6461 myMesh_i->CreateGroupServants(); // publish created groups if any
6466 //================================================================================
6468 * \brief Double nodes on some external faces and create flat elements.
6469 * Flat elements are mainly used by some types of mechanic calculations.
6471 * Each group of the list must be constituted of faces.
6472 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6473 * @param theGroupsOfFaces - list of groups of faces
6474 * @return TRUE if operation has been completed successfully, FALSE otherwise
6476 //================================================================================
6479 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6480 throw (SALOME::SALOME_Exception)
6485 SMESHDS_Mesh* aMeshDS = getMeshDS();
6487 vector<TIDSortedElemSet> faceGroups;
6490 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6492 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6493 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6495 TIDSortedElemSet faceGroup;
6497 faceGroups.push_back(faceGroup);
6498 SMESH::long_array_var anIDs = aGrp->GetIDs();
6499 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6503 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6504 // TODO publish the groups of flat elements in study
6506 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6508 // Update Python script
6509 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6512 SMESH_CATCH( SMESH::throwCorbaException );
6516 //================================================================================
6518 * \brief Identify all the elements around a geom shape, get the faces delimiting
6521 * Build groups of volume to remove, groups of faces to replace on the skin of the
6522 * object, groups of faces to remove inside the object, (idem edges).
6523 * Build ordered list of nodes at the border of each group of faces to replace
6524 * (to be used to build a geom subshape).
6526 //================================================================================
6528 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6529 GEOM::GEOM_Object_ptr theShape,
6530 const char* groupName,
6531 const SMESH::double_array& theNodesCoords,
6532 SMESH::array_of_long_array_out GroupsOfNodes)
6533 throw (SALOME::SALOME_Exception)
6538 std::vector<std::vector<int> > aListOfListOfNodes;
6539 ::SMESH_MeshEditor aMeshEditor( myMesh );
6541 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6542 if ( !theNodeSearcher )
6543 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6545 vector<double> nodesCoords;
6546 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6548 nodesCoords.push_back( theNodesCoords[i] );
6551 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6552 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6553 nodesCoords, aListOfListOfNodes);
6555 GroupsOfNodes = new SMESH::array_of_long_array;
6556 GroupsOfNodes->length( aListOfListOfNodes.size() );
6557 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6558 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6560 vector<int>& aListOfNodes = *llIt;
6561 vector<int>::iterator lIt = aListOfNodes.begin();;
6562 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6563 aGroup.length( aListOfNodes.size() );
6564 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6565 aGroup[ j ] = (*lIt);
6567 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6570 << ", '" << groupName << "', "
6571 << theNodesCoords << " )";
6573 SMESH_CATCH( SMESH::throwCorbaException );
6576 // issue 20749 ===================================================================
6578 * \brief Creates missing boundary elements
6579 * \param elements - elements whose boundary is to be checked
6580 * \param dimension - defines type of boundary elements to create
6581 * \param groupName - a name of group to store created boundary elements in,
6582 * "" means not to create the group
6583 * \param meshName - a name of new mesh to store created boundary elements in,
6584 * "" means not to create the new mesh
6585 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6586 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6587 * boundary elements will be copied into the new mesh
6588 * \param group - returns the create group, if any
6589 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6591 // ================================================================================
6593 SMESH::SMESH_Mesh_ptr
6594 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6595 SMESH::Bnd_Dimension dim,
6596 const char* groupName,
6597 const char* meshName,
6598 CORBA::Boolean toCopyElements,
6599 CORBA::Boolean toCopyExistingBondary,
6600 SMESH::SMESH_Group_out group)
6601 throw (SALOME::SALOME_Exception)
6606 if ( dim > SMESH::BND_1DFROM2D )
6607 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6609 SMESHDS_Mesh* aMeshDS = getMeshDS();
6611 SMESH::SMESH_Mesh_var mesh_var;
6612 SMESH::SMESH_Group_var group_var;
6616 TIDSortedElemSet elements;
6617 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6618 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6622 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6623 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6625 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6627 // group of new boundary elements
6628 SMESH_Group* smesh_group = 0;
6629 if ( strlen(groupName) )
6631 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6632 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6633 smesh_group = group_i->GetSmeshGroup();
6637 getEditor().MakeBoundaryMesh( elements,
6638 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6642 toCopyExistingBondary);
6645 smesh_mesh->GetMeshDS()->Modified();
6648 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6650 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6651 if ( mesh_var->_is_nil() )
6652 pyDump << myMesh_i->_this() << ", ";
6654 pyDump << mesh_var << ", ";
6655 if ( group_var->_is_nil() )
6656 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6658 pyDump << group_var << " = ";
6659 pyDump << this << ".MakeBoundaryMesh( "
6661 << "SMESH." << dimName[int(dim)] << ", "
6662 << "'" << groupName << "', "
6663 << "'" << meshName<< "', "
6664 << toCopyElements << ", "
6665 << toCopyExistingBondary << ")";
6667 group = group_var._retn();
6668 return mesh_var._retn();
6670 SMESH_CATCH( SMESH::throwCorbaException );
6671 return SMESH::SMESH_Mesh::_nil();
6674 //================================================================================
6676 * \brief Creates missing boundary elements
6677 * \param dimension - defines type of boundary elements to create
6678 * \param groupName - a name of group to store all boundary elements in,
6679 * "" means not to create the group
6680 * \param meshName - a name of a new mesh, which is a copy of the initial
6681 * mesh + created boundary elements; "" means not to create the new mesh
6682 * \param toCopyAll - if true, the whole initial mesh will be copied into
6683 * the new mesh else only boundary elements will be copied into the new mesh
6684 * \param groups - optional groups of elements to make boundary around
6685 * \param mesh - returns the mesh where elements were added to
6686 * \param group - returns the created group, if any
6687 * \retval long - number of added boundary elements
6689 //================================================================================
6691 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6692 const char* groupName,
6693 const char* meshName,
6694 CORBA::Boolean toCopyAll,
6695 const SMESH::ListOfIDSources& groups,
6696 SMESH::SMESH_Mesh_out mesh,
6697 SMESH::SMESH_Group_out group)
6698 throw (SALOME::SALOME_Exception)
6703 if ( dim > SMESH::BND_1DFROM2D )
6704 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6706 // separate groups belonging to this and other mesh
6707 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6708 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6709 groupsOfThisMesh ->length( groups.length() );
6710 groupsOfOtherMesh->length( groups.length() );
6711 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6712 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
6714 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6715 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6716 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6718 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6719 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6720 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
6722 groupsOfThisMesh->length( nbGroups );
6723 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6728 if ( nbGroupsOfOtherMesh > 0 )
6730 // process groups belonging to another mesh
6731 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6732 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6733 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6734 groupsOfOtherMesh, mesh, group );
6737 SMESH::SMESH_Mesh_var mesh_var;
6738 SMESH::SMESH_Group_var group_var;
6741 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6742 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6746 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6748 /*toCopyGroups=*/false,
6749 /*toKeepIDs=*/true);
6751 mesh_var = makeMesh(meshName);
6753 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6754 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6757 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6758 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6760 // group of boundary elements
6761 SMESH_Group* smesh_group = 0;
6762 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6763 if ( strlen(groupName) )
6765 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6766 group_var = mesh_i->CreateGroup( groupType, groupName );
6767 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6768 smesh_group = group_i->GetSmeshGroup();
6771 TIDSortedElemSet elements;
6773 if ( groups.length() > 0 )
6775 for ( int i = 0; i < nbGroups; ++i )
6778 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6780 SMESH::Bnd_Dimension bdim =
6781 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6782 nbAdded += getEditor().MakeBoundaryMesh( elements,
6783 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6786 /*toCopyElements=*/false,
6787 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6788 /*toAddExistingBondary=*/true,
6789 /*aroundElements=*/true);
6795 nbAdded += getEditor().MakeBoundaryMesh( elements,
6796 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6799 /*toCopyElements=*/false,
6800 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6801 /*toAddExistingBondary=*/true);
6803 tgtMesh->GetMeshDS()->Modified();
6805 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6807 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6808 pyDump << "nbAdded, ";
6809 if ( mesh_var->_is_nil() )
6810 pyDump << myMesh_i->_this() << ", ";
6812 pyDump << mesh_var << ", ";
6813 if ( group_var->_is_nil() )
6814 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6816 pyDump << group_var << " = ";
6817 pyDump << this << ".MakeBoundaryElements( "
6818 << "SMESH." << dimName[int(dim)] << ", "
6819 << "'" << groupName << "', "
6820 << "'" << meshName<< "', "
6821 << toCopyAll << ", "
6824 mesh = mesh_var._retn();
6825 group = group_var._retn();
6828 SMESH_CATCH( SMESH::throwCorbaException );