1 // Copyright (C) 2007-2015 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 occured
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 (int i=0; i<IDs.length(); i++) {
289 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
291 aMap.insert( aMap.end(), elem );
294 for (int 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(int 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(int 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 ) == 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 futher mesh re-compute.
471 * \param [in] isReComputeSafe - true if the modification does not influence
472 * futher 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 par a 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 occured 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 (int 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 (int 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)
863 for ( int i = 0; i < seq.size(); i++ )
864 IdList.push_back( seq[i] );
866 int nbNodesBefore = myMesh->NbNodes();
867 getEditor().Remove( IdList, true );
868 int nbNodesAfter = myMesh->NbNodes();
870 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
871 return nbNodesBefore - nbNodesAfter;
873 SMESH_CATCH( SMESH::throwCorbaException );
877 //=============================================================================
881 //=============================================================================
883 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
884 throw (SALOME::SALOME_Exception)
889 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
891 // Update Python script
892 TPythonDump() << "nodeID = " << this << ".AddNode( "
893 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
895 declareMeshModified( /*isReComputeSafe=*/false );
898 SMESH_CATCH( SMESH::throwCorbaException );
902 //=============================================================================
904 * Create 0D element on the given node.
906 //=============================================================================
908 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
909 throw (SALOME::SALOME_Exception)
914 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
915 SMDS_MeshElement* elem = getMeshDS()->Add0DElement(aNode);
917 // Update Python script
918 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
920 declareMeshModified( /*isReComputeSafe=*/false );
922 return elem ? elem->GetID() : 0;
924 SMESH_CATCH( SMESH::throwCorbaException );
928 //=============================================================================
930 * Create a ball element on the given node.
932 //=============================================================================
934 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
935 throw (SALOME::SALOME_Exception)
940 if ( diameter < std::numeric_limits<double>::min() )
941 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
943 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
944 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
946 // Update Python script
947 TPythonDump() << "ballElem = "
948 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
950 declareMeshModified( /*isReComputeSafe=*/false );
951 return elem ? elem->GetID() : 0;
953 SMESH_CATCH( SMESH::throwCorbaException );
957 //=============================================================================
959 * Create an edge, either linear and quadratic (this is determed
960 * by number of given nodes, two or three)
962 //=============================================================================
964 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
965 throw (SALOME::SALOME_Exception)
970 int NbNodes = IDsOfNodes.length();
971 SMDS_MeshElement* elem = 0;
974 CORBA::Long index1 = IDsOfNodes[0];
975 CORBA::Long index2 = IDsOfNodes[1];
976 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
977 getMeshDS()->FindNode(index2));
979 // Update Python script
980 TPythonDump() << "edge = " << this << ".AddEdge([ "
981 << index1 << ", " << index2 <<" ])";
984 CORBA::Long n1 = IDsOfNodes[0];
985 CORBA::Long n2 = IDsOfNodes[1];
986 CORBA::Long n12 = IDsOfNodes[2];
987 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
988 getMeshDS()->FindNode(n2),
989 getMeshDS()->FindNode(n12));
990 // Update Python script
991 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
992 <<n1<<", "<<n2<<", "<<n12<<" ])";
995 declareMeshModified( /*isReComputeSafe=*/false );
996 return elem ? elem->GetID() : 0;
998 SMESH_CATCH( SMESH::throwCorbaException );
1002 //=============================================================================
1006 //=============================================================================
1008 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1009 throw (SALOME::SALOME_Exception)
1014 int NbNodes = IDsOfNodes.length();
1020 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1021 for (int i = 0; i < NbNodes; i++)
1022 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1024 SMDS_MeshElement* elem = 0;
1026 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1027 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1028 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1029 nodes[4], nodes[5]); break;
1030 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1031 nodes[4], nodes[5], nodes[6]); break;
1032 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1033 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1034 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1035 nodes[4], nodes[5], nodes[6], nodes[7],
1037 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1040 // Update Python script
1041 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1043 declareMeshModified( /*isReComputeSafe=*/false );
1045 return elem ? elem->GetID() : 0;
1047 SMESH_CATCH( SMESH::throwCorbaException );
1051 //=============================================================================
1055 //=============================================================================
1057 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1058 throw (SALOME::SALOME_Exception)
1063 int NbNodes = IDsOfNodes.length();
1064 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1065 for (int i = 0; i < NbNodes; i++)
1066 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1069 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1071 // Update Python script
1072 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1074 declareMeshModified( /*isReComputeSafe=*/false );
1075 return elem ? elem->GetID() : 0;
1077 SMESH_CATCH( SMESH::throwCorbaException );
1081 //=============================================================================
1083 * AddQuadPolygonalFace
1085 //=============================================================================
1087 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1088 throw (SALOME::SALOME_Exception)
1093 int NbNodes = IDsOfNodes.length();
1094 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1095 for (int i = 0; i < NbNodes; i++)
1096 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1098 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1100 // Update Python script
1101 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1103 declareMeshModified( /*isReComputeSafe=*/false );
1104 return elem ? elem->GetID() : 0;
1106 SMESH_CATCH( SMESH::throwCorbaException );
1110 //=============================================================================
1112 * Create volume, either linear and quadratic (this is determed
1113 * by number of given nodes)
1115 //=============================================================================
1117 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1118 throw (SALOME::SALOME_Exception)
1123 int NbNodes = IDsOfNodes.length();
1124 vector< const SMDS_MeshNode*> n(NbNodes);
1125 for(int i=0;i<NbNodes;i++)
1126 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1128 SMDS_MeshElement* elem = 0;
1131 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1132 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1133 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1134 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1135 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1136 n[6],n[7],n[8],n[9]);
1138 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1139 n[6],n[7],n[8],n[9],n[10],n[11]);
1141 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1142 n[7],n[8],n[9],n[10],n[11],n[12]);
1144 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1145 n[9],n[10],n[11],n[12],n[13],n[14]);
1147 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1148 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1149 n[15],n[16],n[17],n[18],n[19]);
1151 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1152 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1153 n[15],n[16],n[17],n[18],n[19],
1154 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1158 // Update Python script
1159 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1161 declareMeshModified( /*isReComputeSafe=*/false );
1162 return elem ? elem->GetID() : 0;
1164 SMESH_CATCH( SMESH::throwCorbaException );
1168 //=============================================================================
1170 * AddPolyhedralVolume
1172 //=============================================================================
1173 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1174 const SMESH::long_array & Quantities)
1175 throw (SALOME::SALOME_Exception)
1180 int NbNodes = IDsOfNodes.length();
1181 std::vector<const SMDS_MeshNode*> n (NbNodes);
1182 for (int i = 0; i < NbNodes; i++)
1184 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1185 if (!aNode) return 0;
1189 int NbFaces = Quantities.length();
1190 std::vector<int> q (NbFaces);
1191 for (int j = 0; j < NbFaces; j++)
1192 q[j] = Quantities[j];
1194 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1196 // Update Python script
1197 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1198 << IDsOfNodes << ", " << Quantities << " )";
1200 declareMeshModified( /*isReComputeSafe=*/false );
1201 return elem ? elem->GetID() : 0;
1203 SMESH_CATCH( SMESH::throwCorbaException );
1207 //=============================================================================
1209 * AddPolyhedralVolumeByFaces
1211 //=============================================================================
1213 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1214 throw (SALOME::SALOME_Exception)
1219 int NbFaces = IdsOfFaces.length();
1220 std::vector<const SMDS_MeshNode*> poly_nodes;
1221 std::vector<int> quantities (NbFaces);
1223 for (int i = 0; i < NbFaces; i++) {
1224 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1225 quantities[i] = aFace->NbNodes();
1227 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1228 while (It->more()) {
1229 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1233 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1235 // Update Python script
1236 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1237 << IdsOfFaces << " )";
1239 declareMeshModified( /*isReComputeSafe=*/false );
1240 return elem ? elem->GetID() : 0;
1242 SMESH_CATCH( SMESH::throwCorbaException );
1246 //=============================================================================
1248 // \brief Create 0D elements on all nodes of the given object except those
1249 // nodes on which a 0D element already exists.
1250 // \param theObject object on whose nodes 0D elements will be created.
1251 // \param theGroupName optional name of a group to add 0D elements created
1252 // and/or found on nodes of \a theObject.
1253 // \return an object (a new group or a temporary SMESH_IDSource) holding
1254 // ids of new and/or found 0D elements.
1256 //=============================================================================
1258 SMESH::SMESH_IDSource_ptr
1259 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1260 const char* theGroupName)
1261 throw (SALOME::SALOME_Exception)
1266 SMESH::SMESH_IDSource_var result;
1269 TIDSortedElemSet elements, elems0D;
1270 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1271 getEditor().Create0DElementsOnAllNodes( elements, elems0D );
1273 SMESH::long_array_var newElems = new SMESH::long_array;
1274 newElems->length( elems0D.size() );
1275 TIDSortedElemSet::iterator eIt = elems0D.begin();
1276 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1277 newElems[ i ] = (*eIt)->GetID();
1279 SMESH::SMESH_GroupBase_var groupToFill;
1280 if ( theGroupName && strlen( theGroupName ))
1282 // Get existing group named theGroupName
1283 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1284 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1285 SMESH::SMESH_GroupBase_var group = groups[i];
1286 if ( !group->_is_nil() ) {
1287 CORBA::String_var name = group->GetName();
1288 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1289 groupToFill = group;
1294 if ( groupToFill->_is_nil() )
1295 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1296 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1297 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1300 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1302 group_i->Add( newElems );
1303 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1304 pyDump << groupToFill;
1308 result = MakeIDSource( newElems, SMESH::ELEM0D );
1309 pyDump << "elem0DIDs";
1312 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1313 << theObject << ", '" << theGroupName << "' )";
1315 return result._retn();
1317 SMESH_CATCH( SMESH::throwCorbaException );
1321 //=============================================================================
1323 * \brief Bind a node to a vertex
1324 * \param NodeID - node ID
1325 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1326 * \retval boolean - false if NodeID or VertexID is invalid
1328 //=============================================================================
1330 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1331 throw (SALOME::SALOME_Exception)
1335 SMESHDS_Mesh * mesh = getMeshDS();
1336 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1338 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1340 if ( mesh->MaxShapeIndex() < VertexID )
1341 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1343 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1344 if ( shape.ShapeType() != TopAbs_VERTEX )
1345 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1347 mesh->SetNodeOnVertex( node, VertexID );
1349 myMesh->SetIsModified( true );
1351 SMESH_CATCH( SMESH::throwCorbaException );
1354 //=============================================================================
1356 * \brief Store node position on an edge
1357 * \param NodeID - node ID
1358 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1359 * \param paramOnEdge - parameter on edge where the node is located
1360 * \retval boolean - false if any parameter is invalid
1362 //=============================================================================
1364 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1365 CORBA::Double paramOnEdge)
1366 throw (SALOME::SALOME_Exception)
1370 SMESHDS_Mesh * mesh = getMeshDS();
1371 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1373 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1375 if ( mesh->MaxShapeIndex() < EdgeID )
1376 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1378 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1379 if ( shape.ShapeType() != TopAbs_EDGE )
1380 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1383 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1384 if ( paramOnEdge < f || paramOnEdge > l )
1385 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1387 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1389 myMesh->SetIsModified( true );
1391 SMESH_CATCH( SMESH::throwCorbaException );
1394 //=============================================================================
1396 * \brief Store node position on a face
1397 * \param NodeID - node ID
1398 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1399 * \param u - U parameter on face where the node is located
1400 * \param v - V parameter on face where the node is located
1401 * \retval boolean - false if any parameter is invalid
1403 //=============================================================================
1405 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1406 CORBA::Double u, CORBA::Double v)
1407 throw (SALOME::SALOME_Exception)
1410 SMESHDS_Mesh * mesh = getMeshDS();
1411 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1413 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1415 if ( mesh->MaxShapeIndex() < FaceID )
1416 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1418 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1419 if ( shape.ShapeType() != TopAbs_FACE )
1420 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1422 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1423 bool isOut = ( u < surf.FirstUParameter() ||
1424 u > surf.LastUParameter() ||
1425 v < surf.FirstVParameter() ||
1426 v > surf.LastVParameter() );
1430 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1431 << " u( " << surf.FirstUParameter()
1432 << "," << surf.LastUParameter()
1433 << ") v( " << surf.FirstVParameter()
1434 << "," << surf.LastVParameter() << ")" );
1436 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1439 mesh->SetNodeOnFace( node, FaceID, u, v );
1440 myMesh->SetIsModified( true );
1442 SMESH_CATCH( SMESH::throwCorbaException );
1445 //=============================================================================
1447 * \brief Bind a node to a solid
1448 * \param NodeID - node ID
1449 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1450 * \retval boolean - false if NodeID or SolidID is invalid
1452 //=============================================================================
1454 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1455 throw (SALOME::SALOME_Exception)
1458 SMESHDS_Mesh * mesh = getMeshDS();
1459 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1461 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1463 if ( mesh->MaxShapeIndex() < SolidID )
1464 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1466 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1467 if ( shape.ShapeType() != TopAbs_SOLID &&
1468 shape.ShapeType() != TopAbs_SHELL)
1469 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1471 mesh->SetNodeInVolume( node, SolidID );
1473 SMESH_CATCH( SMESH::throwCorbaException );
1476 //=============================================================================
1478 * \brief Bind an element to a shape
1479 * \param ElementID - element ID
1480 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1482 //=============================================================================
1484 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1485 CORBA::Long ShapeID)
1486 throw (SALOME::SALOME_Exception)
1489 SMESHDS_Mesh * mesh = getMeshDS();
1490 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1492 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1494 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1495 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1497 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1498 if ( shape.ShapeType() != TopAbs_EDGE &&
1499 shape.ShapeType() != TopAbs_FACE &&
1500 shape.ShapeType() != TopAbs_SOLID &&
1501 shape.ShapeType() != TopAbs_SHELL )
1502 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1504 mesh->SetMeshElementOnShape( elem, ShapeID );
1506 myMesh->SetIsModified( true );
1508 SMESH_CATCH( SMESH::throwCorbaException );
1511 //=============================================================================
1515 //=============================================================================
1517 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1518 CORBA::Long NodeID2)
1519 throw (SALOME::SALOME_Exception)
1524 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1525 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1529 // Update Python script
1530 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1531 << NodeID1 << ", " << NodeID2 << " )";
1533 int ret = getEditor().InverseDiag ( n1, n2 );
1535 declareMeshModified( /*isReComputeSafe=*/false );
1538 SMESH_CATCH( SMESH::throwCorbaException );
1542 //=============================================================================
1546 //=============================================================================
1548 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1549 CORBA::Long NodeID2)
1550 throw (SALOME::SALOME_Exception)
1555 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1556 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1560 // Update Python script
1561 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1562 << NodeID1 << ", " << NodeID2 << " )";
1565 bool stat = getEditor().DeleteDiag ( n1, n2 );
1567 declareMeshModified( /*isReComputeSafe=*/!stat );
1571 SMESH_CATCH( SMESH::throwCorbaException );
1575 //=============================================================================
1579 //=============================================================================
1581 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1582 throw (SALOME::SALOME_Exception)
1587 for (int i = 0; i < IDsOfElements.length(); i++)
1589 CORBA::Long index = IDsOfElements[i];
1590 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1592 getEditor().Reorient( elem );
1594 // Update Python script
1595 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1597 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1600 SMESH_CATCH( SMESH::throwCorbaException );
1604 //=============================================================================
1608 //=============================================================================
1610 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1611 throw (SALOME::SALOME_Exception)
1616 TPythonDump aTPythonDump; // suppress dump in Reorient()
1618 prepareIdSource( theObject );
1620 SMESH::long_array_var anElementsId = theObject->GetIDs();
1621 CORBA::Boolean isDone = Reorient(anElementsId);
1623 // Update Python script
1624 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1626 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1629 SMESH_CATCH( SMESH::throwCorbaException );
1633 //=======================================================================
1634 //function : Reorient2D
1635 //purpose : Reorient faces contained in \a the2Dgroup.
1636 // the2Dgroup - the mesh or its part to reorient
1637 // theDirection - desired direction of normal of \a theFace
1638 // theFace - ID of face whose orientation is checked.
1639 // It can be < 1 then \a thePoint is used to find a face.
1640 // thePoint - is used to find a face if \a theFace < 1.
1641 // return number of reoriented elements.
1642 //=======================================================================
1644 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1645 const SMESH::DirStruct& theDirection,
1646 CORBA::Long theFace,
1647 const SMESH::PointStruct& thePoint)
1648 throw (SALOME::SALOME_Exception)
1651 initData(/*deleteSearchers=*/false);
1653 TIDSortedElemSet elements;
1654 IDSource_Error error;
1655 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1656 if ( error == IDSource_EMPTY )
1658 if ( error == IDSource_INVALID )
1659 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1662 const SMDS_MeshElement* face = 0;
1665 face = getMeshDS()->FindElement( theFace );
1667 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1668 if ( face->GetType() != SMDSAbs_Face )
1669 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1673 // create theElementSearcher if needed
1674 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1675 if ( !theElementSearcher )
1677 if ( elements.empty() ) // search in the whole mesh
1679 if ( myMesh->NbFaces() == 0 )
1680 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1682 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1686 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1687 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1689 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1693 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1694 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1697 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1698 if ( !elements.empty() && !elements.count( face ))
1699 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1702 const SMESH::PointStruct * P = &theDirection.PS;
1703 gp_Vec dirVec( P->x, P->y, P->z );
1704 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1705 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1707 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1710 declareMeshModified( /*isReComputeSafe=*/false );
1712 TPythonDump() << this << ".Reorient2D( "
1713 << the2Dgroup << ", "
1714 << theDirection << ", "
1716 << thePoint << " )";
1720 SMESH_CATCH( SMESH::throwCorbaException );
1724 //=======================================================================
1725 //function : Reorient2DBy3D
1726 //purpose : Reorient faces basing on orientation of adjacent volumes.
1727 //=======================================================================
1729 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1730 SMESH::SMESH_IDSource_ptr volumeGroup,
1731 CORBA::Boolean outsideNormal)
1732 throw (SALOME::SALOME_Exception)
1737 TIDSortedElemSet volumes;
1738 IDSource_Error volsError;
1739 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1742 for ( size_t i = 0; i < faceGroups.length(); ++i )
1744 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1746 TIDSortedElemSet faces;
1747 IDSource_Error error;
1748 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1749 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1750 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1751 if ( error == IDSource_OK && volsError != IDSource_OK )
1752 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1754 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1756 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1761 declareMeshModified( /*isReComputeSafe=*/false );
1763 TPythonDump() << this << ".Reorient2DBy3D( "
1764 << faceGroups << ", "
1765 << volumeGroup << ", "
1766 << outsideNormal << " )";
1770 SMESH_CATCH( SMESH::throwCorbaException );
1774 //=============================================================================
1776 * \brief Fuse neighbour triangles into quadrangles.
1778 //=============================================================================
1780 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1781 SMESH::NumericalFunctor_ptr Criterion,
1782 CORBA::Double MaxAngle)
1783 throw (SALOME::SALOME_Exception)
1788 SMESHDS_Mesh* aMesh = getMeshDS();
1789 TIDSortedElemSet faces,copyFaces;
1790 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1791 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1792 TIDSortedElemSet* workElements = & faces;
1794 if ( myIsPreviewMode ) {
1795 SMDSAbs_ElementType select = SMDSAbs_Face;
1796 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1797 workElements = & copyFaces;
1800 SMESH::NumericalFunctor_i* aNumericalFunctor =
1801 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1802 SMESH::Controls::NumericalFunctorPtr aCrit;
1803 if ( !aNumericalFunctor )
1804 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1806 aCrit = aNumericalFunctor->GetNumericalFunctor();
1808 if ( !myIsPreviewMode ) {
1809 // Update Python script
1810 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1811 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1814 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1816 declareMeshModified( /*isReComputeSafe=*/!stat );
1819 SMESH_CATCH( SMESH::throwCorbaException );
1823 //=============================================================================
1825 * \brief Fuse neighbour triangles into quadrangles.
1827 //=============================================================================
1829 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1830 SMESH::NumericalFunctor_ptr Criterion,
1831 CORBA::Double MaxAngle)
1832 throw (SALOME::SALOME_Exception)
1837 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1839 prepareIdSource( theObject );
1840 SMESH::long_array_var anElementsId = theObject->GetIDs();
1841 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1843 if ( !myIsPreviewMode ) {
1844 SMESH::NumericalFunctor_i* aNumericalFunctor =
1845 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1847 // Update Python script
1848 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1849 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1854 SMESH_CATCH( SMESH::throwCorbaException );
1858 //=============================================================================
1860 * \brief Split quadrangles into triangles.
1862 //=============================================================================
1864 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1865 SMESH::NumericalFunctor_ptr Criterion)
1866 throw (SALOME::SALOME_Exception)
1871 SMESHDS_Mesh* aMesh = getMeshDS();
1872 TIDSortedElemSet faces;
1873 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1875 SMESH::NumericalFunctor_i* aNumericalFunctor =
1876 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1877 SMESH::Controls::NumericalFunctorPtr aCrit;
1878 if ( !aNumericalFunctor )
1879 aCrit.reset( new SMESH::Controls::AspectRatio() );
1881 aCrit = aNumericalFunctor->GetNumericalFunctor();
1884 // Update Python script
1885 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1887 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1889 declareMeshModified( /*isReComputeSafe=*/false );
1892 SMESH_CATCH( SMESH::throwCorbaException );
1896 //=============================================================================
1898 * \brief Split quadrangles into triangles.
1900 //=============================================================================
1902 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1903 SMESH::NumericalFunctor_ptr Criterion)
1904 throw (SALOME::SALOME_Exception)
1909 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1911 prepareIdSource( theObject );
1912 SMESH::long_array_var anElementsId = theObject->GetIDs();
1913 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1915 SMESH::NumericalFunctor_i* aNumericalFunctor =
1916 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1918 // Update Python script
1919 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1921 declareMeshModified( /*isReComputeSafe=*/false );
1924 SMESH_CATCH( SMESH::throwCorbaException );
1928 //================================================================================
1930 * \brief Split each of quadrangles into 4 triangles.
1931 * \param [in] theObject - theQuads Container of quadrangles to split.
1933 //================================================================================
1935 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1936 throw (SALOME::SALOME_Exception)
1941 TIDSortedElemSet faces;
1942 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1944 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1946 getEditor().QuadTo4Tri( faces );
1947 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1949 SMESH_CATCH( SMESH::throwCorbaException );
1952 //=============================================================================
1954 * \brief Split quadrangles into triangles.
1956 //=============================================================================
1958 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1959 CORBA::Boolean Diag13)
1960 throw (SALOME::SALOME_Exception)
1965 SMESHDS_Mesh* aMesh = getMeshDS();
1966 TIDSortedElemSet faces;
1967 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1969 // Update Python script
1970 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1971 << IDsOfElements << ", " << Diag13 << " )";
1973 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1975 declareMeshModified( /*isReComputeSafe=*/ !stat );
1978 SMESH_CATCH( SMESH::throwCorbaException );
1982 //=============================================================================
1984 * \brief Split quadrangles into triangles.
1986 //=============================================================================
1988 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1989 CORBA::Boolean Diag13)
1990 throw (SALOME::SALOME_Exception)
1995 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
1997 prepareIdSource( theObject );
1998 SMESH::long_array_var anElementsId = theObject->GetIDs();
1999 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2001 // Update Python script
2002 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2003 << theObject << ", " << Diag13 << " )";
2005 declareMeshModified( /*isReComputeSafe=*/!isDone );
2008 SMESH_CATCH( SMESH::throwCorbaException );
2013 //=============================================================================
2015 * Find better splitting of the given quadrangle.
2016 * \param IDOfQuad ID of the quadrangle to be splitted.
2017 * \param Criterion A criterion to choose a diagonal for splitting.
2018 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2019 * diagonal is better, 0 if error occurs.
2021 //=============================================================================
2023 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2024 SMESH::NumericalFunctor_ptr Criterion)
2025 throw (SALOME::SALOME_Exception)
2030 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2031 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2033 SMESH::NumericalFunctor_i* aNumericalFunctor =
2034 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2035 SMESH::Controls::NumericalFunctorPtr aCrit;
2036 if (aNumericalFunctor)
2037 aCrit = aNumericalFunctor->GetNumericalFunctor();
2039 aCrit.reset(new SMESH::Controls::AspectRatio());
2041 int id = getEditor().BestSplit(quad, aCrit);
2042 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2046 SMESH_CATCH( SMESH::throwCorbaException );
2050 //================================================================================
2052 * \brief Split volumic elements into tetrahedrons
2054 //================================================================================
2056 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2057 CORBA::Short methodFlags)
2058 throw (SALOME::SALOME_Exception)
2063 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2064 const int noneFacet = -1;
2065 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2066 while( volIt->more() )
2067 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2069 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2070 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2072 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2073 << elems << ", " << methodFlags << " )";
2075 SMESH_CATCH( SMESH::throwCorbaException );
2078 //================================================================================
2080 * \brief Split hexahedra into triangular prisms
2081 * \param elems - elements to split
2082 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2083 * to split into triangles
2084 * \param methodFlags - flags passing splitting method:
2085 * 1 - split the hexahedron into 2 prisms
2086 * 2 - split the hexahedron into 4 prisms
2088 //================================================================================
2090 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2091 const SMESH::PointStruct & startHexPoint,
2092 const SMESH::DirStruct& facetToSplitNormal,
2093 CORBA::Short methodFlags,
2094 CORBA::Boolean allDomains)
2095 throw (SALOME::SALOME_Exception)
2099 prepareIdSource( elems );
2101 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2104 gp_Dir( facetToSplitNormal.PS.x,
2105 facetToSplitNormal.PS.y,
2106 facetToSplitNormal.PS.z ));
2107 TIDSortedElemSet elemSet;
2108 SMESH::long_array_var anElementsId = elems->GetIDs();
2109 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2110 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2112 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2113 while ( !elemSet.empty() )
2115 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2119 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2120 for ( ; ef != elemFacets.end(); ++ef )
2121 elemSet.erase( ef->first );
2124 if ( methodFlags == 2 )
2125 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2127 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2129 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2130 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2132 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2134 << startHexPoint << ", "
2135 << facetToSplitNormal<< ", "
2136 << methodFlags<< ", "
2137 << allDomains << " )";
2139 SMESH_CATCH( SMESH::throwCorbaException );
2142 //================================================================================
2144 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2145 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2146 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2147 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2148 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2149 * will be split in order to keep the mesh conformal.
2150 * \param elems - elements to split
2152 //================================================================================
2154 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2155 throw (SALOME::SALOME_Exception)
2160 TIDSortedElemSet elemSet;
2161 for ( size_t i = 0; i < theElems.length(); ++i )
2163 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2164 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2165 if ( mesh->GetId() != myMesh_i->GetId() )
2166 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2168 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2170 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2172 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2174 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2175 << theElems << " )";
2177 SMESH_CATCH( SMESH::throwCorbaException );
2180 //=======================================================================
2183 //=======================================================================
2186 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2187 const SMESH::long_array & IDsOfFixedNodes,
2188 CORBA::Long MaxNbOfIterations,
2189 CORBA::Double MaxAspectRatio,
2190 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2191 throw (SALOME::SALOME_Exception)
2193 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2194 MaxAspectRatio, Method, false );
2198 //=======================================================================
2199 //function : SmoothParametric
2201 //=======================================================================
2204 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2205 const SMESH::long_array & IDsOfFixedNodes,
2206 CORBA::Long MaxNbOfIterations,
2207 CORBA::Double MaxAspectRatio,
2208 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2209 throw (SALOME::SALOME_Exception)
2211 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2212 MaxAspectRatio, Method, true );
2216 //=======================================================================
2217 //function : SmoothObject
2219 //=======================================================================
2222 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2223 const SMESH::long_array & IDsOfFixedNodes,
2224 CORBA::Long MaxNbOfIterations,
2225 CORBA::Double MaxAspectRatio,
2226 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2227 throw (SALOME::SALOME_Exception)
2229 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2230 MaxAspectRatio, Method, false);
2234 //=======================================================================
2235 //function : SmoothParametricObject
2237 //=======================================================================
2240 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2241 const SMESH::long_array & IDsOfFixedNodes,
2242 CORBA::Long MaxNbOfIterations,
2243 CORBA::Double MaxAspectRatio,
2244 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2245 throw (SALOME::SALOME_Exception)
2247 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2248 MaxAspectRatio, Method, true);
2252 //=============================================================================
2256 //=============================================================================
2259 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2260 const SMESH::long_array & IDsOfFixedNodes,
2261 CORBA::Long MaxNbOfIterations,
2262 CORBA::Double MaxAspectRatio,
2263 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2265 throw (SALOME::SALOME_Exception)
2270 SMESHDS_Mesh* aMesh = getMeshDS();
2272 TIDSortedElemSet elements;
2273 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2275 set<const SMDS_MeshNode*> fixedNodes;
2276 for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
2277 CORBA::Long index = IDsOfFixedNodes[i];
2278 const SMDS_MeshNode * node = aMesh->FindNode(index);
2280 fixedNodes.insert( node );
2282 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2283 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2284 method = ::SMESH_MeshEditor::CENTROIDAL;
2286 getEditor().Smooth(elements, fixedNodes, method,
2287 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2289 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2291 // Update Python script
2292 TPythonDump() << "isDone = " << this << "."
2293 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2294 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2295 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2296 << "SMESH.SMESH_MeshEditor."
2297 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2298 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2302 SMESH_CATCH( SMESH::throwCorbaException );
2306 //=============================================================================
2310 //=============================================================================
2313 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2314 const SMESH::long_array & IDsOfFixedNodes,
2315 CORBA::Long MaxNbOfIterations,
2316 CORBA::Double MaxAspectRatio,
2317 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2319 throw (SALOME::SALOME_Exception)
2324 TPythonDump aTPythonDump; // suppress dump in smooth()
2326 prepareIdSource( theObject );
2327 SMESH::long_array_var anElementsId = theObject->GetIDs();
2328 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2329 MaxAspectRatio, Method, IsParametric);
2331 // Update Python script
2332 aTPythonDump << "isDone = " << this << "."
2333 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2334 << theObject << ", " << IDsOfFixedNodes << ", "
2335 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2336 << "SMESH.SMESH_MeshEditor."
2337 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2338 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2342 SMESH_CATCH( SMESH::throwCorbaException );
2346 //=============================================================================
2350 //=============================================================================
2352 void SMESH_MeshEditor_i::RenumberNodes()
2353 throw (SALOME::SALOME_Exception)
2356 // Update Python script
2357 TPythonDump() << this << ".RenumberNodes()";
2359 getMeshDS()->Renumber( true );
2361 SMESH_CATCH( SMESH::throwCorbaException );
2364 //=============================================================================
2368 //=============================================================================
2370 void SMESH_MeshEditor_i::RenumberElements()
2371 throw (SALOME::SALOME_Exception)
2374 // Update Python script
2375 TPythonDump() << this << ".RenumberElements()";
2377 getMeshDS()->Renumber( false );
2379 SMESH_CATCH( SMESH::throwCorbaException );
2382 //=======================================================================
2384 * \brief Return groups by their IDs
2386 //=======================================================================
2388 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2389 throw (SALOME::SALOME_Exception)
2394 myMesh_i->CreateGroupServants();
2395 return myMesh_i->GetGroups( *groupIDs );
2397 SMESH_CATCH( SMESH::throwCorbaException );
2401 //=======================================================================
2402 //function : RotationSweepObjects
2404 //=======================================================================
2406 SMESH::ListOfGroups*
2407 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2408 const SMESH::ListOfIDSources & theEdges,
2409 const SMESH::ListOfIDSources & theFaces,
2410 const SMESH::AxisStruct & theAxis,
2411 CORBA::Double theAngleInRadians,
2412 CORBA::Long theNbOfSteps,
2413 CORBA::Double theTolerance,
2414 const bool theMakeGroups)
2415 throw (SALOME::SALOME_Exception)
2420 TIDSortedElemSet elemsNodes[2];
2421 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2422 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2423 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2425 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2426 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2427 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2428 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2430 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2431 bool makeWalls=true;
2432 if ( myIsPreviewMode )
2434 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2435 TPreviewMesh * tmpMesh = getPreviewMesh();
2436 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2437 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2438 workElements = & copyElements[0];
2439 //makeWalls = false; -- faces are needed for preview
2442 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2444 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2445 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2447 ::SMESH_MeshEditor::PGroupIDs groupIds =
2448 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2449 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2451 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2453 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2455 if ( !myIsPreviewMode )
2457 dumpGroupsList( aPythonDump, aGroups );
2458 aPythonDump << this<< ".RotationSweepObjects( "
2463 << TVar( theAngleInRadians ) << ", "
2464 << TVar( theNbOfSteps ) << ", "
2465 << TVar( theTolerance ) << ", "
2466 << theMakeGroups << " )";
2470 getPreviewMesh()->Remove( SMDSAbs_Volume );
2473 return aGroups ? aGroups : new SMESH::ListOfGroups;
2475 SMESH_CATCH( SMESH::throwCorbaException );
2479 namespace MeshEditor_I
2482 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2484 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2486 bool myIsExtrusionByNormal;
2488 static int makeFlags( CORBA::Boolean MakeGroups,
2489 CORBA::Boolean ByAverageNormal = false,
2490 CORBA::Boolean UseInputElemsOnly = false,
2491 CORBA::Long Flags = 0,
2492 CORBA::Boolean MakeBoundary = true )
2494 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2495 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2496 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2497 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2501 ExtrusionParams(const SMESH::DirStruct & theDir,
2502 CORBA::Long theNbOfSteps,
2503 CORBA::Boolean theMakeGroups):
2504 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2508 makeFlags( theMakeGroups )),
2509 myIsExtrusionByNormal( false )
2513 ExtrusionParams(const SMESH::DirStruct & theDir,
2514 CORBA::Long theNbOfSteps,
2515 CORBA::Boolean theMakeGroups,
2516 CORBA::Long theExtrFlags,
2517 CORBA::Double theSewTolerance):
2518 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2522 makeFlags( theMakeGroups, false, false,
2523 theExtrFlags, false ),
2525 myIsExtrusionByNormal( false )
2528 // params for extrusion by normal
2529 ExtrusionParams(CORBA::Double theStepSize,
2530 CORBA::Long theNbOfSteps,
2531 CORBA::Short theDim,
2532 CORBA::Boolean theByAverageNormal,
2533 CORBA::Boolean theUseInputElemsOnly,
2534 CORBA::Boolean theMakeGroups ):
2535 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2537 makeFlags( theMakeGroups,
2538 theByAverageNormal, theUseInputElemsOnly ),
2540 myIsExtrusionByNormal( true )
2546 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2551 //=======================================================================
2553 * \brief Generate dim+1 elements by extrusion of elements along vector
2554 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2555 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2556 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2557 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2558 * \param [in] nbOfSteps - number of elements to generate from one element
2559 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2560 * corresponding to groups the input elements included in.
2561 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2563 //=======================================================================
2565 SMESH::ListOfGroups*
2566 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2567 const SMESH::ListOfIDSources & theEdges,
2568 const SMESH::ListOfIDSources & theFaces,
2569 const SMESH::DirStruct & theStepVector,
2570 CORBA::Long theNbOfSteps,
2571 CORBA::Boolean theToMakeGroups)
2572 throw (SALOME::SALOME_Exception)
2577 ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
2579 TIDSortedElemSet elemsNodes[2];
2580 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2581 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2582 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2584 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2585 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2586 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2587 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2589 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2590 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2591 if ( myIsPreviewMode )
2593 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2594 // previewType = SMDSAbs_Edge;
2596 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2597 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2598 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2599 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2600 workElements = & copyElements[0];
2602 params.SetNoGroups();
2604 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2606 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2607 ::SMESH_MeshEditor::PGroupIDs groupIds =
2608 getEditor().ExtrusionSweep( workElements, params, aHistory );
2610 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2612 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2614 if ( !myIsPreviewMode )
2616 dumpGroupsList( aPythonDump, aGroups );
2617 aPythonDump << this<< ".ExtrusionSweepObjects( "
2621 << theStepVector << ", "
2622 << TVar( theNbOfSteps ) << ", "
2623 << theToMakeGroups << " )";
2627 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2630 return aGroups ? aGroups : new SMESH::ListOfGroups;
2632 SMESH_CATCH( SMESH::throwCorbaException );
2636 //=======================================================================
2637 //function : ExtrusionByNormal
2639 //=======================================================================
2641 SMESH::ListOfGroups*
2642 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2643 CORBA::Double stepSize,
2644 CORBA::Long nbOfSteps,
2645 CORBA::Boolean byAverageNormal,
2646 CORBA::Boolean useInputElemsOnly,
2647 CORBA::Boolean makeGroups,
2649 throw (SALOME::SALOME_Exception)
2654 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2656 ExtrusionParams params( stepSize, nbOfSteps, dim,
2657 byAverageNormal, useInputElemsOnly, makeGroups );
2659 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2660 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2662 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2663 if (( elemTypes->length() == 1 ) &&
2664 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2665 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2668 TIDSortedElemSet elemsNodes[2];
2669 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2670 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2672 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2673 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2674 if ( myIsPreviewMode )
2676 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2677 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2678 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2679 workElements = & copyElements[0];
2681 params.SetNoGroups();
2684 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2685 ::SMESH_MeshEditor::PGroupIDs groupIds =
2686 getEditor().ExtrusionSweep( workElements, params, aHistory );
2688 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2690 if (!myIsPreviewMode) {
2691 dumpGroupsList(aPythonDump, aGroups);
2692 aPythonDump << this << ".ExtrusionByNormal( " << objects
2693 << ", " << TVar( stepSize )
2694 << ", " << TVar( nbOfSteps )
2695 << ", " << byAverageNormal
2696 << ", " << useInputElemsOnly
2697 << ", " << makeGroups
2703 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2706 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2708 return aGroups ? aGroups : new SMESH::ListOfGroups;
2710 SMESH_CATCH( SMESH::throwCorbaException );
2714 //=======================================================================
2715 //function : AdvancedExtrusion
2717 //=======================================================================
2719 SMESH::ListOfGroups*
2720 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2721 const SMESH::DirStruct & theStepVector,
2722 CORBA::Long theNbOfSteps,
2723 CORBA::Long theExtrFlags,
2724 CORBA::Double theSewTolerance,
2725 CORBA::Boolean theMakeGroups)
2726 throw (SALOME::SALOME_Exception)
2731 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2733 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2734 theExtrFlags, theSewTolerance );
2736 TIDSortedElemSet elemsNodes[2];
2737 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2739 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2740 ::SMESH_MeshEditor::PGroupIDs groupIds =
2741 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2743 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2745 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2747 if ( !myIsPreviewMode ) {
2748 dumpGroupsList(aPythonDump, aGroups);
2749 aPythonDump << this << ".AdvancedExtrusion( "
2750 << theIDsOfElements << ", "
2751 << theStepVector << ", "
2752 << theNbOfSteps << ", "
2753 << theExtrFlags << ", "
2754 << theSewTolerance << ", "
2755 << theMakeGroups << " )";
2759 getPreviewMesh()->Remove( SMDSAbs_Volume );
2762 return aGroups ? aGroups : new SMESH::ListOfGroups;
2764 SMESH_CATCH( SMESH::throwCorbaException );
2768 //================================================================================
2770 * \brief Convert extrusion error to IDL enum
2772 //================================================================================
2776 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2778 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2782 RETCASE( EXTR_NO_ELEMENTS );
2783 RETCASE( EXTR_PATH_NOT_EDGE );
2784 RETCASE( EXTR_BAD_PATH_SHAPE );
2785 RETCASE( EXTR_BAD_STARTING_NODE );
2786 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2787 RETCASE( EXTR_CANT_GET_TANGENT );
2789 return SMESH::SMESH_MeshEditor::EXTR_OK;
2793 //=======================================================================
2794 //function : extrusionAlongPath
2796 //=======================================================================
2797 SMESH::ListOfGroups*
2798 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2799 const SMESH::ListOfIDSources & theEdges,
2800 const SMESH::ListOfIDSources & theFaces,
2801 SMESH::SMESH_IDSource_ptr thePathMesh,
2802 GEOM::GEOM_Object_ptr thePathShape,
2803 CORBA::Long theNodeStart,
2804 CORBA::Boolean theHasAngles,
2805 const SMESH::double_array & theAngles,
2806 CORBA::Boolean theLinearVariation,
2807 CORBA::Boolean theHasRefPoint,
2808 const SMESH::PointStruct & theRefPoint,
2810 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2811 throw (SALOME::SALOME_Exception)
2816 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2818 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2819 if ( thePathMesh->_is_nil() )
2820 return aGroups._retn();
2823 SMESH_subMesh* aSubMesh = 0;
2824 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2825 if ( thePathShape->_is_nil() )
2827 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2828 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2830 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2831 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2832 if ( !aMeshImp ) return aGroups._retn();
2833 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2834 if ( !aSubMesh ) return aGroups._retn();
2836 else if ( !aMeshImp ||
2837 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2839 return aGroups._retn();
2844 if ( !aMeshImp ) return aGroups._retn();
2845 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2846 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2847 if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
2848 return aGroups._retn();
2851 SMDS_MeshNode* nodeStart =
2852 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2854 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2855 return aGroups._retn();
2858 TIDSortedElemSet elemsNodes[2];
2859 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2860 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2861 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2863 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2864 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2865 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2866 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2868 list<double> angles;
2869 for (int i = 0; i < theAngles.length(); i++) {
2870 angles.push_back( theAngles[i] );
2873 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2875 int nbOldGroups = myMesh->NbGroup();
2877 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2878 if ( myIsPreviewMode )
2880 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2881 TPreviewMesh * tmpMesh = getPreviewMesh();
2882 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2883 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2884 workElements = & copyElements[0];
2885 theMakeGroups = false;
2888 ::SMESH_MeshEditor::Extrusion_Error error;
2890 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2891 theHasAngles, angles, theLinearVariation,
2892 theHasRefPoint, refPnt, theMakeGroups );
2894 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2895 theHasAngles, angles, theLinearVariation,
2896 theHasRefPoint, refPnt, theMakeGroups );
2898 declareMeshModified( /*isReComputeSafe=*/true );
2899 theError = convExtrError( error );
2901 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2902 if ( theMakeGroups ) {
2903 list<int> groupIDs = myMesh->GetGroupIds();
2904 list<int>::iterator newBegin = groupIDs.begin();
2905 std::advance( newBegin, nbOldGroups ); // skip old groups
2906 groupIDs.erase( groupIDs.begin(), newBegin );
2907 aGroups = getGroups( & groupIDs );
2908 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2911 if ( !myIsPreviewMode ) {
2912 aPythonDump << "(" << aGroups << ", error) = "
2913 << this << ".ExtrusionAlongPathObjects( "
2917 << thePathMesh << ", "
2918 << thePathShape << ", "
2919 << theNodeStart << ", "
2920 << theHasAngles << ", "
2921 << theAngles << ", "
2922 << theLinearVariation << ", "
2923 << theHasRefPoint << ", "
2924 << "SMESH.PointStruct( "
2925 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2926 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2927 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2928 << theMakeGroups << " )";
2932 getPreviewMesh()->Remove( SMDSAbs_Volume );
2935 return aGroups._retn();
2937 SMESH_CATCH( SMESH::throwCorbaException );
2941 //================================================================================
2943 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2944 * of given angles along path steps
2945 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2946 * which proceeds the extrusion
2947 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2948 * is used to define the sub-mesh for the path
2950 //================================================================================
2952 SMESH::double_array*
2953 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2954 GEOM::GEOM_Object_ptr thePathShape,
2955 const SMESH::double_array & theAngles)
2957 SMESH::double_array_var aResult = new SMESH::double_array();
2958 int nbAngles = theAngles.length();
2959 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2961 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2962 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2963 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2964 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2965 return aResult._retn();
2966 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2967 if ( nbSteps == nbAngles )
2969 aResult.inout() = theAngles;
2973 aResult->length( nbSteps );
2974 double rAn2St = double( nbAngles ) / double( nbSteps );
2975 double angPrev = 0, angle;
2976 for ( int iSt = 0; iSt < nbSteps; ++iSt )
2978 double angCur = rAn2St * ( iSt+1 );
2979 double angCurFloor = floor( angCur );
2980 double angPrevFloor = floor( angPrev );
2981 if ( angPrevFloor == angCurFloor )
2982 angle = rAn2St * theAngles[ int( angCurFloor ) ];
2985 int iP = int( angPrevFloor );
2986 double angPrevCeil = ceil(angPrev);
2987 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2989 int iC = int( angCurFloor );
2990 if ( iC < nbAngles )
2991 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2993 iP = int( angPrevCeil );
2995 angle += theAngles[ iC ];
2997 aResult[ iSt ] = angle;
3002 // Update Python script
3003 TPythonDump() << "rotAngles = " << theAngles;
3004 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3005 << thePathMesh << ", "
3006 << thePathShape << ", "
3009 return aResult._retn();
3012 //=======================================================================
3015 //=======================================================================
3017 SMESH::ListOfGroups*
3018 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3019 const SMESH::AxisStruct & theAxis,
3020 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3021 CORBA::Boolean theCopy,
3023 ::SMESH_Mesh* theTargetMesh)
3024 throw (SALOME::SALOME_Exception)
3029 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3030 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3032 if ( theTargetMesh )
3036 switch ( theMirrorType ) {
3037 case SMESH::SMESH_MeshEditor::POINT:
3038 aTrsf.SetMirror( P );
3040 case SMESH::SMESH_MeshEditor::AXIS:
3041 aTrsf.SetMirror( gp_Ax1( P, V ));
3044 aTrsf.SetMirror( gp_Ax2( P, V ));
3047 TIDSortedElemSet copyElements;
3048 TIDSortedElemSet* workElements = & theElements;
3050 if ( myIsPreviewMode )
3052 TPreviewMesh * tmpMesh = getPreviewMesh();
3053 tmpMesh->Copy( theElements, copyElements);
3054 if ( !theCopy && !theTargetMesh )
3056 TIDSortedElemSet elemsAround, elemsAroundCopy;
3057 getElementsAround( theElements, getMeshDS(), elemsAround );
3058 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3060 workElements = & copyElements;
3061 theMakeGroups = false;
3064 ::SMESH_MeshEditor::PGroupIDs groupIds =
3065 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3067 if ( theCopy && !myIsPreviewMode)
3069 if ( theTargetMesh )
3071 theTargetMesh->GetMeshDS()->Modified();
3075 declareMeshModified( /*isReComputeSafe=*/false );
3078 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3080 SMESH_CATCH( SMESH::throwCorbaException );
3084 //=======================================================================
3087 //=======================================================================
3089 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3090 const SMESH::AxisStruct & theAxis,
3091 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3092 CORBA::Boolean theCopy)
3093 throw (SALOME::SALOME_Exception)
3095 if ( !myIsPreviewMode ) {
3096 TPythonDump() << this << ".Mirror( "
3097 << theIDsOfElements << ", "
3099 << mirrorTypeName(theMirrorType) << ", "
3102 if ( theIDsOfElements.length() > 0 )
3104 TIDSortedElemSet elements;
3105 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3106 mirror(elements, theAxis, theMirrorType, theCopy, false);
3111 //=======================================================================
3112 //function : MirrorObject
3114 //=======================================================================
3116 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3117 const SMESH::AxisStruct & theAxis,
3118 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3119 CORBA::Boolean theCopy)
3120 throw (SALOME::SALOME_Exception)
3122 if ( !myIsPreviewMode ) {
3123 TPythonDump() << this << ".MirrorObject( "
3124 << theObject << ", "
3126 << mirrorTypeName(theMirrorType) << ", "
3129 TIDSortedElemSet elements;
3131 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3133 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3134 mirror(elements, theAxis, theMirrorType, theCopy, false);
3137 //=======================================================================
3138 //function : MirrorMakeGroups
3140 //=======================================================================
3142 SMESH::ListOfGroups*
3143 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3144 const SMESH::AxisStruct& theMirror,
3145 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3146 throw (SALOME::SALOME_Exception)
3148 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3150 SMESH::ListOfGroups * aGroups = 0;
3151 if ( theIDsOfElements.length() > 0 )
3153 TIDSortedElemSet elements;
3154 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3155 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3157 if (!myIsPreviewMode) {
3158 dumpGroupsList(aPythonDump, aGroups);
3159 aPythonDump << this << ".MirrorMakeGroups( "
3160 << theIDsOfElements << ", "
3161 << theMirror << ", "
3162 << mirrorTypeName(theMirrorType) << " )";
3167 //=======================================================================
3168 //function : MirrorObjectMakeGroups
3170 //=======================================================================
3172 SMESH::ListOfGroups*
3173 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3174 const SMESH::AxisStruct& theMirror,
3175 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3176 throw (SALOME::SALOME_Exception)
3178 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3180 SMESH::ListOfGroups * aGroups = 0;
3181 TIDSortedElemSet elements;
3182 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3183 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3185 if (!myIsPreviewMode)
3187 dumpGroupsList(aPythonDump,aGroups);
3188 aPythonDump << this << ".MirrorObjectMakeGroups( "
3189 << theObject << ", "
3190 << theMirror << ", "
3191 << mirrorTypeName(theMirrorType) << " )";
3196 //=======================================================================
3197 //function : MirrorMakeMesh
3199 //=======================================================================
3201 SMESH::SMESH_Mesh_ptr
3202 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3203 const SMESH::AxisStruct& theMirror,
3204 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3205 CORBA::Boolean theCopyGroups,
3206 const char* theMeshName)
3207 throw (SALOME::SALOME_Exception)
3209 SMESH_Mesh_i* mesh_i;
3210 SMESH::SMESH_Mesh_var mesh;
3211 { // open new scope to dump "MakeMesh" command
3212 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3214 TPythonDump pydump; // to prevent dump at mesh creation
3216 mesh = makeMesh( theMeshName );
3217 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3218 if (mesh_i && theIDsOfElements.length() > 0 )
3220 TIDSortedElemSet elements;
3221 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3222 mirror(elements, theMirror, theMirrorType,
3223 false, theCopyGroups, & mesh_i->GetImpl());
3224 mesh_i->CreateGroupServants();
3227 if (!myIsPreviewMode) {
3228 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3229 << theIDsOfElements << ", "
3230 << theMirror << ", "
3231 << mirrorTypeName(theMirrorType) << ", "
3232 << theCopyGroups << ", '"
3233 << theMeshName << "' )";
3238 if (!myIsPreviewMode && mesh_i)
3239 mesh_i->GetGroups();
3241 return mesh._retn();
3244 //=======================================================================
3245 //function : MirrorObjectMakeMesh
3247 //=======================================================================
3249 SMESH::SMESH_Mesh_ptr
3250 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3251 const SMESH::AxisStruct& theMirror,
3252 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3253 CORBA::Boolean theCopyGroups,
3254 const char* theMeshName)
3255 throw (SALOME::SALOME_Exception)
3257 SMESH_Mesh_i* mesh_i;
3258 SMESH::SMESH_Mesh_var mesh;
3259 { // open new scope to dump "MakeMesh" command
3260 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3262 TPythonDump pydump; // to prevent dump at mesh creation
3264 mesh = makeMesh( theMeshName );
3265 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3266 TIDSortedElemSet elements;
3268 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3270 mirror(elements, theMirror, theMirrorType,
3271 false, theCopyGroups, & mesh_i->GetImpl());
3272 mesh_i->CreateGroupServants();
3274 if (!myIsPreviewMode) {
3275 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3276 << theObject << ", "
3277 << theMirror << ", "
3278 << mirrorTypeName(theMirrorType) << ", "
3279 << theCopyGroups << ", '"
3280 << theMeshName << "' )";
3285 if (!myIsPreviewMode && mesh_i)
3286 mesh_i->GetGroups();
3288 return mesh._retn();
3291 //=======================================================================
3292 //function : translate
3294 //=======================================================================
3296 SMESH::ListOfGroups*
3297 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3298 const SMESH::DirStruct & theVector,
3299 CORBA::Boolean theCopy,
3301 ::SMESH_Mesh* theTargetMesh)
3302 throw (SALOME::SALOME_Exception)
3307 if ( theTargetMesh )
3311 const SMESH::PointStruct * P = &theVector.PS;
3312 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3314 TIDSortedElemSet copyElements;
3315 TIDSortedElemSet* workElements = &theElements;
3317 if ( myIsPreviewMode )
3319 TPreviewMesh * tmpMesh = getPreviewMesh();
3320 tmpMesh->Copy( theElements, copyElements);
3321 if ( !theCopy && !theTargetMesh )
3323 TIDSortedElemSet elemsAround, elemsAroundCopy;
3324 getElementsAround( theElements, getMeshDS(), elemsAround );
3325 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3327 workElements = & copyElements;
3328 theMakeGroups = false;
3331 ::SMESH_MeshEditor::PGroupIDs groupIds =
3332 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3334 if ( theCopy && !myIsPreviewMode )
3336 if ( theTargetMesh )
3338 theTargetMesh->GetMeshDS()->Modified();
3342 declareMeshModified( /*isReComputeSafe=*/false );
3346 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3348 SMESH_CATCH( SMESH::throwCorbaException );
3352 //=======================================================================
3353 //function : Translate
3355 //=======================================================================
3357 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3358 const SMESH::DirStruct & theVector,
3359 CORBA::Boolean theCopy)
3360 throw (SALOME::SALOME_Exception)
3362 if (!myIsPreviewMode) {
3363 TPythonDump() << this << ".Translate( "
3364 << theIDsOfElements << ", "
3365 << theVector << ", "
3368 if (theIDsOfElements.length()) {
3369 TIDSortedElemSet elements;
3370 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3371 translate(elements, theVector, theCopy, false);
3375 //=======================================================================
3376 //function : TranslateObject
3378 //=======================================================================
3380 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3381 const SMESH::DirStruct & theVector,
3382 CORBA::Boolean theCopy)
3383 throw (SALOME::SALOME_Exception)
3385 if (!myIsPreviewMode) {
3386 TPythonDump() << this << ".TranslateObject( "
3387 << theObject << ", "
3388 << theVector << ", "
3391 TIDSortedElemSet elements;
3393 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3395 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3396 translate(elements, theVector, theCopy, false);
3399 //=======================================================================
3400 //function : TranslateMakeGroups
3402 //=======================================================================
3404 SMESH::ListOfGroups*
3405 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3406 const SMESH::DirStruct& theVector)
3407 throw (SALOME::SALOME_Exception)
3409 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3411 SMESH::ListOfGroups * aGroups = 0;
3412 if (theIDsOfElements.length()) {
3413 TIDSortedElemSet elements;
3414 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3415 aGroups = translate(elements,theVector,true,true);
3417 if (!myIsPreviewMode) {
3418 dumpGroupsList(aPythonDump, aGroups);
3419 aPythonDump << this << ".TranslateMakeGroups( "
3420 << theIDsOfElements << ", "
3421 << theVector << " )";
3426 //=======================================================================
3427 //function : TranslateObjectMakeGroups
3429 //=======================================================================
3431 SMESH::ListOfGroups*
3432 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3433 const SMESH::DirStruct& theVector)
3434 throw (SALOME::SALOME_Exception)
3436 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3438 SMESH::ListOfGroups * aGroups = 0;
3439 TIDSortedElemSet elements;
3440 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3441 aGroups = translate(elements, theVector, true, true);
3443 if (!myIsPreviewMode) {
3444 dumpGroupsList(aPythonDump, aGroups);
3445 aPythonDump << this << ".TranslateObjectMakeGroups( "
3446 << theObject << ", "
3447 << theVector << " )";
3452 //=======================================================================
3453 //function : TranslateMakeMesh
3455 //=======================================================================
3457 SMESH::SMESH_Mesh_ptr
3458 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3459 const SMESH::DirStruct& theVector,
3460 CORBA::Boolean theCopyGroups,
3461 const char* theMeshName)
3462 throw (SALOME::SALOME_Exception)
3464 SMESH_Mesh_i* mesh_i;
3465 SMESH::SMESH_Mesh_var mesh;
3467 { // open new scope to dump "MakeMesh" command
3468 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3470 TPythonDump pydump; // to prevent dump at mesh creation
3472 mesh = makeMesh( theMeshName );
3473 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3475 if ( mesh_i && theIDsOfElements.length() )
3477 TIDSortedElemSet elements;
3478 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3479 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3480 mesh_i->CreateGroupServants();
3483 if ( !myIsPreviewMode ) {
3484 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3485 << theIDsOfElements << ", "
3486 << theVector << ", "
3487 << theCopyGroups << ", '"
3488 << theMeshName << "' )";
3493 if (!myIsPreviewMode && mesh_i)
3494 mesh_i->GetGroups();
3496 return mesh._retn();
3499 //=======================================================================
3500 //function : TranslateObjectMakeMesh
3502 //=======================================================================
3504 SMESH::SMESH_Mesh_ptr
3505 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3506 const SMESH::DirStruct& theVector,
3507 CORBA::Boolean theCopyGroups,
3508 const char* theMeshName)
3509 throw (SALOME::SALOME_Exception)
3512 SMESH_Mesh_i* mesh_i;
3513 SMESH::SMESH_Mesh_var mesh;
3514 { // open new scope to dump "MakeMesh" command
3515 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3517 TPythonDump pydump; // to prevent dump at mesh creation
3518 mesh = makeMesh( theMeshName );
3519 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3521 TIDSortedElemSet elements;
3523 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3525 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3526 mesh_i->CreateGroupServants();
3528 if ( !myIsPreviewMode ) {
3529 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3530 << theObject << ", "
3531 << theVector << ", "
3532 << theCopyGroups << ", '"
3533 << theMeshName << "' )";
3538 if (!myIsPreviewMode && mesh_i)
3539 mesh_i->GetGroups();
3541 return mesh._retn();
3543 SMESH_CATCH( SMESH::throwCorbaException );
3547 //=======================================================================
3550 //=======================================================================
3552 SMESH::ListOfGroups*
3553 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3554 const SMESH::AxisStruct & theAxis,
3555 CORBA::Double theAngle,
3556 CORBA::Boolean theCopy,
3558 ::SMESH_Mesh* theTargetMesh)
3559 throw (SALOME::SALOME_Exception)
3564 if ( theTargetMesh )
3567 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3568 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3571 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3573 TIDSortedElemSet copyElements;
3574 TIDSortedElemSet* workElements = &theElements;
3575 if ( myIsPreviewMode ) {
3576 TPreviewMesh * tmpMesh = getPreviewMesh();
3577 tmpMesh->Copy( theElements, copyElements );
3578 if ( !theCopy && !theTargetMesh )
3580 TIDSortedElemSet elemsAround, elemsAroundCopy;
3581 getElementsAround( theElements, getMeshDS(), elemsAround );
3582 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3584 workElements = ©Elements;
3585 theMakeGroups = false;
3588 ::SMESH_MeshEditor::PGroupIDs groupIds =
3589 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3591 if ( theCopy && !myIsPreviewMode)
3593 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3594 else declareMeshModified( /*isReComputeSafe=*/false );
3597 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3599 SMESH_CATCH( SMESH::throwCorbaException );
3603 //=======================================================================
3606 //=======================================================================
3608 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3609 const SMESH::AxisStruct & theAxis,
3610 CORBA::Double theAngle,
3611 CORBA::Boolean theCopy)
3612 throw (SALOME::SALOME_Exception)
3614 if (!myIsPreviewMode) {
3615 TPythonDump() << this << ".Rotate( "
3616 << theIDsOfElements << ", "
3618 << TVar( theAngle ) << ", "
3621 if (theIDsOfElements.length() > 0)
3623 TIDSortedElemSet elements;
3624 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3625 rotate(elements,theAxis,theAngle,theCopy,false);
3629 //=======================================================================
3630 //function : RotateObject
3632 //=======================================================================
3634 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3635 const SMESH::AxisStruct & theAxis,
3636 CORBA::Double theAngle,
3637 CORBA::Boolean theCopy)
3638 throw (SALOME::SALOME_Exception)
3640 if ( !myIsPreviewMode ) {
3641 TPythonDump() << this << ".RotateObject( "
3642 << theObject << ", "
3644 << TVar( theAngle ) << ", "
3647 TIDSortedElemSet elements;
3648 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3649 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3650 rotate(elements,theAxis,theAngle,theCopy,false);
3653 //=======================================================================
3654 //function : RotateMakeGroups
3656 //=======================================================================
3658 SMESH::ListOfGroups*
3659 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3660 const SMESH::AxisStruct& theAxis,
3661 CORBA::Double theAngle)
3662 throw (SALOME::SALOME_Exception)
3664 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3666 SMESH::ListOfGroups * aGroups = 0;
3667 if (theIDsOfElements.length() > 0)
3669 TIDSortedElemSet elements;
3670 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3671 aGroups = rotate(elements,theAxis,theAngle,true,true);
3673 if (!myIsPreviewMode) {
3674 dumpGroupsList(aPythonDump, aGroups);
3675 aPythonDump << this << ".RotateMakeGroups( "
3676 << theIDsOfElements << ", "
3678 << TVar( theAngle ) << " )";
3683 //=======================================================================
3684 //function : RotateObjectMakeGroups
3686 //=======================================================================
3688 SMESH::ListOfGroups*
3689 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3690 const SMESH::AxisStruct& theAxis,
3691 CORBA::Double theAngle)
3692 throw (SALOME::SALOME_Exception)
3694 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3696 SMESH::ListOfGroups * aGroups = 0;
3697 TIDSortedElemSet elements;
3698 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3699 aGroups = rotate(elements, theAxis, theAngle, true, true);
3701 if (!myIsPreviewMode) {
3702 dumpGroupsList(aPythonDump, aGroups);
3703 aPythonDump << this << ".RotateObjectMakeGroups( "
3704 << theObject << ", "
3706 << TVar( theAngle ) << " )";
3711 //=======================================================================
3712 //function : RotateMakeMesh
3714 //=======================================================================
3716 SMESH::SMESH_Mesh_ptr
3717 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3718 const SMESH::AxisStruct& theAxis,
3719 CORBA::Double theAngleInRadians,
3720 CORBA::Boolean theCopyGroups,
3721 const char* theMeshName)
3722 throw (SALOME::SALOME_Exception)
3725 SMESH::SMESH_Mesh_var mesh;
3726 SMESH_Mesh_i* mesh_i;
3728 { // open new scope to dump "MakeMesh" command
3729 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3731 TPythonDump pydump; // to prevent dump at mesh creation
3733 mesh = makeMesh( theMeshName );
3734 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3736 if ( mesh_i && theIDsOfElements.length() > 0 )
3738 TIDSortedElemSet elements;
3739 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3740 rotate(elements, theAxis, theAngleInRadians,
3741 false, theCopyGroups, & mesh_i->GetImpl());
3742 mesh_i->CreateGroupServants();
3744 if ( !myIsPreviewMode ) {
3745 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3746 << theIDsOfElements << ", "
3748 << TVar( theAngleInRadians ) << ", "
3749 << theCopyGroups << ", '"
3750 << theMeshName << "' )";
3755 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3756 mesh_i->GetGroups();
3758 return mesh._retn();
3760 SMESH_CATCH( SMESH::throwCorbaException );
3764 //=======================================================================
3765 //function : RotateObjectMakeMesh
3767 //=======================================================================
3769 SMESH::SMESH_Mesh_ptr
3770 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3771 const SMESH::AxisStruct& theAxis,
3772 CORBA::Double theAngleInRadians,
3773 CORBA::Boolean theCopyGroups,
3774 const char* theMeshName)
3775 throw (SALOME::SALOME_Exception)
3778 SMESH::SMESH_Mesh_var mesh;
3779 SMESH_Mesh_i* mesh_i;
3781 {// open new scope to dump "MakeMesh" command
3782 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3784 TPythonDump pydump; // to prevent dump at mesh creation
3785 mesh = makeMesh( theMeshName );
3786 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3788 TIDSortedElemSet elements;
3790 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3792 rotate(elements, theAxis, theAngleInRadians,
3793 false, theCopyGroups, & mesh_i->GetImpl());
3794 mesh_i->CreateGroupServants();
3796 if ( !myIsPreviewMode ) {
3797 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3798 << theObject << ", "
3800 << TVar( theAngleInRadians ) << ", "
3801 << theCopyGroups << ", '"
3802 << theMeshName << "' )";
3807 if (!myIsPreviewMode && mesh_i)
3808 mesh_i->GetGroups();
3810 return mesh._retn();
3812 SMESH_CATCH( SMESH::throwCorbaException );
3816 //=======================================================================
3819 //=======================================================================
3821 SMESH::ListOfGroups*
3822 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3823 const SMESH::PointStruct& thePoint,
3824 const SMESH::double_array& theScaleFact,
3825 CORBA::Boolean theCopy,
3827 ::SMESH_Mesh* theTargetMesh)
3828 throw (SALOME::SALOME_Exception)
3832 if ( theScaleFact.length() < 1 )
3833 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3834 if ( theScaleFact.length() == 2 )
3835 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3837 if ( theTargetMesh )
3840 TIDSortedElemSet elements;
3841 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3842 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3847 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3848 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3852 #if OCC_VERSION_LARGE > 0x06070100
3853 // fight against orthogonalization
3854 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3855 // 0, S[1], 0, thePoint.y * (1-S[1]),
3856 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3857 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3858 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3859 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3860 loc.SetCoord( thePoint.x * (1-S[0]),
3861 thePoint.y * (1-S[1]),
3862 thePoint.z * (1-S[2]));
3863 M.SetDiagonal( S[0], S[1], S[2] );
3866 double tol = std::numeric_limits<double>::max();
3867 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3868 0, S[1], 0, thePoint.y * (1-S[1]),
3869 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3872 TIDSortedElemSet copyElements;
3873 TIDSortedElemSet* workElements = &elements;
3874 if ( myIsPreviewMode )
3876 TPreviewMesh * tmpMesh = getPreviewMesh();
3877 tmpMesh->Copy( elements, copyElements);
3878 if ( !theCopy && !theTargetMesh )
3880 TIDSortedElemSet elemsAround, elemsAroundCopy;
3881 getElementsAround( elements, getMeshDS(), elemsAround );
3882 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3884 workElements = & copyElements;
3885 theMakeGroups = false;
3888 ::SMESH_MeshEditor::PGroupIDs groupIds =
3889 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3891 if ( theCopy && !myIsPreviewMode )
3893 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3894 else declareMeshModified( /*isReComputeSafe=*/false );
3896 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3898 SMESH_CATCH( SMESH::throwCorbaException );
3902 //=======================================================================
3905 //=======================================================================
3907 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3908 const SMESH::PointStruct& thePoint,
3909 const SMESH::double_array& theScaleFact,
3910 CORBA::Boolean theCopy)
3911 throw (SALOME::SALOME_Exception)
3913 if ( !myIsPreviewMode ) {
3914 TPythonDump() << this << ".Scale( "
3915 << theObject << ", "
3917 << TVar( theScaleFact ) << ", "
3920 scale(theObject, thePoint, theScaleFact, theCopy, false);
3924 //=======================================================================
3925 //function : ScaleMakeGroups
3927 //=======================================================================
3929 SMESH::ListOfGroups*
3930 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3931 const SMESH::PointStruct& thePoint,
3932 const SMESH::double_array& theScaleFact)
3933 throw (SALOME::SALOME_Exception)
3935 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3937 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3938 if (!myIsPreviewMode) {
3939 dumpGroupsList(aPythonDump, aGroups);
3940 aPythonDump << this << ".Scale("
3943 << TVar( theScaleFact ) << ",True,True)";
3949 //=======================================================================
3950 //function : ScaleMakeMesh
3952 //=======================================================================
3954 SMESH::SMESH_Mesh_ptr
3955 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3956 const SMESH::PointStruct& thePoint,
3957 const SMESH::double_array& theScaleFact,
3958 CORBA::Boolean theCopyGroups,
3959 const char* theMeshName)
3960 throw (SALOME::SALOME_Exception)
3962 SMESH_Mesh_i* mesh_i;
3963 SMESH::SMESH_Mesh_var mesh;
3964 { // open new scope to dump "MakeMesh" command
3965 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3967 TPythonDump pydump; // to prevent dump at mesh creation
3968 mesh = makeMesh( theMeshName );
3969 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3973 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3974 mesh_i->CreateGroupServants();
3976 if ( !myIsPreviewMode )
3977 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3978 << theObject << ", "
3980 << TVar( theScaleFact ) << ", "
3981 << theCopyGroups << ", '"
3982 << theMeshName << "' )";
3986 if (!myIsPreviewMode && mesh_i)
3987 mesh_i->GetGroups();
3989 return mesh._retn();
3993 //=======================================================================
3994 //function : findCoincidentNodes
3996 //=======================================================================
3998 void SMESH_MeshEditor_i::
3999 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4000 CORBA::Double Tolerance,
4001 SMESH::array_of_long_array_out GroupsOfNodes,
4002 CORBA::Boolean SeparateCornersAndMedium)
4004 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4005 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4007 GroupsOfNodes = new SMESH::array_of_long_array;
4008 GroupsOfNodes->length( aListOfListOfNodes.size() );
4009 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4010 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4012 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4013 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4014 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4015 aGroup.length( aListOfNodes.size() );
4016 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4017 aGroup[ j ] = (*lIt)->GetID();
4021 //=======================================================================
4022 //function : FindCoincidentNodes
4024 //=======================================================================
4026 void SMESH_MeshEditor_i::
4027 FindCoincidentNodes (CORBA::Double Tolerance,
4028 SMESH::array_of_long_array_out GroupsOfNodes,
4029 CORBA::Boolean SeparateCornersAndMedium)
4030 throw (SALOME::SALOME_Exception)
4035 TIDSortedNodeSet nodes; // no input nodes
4036 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4038 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4039 << Tolerance << ", "
4040 << SeparateCornersAndMedium << " )";
4042 SMESH_CATCH( SMESH::throwCorbaException );
4045 //=======================================================================
4046 //function : FindCoincidentNodesOnPart
4048 //=======================================================================
4050 void SMESH_MeshEditor_i::
4051 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4052 CORBA::Double Tolerance,
4053 SMESH::array_of_long_array_out GroupsOfNodes,
4054 CORBA::Boolean SeparateCornersAndMedium)
4055 throw (SALOME::SALOME_Exception)
4060 TIDSortedNodeSet nodes;
4061 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4063 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4065 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4067 << Tolerance << ", "
4068 << SeparateCornersAndMedium << " )";
4070 SMESH_CATCH( SMESH::throwCorbaException );
4073 //================================================================================
4075 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4076 * ExceptSubMeshOrGroups
4078 //================================================================================
4080 void SMESH_MeshEditor_i::
4081 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4082 CORBA::Double theTolerance,
4083 SMESH::array_of_long_array_out theGroupsOfNodes,
4084 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4085 CORBA::Boolean theSeparateCornersAndMedium)
4086 throw (SALOME::SALOME_Exception)
4091 TIDSortedNodeSet nodes;
4092 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4094 for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4096 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4098 while ( nodeIt->more() )
4099 nodes.erase( cast2Node( nodeIt->next() ));
4101 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4103 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4105 << theTolerance << ", "
4106 << theExceptSubMeshOrGroups << ", "
4107 << theSeparateCornersAndMedium << " )";
4109 SMESH_CATCH( SMESH::throwCorbaException );
4112 //=======================================================================
4113 //function : MergeNodes
4115 //=======================================================================
4117 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4118 const SMESH::ListOfIDSources& NodesToKeep)
4119 throw (SALOME::SALOME_Exception)
4124 SMESHDS_Mesh* aMesh = getMeshDS();
4126 TPythonDump aTPythonDump;
4127 aTPythonDump << this << ".MergeNodes([";
4129 TIDSortedNodeSet setOfNodesToKeep;
4130 for ( int i = 0; i < NodesToKeep.length(); ++i )
4132 prepareIdSource( NodesToKeep[i] );
4133 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
4134 while ( nodeIt->more() )
4135 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4138 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4139 for (int i = 0; i < GroupsOfNodes.length(); i++)
4141 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4142 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4143 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4144 for ( int j = 0; j < aNodeGroup.length(); j++ )
4146 CORBA::Long index = aNodeGroup[ j ];
4147 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4149 if ( setOfNodesToKeep.count( node ))
4150 aListOfNodes.push_front( node );
4152 aListOfNodes.push_back( node );
4155 if ( aListOfNodes.size() < 2 )
4156 aListOfListOfNodes.pop_back();
4158 if ( i > 0 ) aTPythonDump << ", ";
4159 aTPythonDump << aNodeGroup;
4162 getEditor().MergeNodes( aListOfListOfNodes );
4164 aTPythonDump << "], " << NodesToKeep << ")";
4166 declareMeshModified( /*isReComputeSafe=*/false );
4168 SMESH_CATCH( SMESH::throwCorbaException );
4171 //=======================================================================
4172 //function : FindEqualElements
4174 //=======================================================================
4176 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4177 SMESH::array_of_long_array_out GroupsOfElementsID)
4178 throw (SALOME::SALOME_Exception)
4183 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4184 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4186 TIDSortedElemSet elems;
4187 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4189 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4190 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4192 GroupsOfElementsID = new SMESH::array_of_long_array;
4193 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4195 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4196 aListOfListOfElementsID.begin();
4197 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4199 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4200 list<int>& listOfIDs = *arraysIt;
4201 aGroup.length( listOfIDs.size() );
4202 list<int>::iterator idIt = listOfIDs.begin();
4203 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4204 aGroup[ k ] = *idIt;
4207 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4211 SMESH_CATCH( SMESH::throwCorbaException );
4214 //=======================================================================
4215 //function : MergeElements
4217 //=======================================================================
4219 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4220 throw (SALOME::SALOME_Exception)
4225 TPythonDump aTPythonDump;
4226 aTPythonDump << this << ".MergeElements( [";
4228 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4230 for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4231 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4232 aListOfListOfElementsID.push_back( list< int >() );
4233 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4234 for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4235 CORBA::Long id = anElemsIDGroup[ j ];
4236 aListOfElemsID.push_back( id );
4238 if ( aListOfElemsID.size() < 2 )
4239 aListOfListOfElementsID.pop_back();
4240 if ( i > 0 ) aTPythonDump << ", ";
4241 aTPythonDump << anElemsIDGroup;
4244 getEditor().MergeElements(aListOfListOfElementsID);
4246 declareMeshModified( /*isReComputeSafe=*/true );
4248 aTPythonDump << "] )";
4250 SMESH_CATCH( SMESH::throwCorbaException );
4253 //=======================================================================
4254 //function : MergeEqualElements
4256 //=======================================================================
4258 void SMESH_MeshEditor_i::MergeEqualElements()
4259 throw (SALOME::SALOME_Exception)
4264 getEditor().MergeEqualElements();
4266 declareMeshModified( /*isReComputeSafe=*/true );
4268 TPythonDump() << this << ".MergeEqualElements()";
4270 SMESH_CATCH( SMESH::throwCorbaException );
4273 //=============================================================================
4275 * Move the node to a given point
4277 //=============================================================================
4279 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4283 throw (SALOME::SALOME_Exception)
4286 initData(/*deleteSearchers=*/false);
4288 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4292 if ( theNodeSearcher )
4293 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4295 if ( myIsPreviewMode ) // make preview data
4297 // in a preview mesh, make edges linked to a node
4298 TPreviewMesh& tmpMesh = *getPreviewMesh();
4299 TIDSortedElemSet linkedNodes;
4300 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4301 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4302 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4303 for ( ; nIt != linkedNodes.end(); ++nIt )
4305 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4306 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4310 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4311 // fill preview data
4313 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4314 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4316 getMeshDS()->MoveNode(node, x, y, z);
4318 if ( !myIsPreviewMode )
4320 // Update Python script
4321 TPythonDump() << "isDone = " << this << ".MoveNode( "
4322 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4323 declareMeshModified( /*isReComputeSafe=*/false );
4326 SMESH_CATCH( SMESH::throwCorbaException );
4331 //================================================================================
4333 * \brief Return ID of node closest to a given point
4335 //================================================================================
4337 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4340 throw (SALOME::SALOME_Exception)
4343 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4345 if ( !theNodeSearcher ) {
4346 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4349 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4350 return node->GetID();
4352 SMESH_CATCH( SMESH::throwCorbaException );
4356 //================================================================================
4358 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4359 * move the node closest to the point to point's location and return ID of the node
4361 //================================================================================
4363 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4366 CORBA::Long theNodeID)
4367 throw (SALOME::SALOME_Exception)
4370 // We keep theNodeSearcher until any mesh modification:
4371 // 1) initData() deletes theNodeSearcher at any edition,
4372 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4374 initData(/*deleteSearchers=*/false);
4376 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4378 int nodeID = theNodeID;
4379 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4380 if ( !node ) // preview moving node
4382 if ( !theNodeSearcher ) {
4383 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4386 node = theNodeSearcher->FindClosestTo( p );
4389 nodeID = node->GetID();
4390 if ( myIsPreviewMode ) // make preview data
4392 // in a preview mesh, make edges linked to a node
4393 TPreviewMesh tmpMesh = *getPreviewMesh();
4394 TIDSortedElemSet linkedNodes;
4395 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4396 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4397 for ( ; nIt != linkedNodes.end(); ++nIt )
4399 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4400 tmpMesh.Copy( &edge );
4403 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4405 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4406 // fill preview data
4408 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4410 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4414 getMeshDS()->MoveNode(node, x, y, z);
4418 if ( !myIsPreviewMode )
4420 TPythonDump() << "nodeID = " << this
4421 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4422 << ", " << nodeID << " )";
4424 declareMeshModified( /*isReComputeSafe=*/false );
4429 SMESH_CATCH( SMESH::throwCorbaException );
4433 //=======================================================================
4435 * Return elements of given type where the given point is IN or ON.
4437 * 'ALL' type means elements of any type excluding nodes
4439 //=======================================================================
4441 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4444 SMESH::ElementType type)
4445 throw (SALOME::SALOME_Exception)
4448 SMESH::long_array_var res = new SMESH::long_array;
4449 vector< const SMDS_MeshElement* > foundElems;
4451 theSearchersDeleter.Set( myMesh );
4452 if ( !theElementSearcher ) {
4453 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4455 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4456 SMDSAbs_ElementType( type ),
4458 res->length( foundElems.size() );
4459 for ( int i = 0; i < foundElems.size(); ++i )
4460 res[i] = foundElems[i]->GetID();
4464 SMESH_CATCH( SMESH::throwCorbaException );
4468 //=======================================================================
4469 //function : FindAmongElementsByPoint
4470 //purpose : Searching among the given elements, return elements of given type
4471 // where the given point is IN or ON.
4472 // 'ALL' type means elements of any type excluding nodes
4473 //=======================================================================
4476 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4480 SMESH::ElementType type)
4481 throw (SALOME::SALOME_Exception)
4484 SMESH::long_array_var res = new SMESH::long_array;
4486 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4487 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4488 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4489 type != types[0] ) // but search of elements of dim > 0
4492 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4493 return FindElementsByPoint( x,y,z, type );
4495 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4497 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4498 if ( !theElementSearcher )
4500 // create a searcher from elementIDs
4501 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4502 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4504 if ( !idSourceToSet( elementIDs, meshDS, elements,
4505 SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4508 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4509 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4511 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4514 vector< const SMDS_MeshElement* > foundElems;
4516 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4517 SMDSAbs_ElementType( type ),
4519 res->length( foundElems.size() );
4520 for ( int i = 0; i < foundElems.size(); ++i )
4521 res[i] = foundElems[i]->GetID();
4525 SMESH_CATCH( SMESH::throwCorbaException );
4529 //=======================================================================
4530 //function : GetPointState
4531 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4532 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4533 //=======================================================================
4535 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4538 throw (SALOME::SALOME_Exception)
4541 theSearchersDeleter.Set( myMesh );
4542 if ( !theElementSearcher ) {
4543 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4545 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4547 SMESH_CATCH( SMESH::throwCorbaException );
4551 //=======================================================================
4552 //function : convError
4554 //=======================================================================
4556 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4558 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4562 RETCASE( SEW_BORDER1_NOT_FOUND );
4563 RETCASE( SEW_BORDER2_NOT_FOUND );
4564 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4565 RETCASE( SEW_BAD_SIDE_NODES );
4566 RETCASE( SEW_VOLUMES_TO_SPLIT );
4567 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4568 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4569 RETCASE( SEW_BAD_SIDE1_NODES );
4570 RETCASE( SEW_BAD_SIDE2_NODES );
4572 return SMESH::SMESH_MeshEditor::SEW_OK;
4575 //=======================================================================
4577 * Returns groups of FreeBorder's coincident within the given tolerance.
4578 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
4579 * to free borders being compared is used.
4581 //=======================================================================
4583 SMESH::CoincidentFreeBorders*
4584 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
4586 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
4590 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
4591 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
4593 // copy free borders
4594 aCFB->borders.length( cfb._borders.size() );
4595 for ( size_t i = 0; i < cfb._borders.size(); ++i )
4597 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
4598 SMESH::FreeBorder& aBRD = aCFB->borders[i];
4599 aBRD.nodeIDs.length( nodes.size() );
4600 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4601 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
4604 // copy coincident parts
4605 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
4606 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
4608 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
4609 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
4610 aGRP.length( grp.size() );
4611 for ( size_t iP = 0; iP < grp.size(); ++iP )
4613 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
4614 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4615 aPART.border = part._border;
4616 aPART.node1 = part._node1;
4617 aPART.node2 = part._node2;
4618 aPART.nodeLast = part._nodeLast;
4621 SMESH_CATCH( SMESH::doNothing );
4623 TPythonDump() << "CoincidentFreeBorders = "
4624 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
4626 return aCFB._retn();
4629 //=======================================================================
4631 * Sew FreeBorder's of each group
4633 //=======================================================================
4635 CORBA::Short SMESH_MeshEditor_i::
4636 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
4637 CORBA::Boolean createPolygons,
4638 CORBA::Boolean createPolyhedra)
4639 throw (SALOME::SALOME_Exception)
4641 CORBA::Short nbSewed = 0;
4643 SMESH_MeshAlgos::TFreeBorderVec groups;
4644 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
4646 // check the input and collect nodes
4647 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
4649 borderNodes.clear();
4650 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
4651 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
4653 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4654 if ( aPART.border < 0 || aPART.border >= freeBorders.borders.length() )
4655 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
4657 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
4659 if ( aPART.node1 < 0 || aPART.node1 > aBRD.nodeIDs.length() )
4660 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
4661 if ( aPART.node2 < 0 || aPART.node2 > aBRD.nodeIDs.length() )
4662 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
4663 if ( aPART.nodeLast < 0 || aPART.nodeLast > aBRD.nodeIDs.length() )
4664 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4666 // do not keep these nodes for further sewing as nodes can be removed by the sewing
4667 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
4668 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
4669 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
4671 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
4673 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
4675 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4677 borderNodes.push_back( n1 );
4678 borderNodes.push_back( n2 );
4679 borderNodes.push_back( n3 );
4681 groups.push_back( borderNodes );
4684 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
4685 // to get nodes that replace other nodes during merge we create 0D elements
4686 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
4689 vector< const SMDS_MeshElement* > tmp0Delems;
4690 for ( size_t i = 0; i < groups.size(); ++i )
4692 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4693 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4695 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
4697 tmp0Delems.push_back( it0D->next() );
4699 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
4703 // cout << endl << "INIT" << endl;
4704 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4706 // cout << i << " ";
4707 // if ( i % 3 == 0 ) cout << "^ ";
4708 // tmp0Delems[i]->GetNode(0)->Print( cout );
4713 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
4715 for ( size_t i = 0; i < groups.size(); ++i )
4717 bool isBordToBord = true;
4718 bool groupSewed = false;
4719 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4720 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
4722 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
4723 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
4724 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
4726 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
4727 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
4728 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
4730 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
4733 // TIDSortedElemSet emptySet, avoidSet;
4734 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
4736 // cout << "WRONG 2nd 1" << endl;
4737 // n0->Print( cout );
4738 // n1->Print( cout );
4740 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
4742 // cout << "WRONG 2nd 2" << endl;
4743 // n3->Print( cout );
4744 // n4->Print( cout );
4747 if ( !isBordToBord )
4749 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
4750 n2 = 0; // and n2 is not used
4752 // 1st border moves to 2nd
4753 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
4755 /*2ndIsFreeBorder=*/ isBordToBord,
4756 createPolygons, createPolyhedra);
4757 groupSewed = ( res == ok );
4759 isBordToBord = false;
4760 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
4761 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
4763 // cout << t << " ";
4764 // if ( t % 3 == 0 ) cout << "^ ";
4765 // tmp0Delems[t]->GetNode(0)->Print( cout );
4768 i0D += nodes.size();
4769 nbSewed += groupSewed;
4772 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
4773 << freeBorders << ", "
4774 << createPolygons << ", "
4775 << createPolyhedra << " )";
4777 SMESH_CATCH( SMESH::doNothing );
4779 declareMeshModified( /*isReComputeSafe=*/false );
4781 // remove tmp 0D elements
4783 set< const SMDS_MeshElement* > removed0D;
4784 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4786 if ( removed0D.insert( tmp0Delems[i] ).second )
4787 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
4789 SMESH_CATCH( SMESH::throwCorbaException );
4794 //=======================================================================
4795 //function : SewFreeBorders
4797 //=======================================================================
4799 SMESH::SMESH_MeshEditor::Sew_Error
4800 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4801 CORBA::Long SecondNodeID1,
4802 CORBA::Long LastNodeID1,
4803 CORBA::Long FirstNodeID2,
4804 CORBA::Long SecondNodeID2,
4805 CORBA::Long LastNodeID2,
4806 CORBA::Boolean CreatePolygons,
4807 CORBA::Boolean CreatePolyedrs)
4808 throw (SALOME::SALOME_Exception)
4813 SMESHDS_Mesh* aMesh = getMeshDS();
4815 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4816 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4817 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4818 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4819 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4820 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4822 if (!aBorderFirstNode ||
4823 !aBorderSecondNode||
4825 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4826 if (!aSide2FirstNode ||
4827 !aSide2SecondNode ||
4829 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4831 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4832 << FirstNodeID1 << ", "
4833 << SecondNodeID1 << ", "
4834 << LastNodeID1 << ", "
4835 << FirstNodeID2 << ", "
4836 << SecondNodeID2 << ", "
4837 << LastNodeID2 << ", "
4838 << CreatePolygons<< ", "
4839 << CreatePolyedrs<< " )";
4841 SMESH::SMESH_MeshEditor::Sew_Error error =
4842 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4853 declareMeshModified( /*isReComputeSafe=*/false );
4856 SMESH_CATCH( SMESH::throwCorbaException );
4857 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4861 //=======================================================================
4862 //function : SewConformFreeBorders
4864 //=======================================================================
4866 SMESH::SMESH_MeshEditor::Sew_Error
4867 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4868 CORBA::Long SecondNodeID1,
4869 CORBA::Long LastNodeID1,
4870 CORBA::Long FirstNodeID2,
4871 CORBA::Long SecondNodeID2)
4872 throw (SALOME::SALOME_Exception)
4877 SMESHDS_Mesh* aMesh = getMeshDS();
4879 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4880 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4881 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4882 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4883 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4884 const SMDS_MeshNode* aSide2ThirdNode = 0;
4886 if (!aBorderFirstNode ||
4887 !aBorderSecondNode||
4889 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4890 if (!aSide2FirstNode ||
4892 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4894 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4895 << FirstNodeID1 << ", "
4896 << SecondNodeID1 << ", "
4897 << LastNodeID1 << ", "
4898 << FirstNodeID2 << ", "
4899 << SecondNodeID2 << " )";
4901 SMESH::SMESH_MeshEditor::Sew_Error error =
4902 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4911 declareMeshModified( /*isReComputeSafe=*/false );
4914 SMESH_CATCH( SMESH::throwCorbaException );
4915 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4919 //=======================================================================
4920 //function : SewBorderToSide
4922 //=======================================================================
4924 SMESH::SMESH_MeshEditor::Sew_Error
4925 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4926 CORBA::Long SecondNodeIDOnFreeBorder,
4927 CORBA::Long LastNodeIDOnFreeBorder,
4928 CORBA::Long FirstNodeIDOnSide,
4929 CORBA::Long LastNodeIDOnSide,
4930 CORBA::Boolean CreatePolygons,
4931 CORBA::Boolean CreatePolyedrs)
4932 throw (SALOME::SALOME_Exception)
4937 SMESHDS_Mesh* aMesh = getMeshDS();
4939 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4940 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4941 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4942 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4943 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4944 const SMDS_MeshNode* aSide2ThirdNode = 0;
4946 if (!aBorderFirstNode ||
4947 !aBorderSecondNode||
4949 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4950 if (!aSide2FirstNode ||
4952 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4954 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4955 << FirstNodeIDOnFreeBorder << ", "
4956 << SecondNodeIDOnFreeBorder << ", "
4957 << LastNodeIDOnFreeBorder << ", "
4958 << FirstNodeIDOnSide << ", "
4959 << LastNodeIDOnSide << ", "
4960 << CreatePolygons << ", "
4961 << CreatePolyedrs << ") ";
4963 SMESH::SMESH_MeshEditor::Sew_Error error =
4964 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4974 declareMeshModified( /*isReComputeSafe=*/false );
4977 SMESH_CATCH( SMESH::throwCorbaException );
4978 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4982 //=======================================================================
4983 //function : SewSideElements
4985 //=======================================================================
4987 SMESH::SMESH_MeshEditor::Sew_Error
4988 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4989 const SMESH::long_array& IDsOfSide2Elements,
4990 CORBA::Long NodeID1OfSide1ToMerge,
4991 CORBA::Long NodeID1OfSide2ToMerge,
4992 CORBA::Long NodeID2OfSide1ToMerge,
4993 CORBA::Long NodeID2OfSide2ToMerge)
4994 throw (SALOME::SALOME_Exception)
4999 SMESHDS_Mesh* aMesh = getMeshDS();
5001 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5002 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5003 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5004 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5006 if (!aFirstNode1ToMerge ||
5007 !aFirstNode2ToMerge )
5008 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5009 if (!aSecondNode1ToMerge||
5010 !aSecondNode2ToMerge)
5011 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5013 TIDSortedElemSet aSide1Elems, aSide2Elems;
5014 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5015 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5017 TPythonDump() << "error = " << this << ".SewSideElements( "
5018 << IDsOfSide1Elements << ", "
5019 << IDsOfSide2Elements << ", "
5020 << NodeID1OfSide1ToMerge << ", "
5021 << NodeID1OfSide2ToMerge << ", "
5022 << NodeID2OfSide1ToMerge << ", "
5023 << NodeID2OfSide2ToMerge << ")";
5025 SMESH::SMESH_MeshEditor::Sew_Error error =
5026 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5029 aSecondNode1ToMerge,
5030 aSecondNode2ToMerge));
5032 declareMeshModified( /*isReComputeSafe=*/false );
5035 SMESH_CATCH( SMESH::throwCorbaException );
5036 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5039 //================================================================================
5041 * \brief Set new nodes for given element
5042 * \param ide - element id
5043 * \param newIDs - new node ids
5044 * \retval CORBA::Boolean - true if result is OK
5046 //================================================================================
5048 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5049 const SMESH::long_array& newIDs)
5050 throw (SALOME::SALOME_Exception)
5055 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5056 if(!elem) return false;
5058 int nbn = newIDs.length();
5060 vector<const SMDS_MeshNode*> aNodes(nbn);
5063 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5066 aNodes[nbn1] = aNode;
5069 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5070 << ide << ", " << newIDs << " )";
5072 MESSAGE("ChangeElementNodes");
5073 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5075 declareMeshModified( /*isReComputeSafe=*/ !res );
5079 SMESH_CATCH( SMESH::throwCorbaException );
5083 //=======================================================================
5085 * \brief Makes a part of the mesh quadratic or bi-quadratic
5087 //=======================================================================
5089 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5090 CORBA::Boolean theToBiQuad,
5091 SMESH::SMESH_IDSource_ptr theObject)
5092 throw (SALOME::SALOME_Exception)
5097 TIDSortedElemSet elems;
5099 if ( !( elemsOK = CORBA::is_nil( theObject )))
5101 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5102 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5106 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5107 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5109 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5110 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5112 declareMeshModified( /*isReComputeSafe=*/false );
5115 SMESH_CATCH( SMESH::throwCorbaException );
5118 //=======================================================================
5119 //function : ConvertFromQuadratic
5121 //=======================================================================
5123 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5124 throw (SALOME::SALOME_Exception)
5129 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5130 TPythonDump() << this << ".ConvertFromQuadratic()";
5131 declareMeshModified( /*isReComputeSafe=*/!isDone );
5134 SMESH_CATCH( SMESH::throwCorbaException );
5138 //=======================================================================
5139 //function : ConvertToQuadratic
5141 //=======================================================================
5143 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5144 throw (SALOME::SALOME_Exception)
5146 convertToQuadratic( theForce3d, false );
5147 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5150 //================================================================================
5152 * \brief Makes a part of the mesh quadratic
5154 //================================================================================
5156 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5157 SMESH::SMESH_IDSource_ptr theObject)
5158 throw (SALOME::SALOME_Exception)
5160 convertToQuadratic( theForce3d, false, theObject );
5161 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5164 //================================================================================
5166 * \brief Makes a part of the mesh bi-quadratic
5168 //================================================================================
5170 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5171 SMESH::SMESH_IDSource_ptr theObject)
5172 throw (SALOME::SALOME_Exception)
5174 convertToQuadratic( theForce3d, true, theObject );
5175 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5178 //================================================================================
5180 * \brief Makes a part of the mesh linear
5182 //================================================================================
5184 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5185 throw (SALOME::SALOME_Exception)
5192 TIDSortedElemSet elems;
5193 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5195 if ( elems.empty() )
5197 ConvertFromQuadratic();
5199 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5201 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5205 getEditor().ConvertFromQuadratic(elems);
5208 declareMeshModified( /*isReComputeSafe=*/false );
5210 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5212 SMESH_CATCH( SMESH::throwCorbaException );
5215 //=======================================================================
5216 //function : makeMesh
5217 //purpose : create a named imported mesh
5218 //=======================================================================
5220 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5222 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5223 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5224 SALOMEDS::Study_var study = gen->GetCurrentStudy();
5225 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5226 gen->SetName( meshSO, theMeshName, "Mesh" );
5227 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5229 return mesh._retn();
5232 //=======================================================================
5233 //function : dumpGroupsList
5235 //=======================================================================
5237 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5238 const SMESH::ListOfGroups * theGroupList)
5240 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5241 if ( isDumpGroupList )
5242 theDumpPython << theGroupList << " = ";
5245 //================================================================================
5247 \brief Generates the unique group name.
5248 \param thePrefix name prefix
5251 //================================================================================
5253 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
5255 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5256 set<string> groupNames;
5258 // Get existing group names
5259 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5260 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5261 if (CORBA::is_nil(aGroup))
5264 CORBA::String_var name = aGroup->GetName();
5265 groupNames.insert( name.in() );
5269 string name = thePrefix;
5272 while (!groupNames.insert(name).second)
5273 name = SMESH_Comment( thePrefix ) << "_" << index++;
5278 //================================================================================
5280 * \brief Prepare SMESH_IDSource for work
5282 //================================================================================
5284 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5286 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5288 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5289 filter->SetMesh( mesh );
5292 //================================================================================
5294 * \brief Retrieve elements of given type from SMESH_IDSource
5296 //================================================================================
5298 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5299 const SMESHDS_Mesh* theMeshDS,
5300 TIDSortedElemSet& theElemSet,
5301 const SMDSAbs_ElementType theType,
5302 const bool emptyIfIsMesh,
5303 IDSource_Error* error)
5306 if ( error ) *error = IDSource_OK;
5308 if ( CORBA::is_nil( theIDSource ) )
5310 if ( error ) *error = IDSource_INVALID;
5313 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5315 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5316 *error = IDSource_EMPTY;
5319 prepareIdSource( theIDSource );
5320 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5321 if ( anIDs->length() == 0 )
5323 if ( error ) *error = IDSource_EMPTY;
5326 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5327 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5329 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5331 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5335 if ( error ) *error = IDSource_INVALID;
5341 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5342 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5344 if ( error ) *error = IDSource_INVALID;
5351 //================================================================================
5353 * \brief Duplicates given elements, i.e. creates new elements based on the
5354 * same nodes as the given ones.
5355 * \param theElements - container of elements to duplicate.
5356 * \param theGroupName - a name of group to contain the generated elements.
5357 * If a group with such a name already exists, the new elements
5358 * are added to the existng group, else a new group is created.
5359 * If \a theGroupName is empty, new elements are not added
5361 * \return a group where the new elements are added. NULL if theGroupName == "".
5364 //================================================================================
5366 SMESH::SMESH_Group_ptr
5367 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5368 const char* theGroupName)
5369 throw (SALOME::SALOME_Exception)
5371 SMESH::SMESH_Group_var newGroup;
5378 TIDSortedElemSet elems;
5379 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5381 getEditor().DoubleElements( elems );
5383 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5386 SMESH::ElementType type =
5387 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5388 // find existing group
5389 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5390 for ( size_t i = 0; i < groups->length(); ++i )
5391 if ( groups[i]->GetType() == type )
5393 CORBA::String_var name = groups[i]->GetName();
5394 if ( strcmp( name, theGroupName ) == 0 ) {
5395 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5399 // create a new group
5400 if ( newGroup->_is_nil() )
5401 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5403 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5405 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5406 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5407 for ( int i = 1; i <= aSeq.Length(); i++ )
5408 groupDS->SMDSGroup().Add( aSeq(i) );
5413 if ( !newGroup->_is_nil() )
5414 pyDump << newGroup << " = ";
5415 pyDump << this << ".DoubleElements( "
5416 << theElements << ", " << "'" << theGroupName <<"')";
5418 SMESH_CATCH( SMESH::throwCorbaException );
5420 return newGroup._retn();
5423 //================================================================================
5425 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5426 \param theNodes - identifiers of nodes to be doubled
5427 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5428 nodes. If list of element identifiers is empty then nodes are doubled but
5429 they not assigned to elements
5430 \return TRUE if operation has been completed successfully, FALSE otherwise
5431 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5433 //================================================================================
5435 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5436 const SMESH::long_array& theModifiedElems )
5437 throw (SALOME::SALOME_Exception)
5442 list< int > aListOfNodes;
5444 for ( i = 0, n = theNodes.length(); i < n; i++ )
5445 aListOfNodes.push_back( theNodes[ i ] );
5447 list< int > aListOfElems;
5448 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5449 aListOfElems.push_back( theModifiedElems[ i ] );
5451 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5453 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5455 // Update Python script
5456 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5460 SMESH_CATCH( SMESH::throwCorbaException );
5464 //================================================================================
5466 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5467 This method provided for convenience works as DoubleNodes() described above.
5468 \param theNodeId - identifier of node to be doubled.
5469 \param theModifiedElems - identifiers of elements to be updated.
5470 \return TRUE if operation has been completed successfully, FALSE otherwise
5471 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5473 //================================================================================
5475 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5476 const SMESH::long_array& theModifiedElems )
5477 throw (SALOME::SALOME_Exception)
5480 SMESH::long_array_var aNodes = new SMESH::long_array;
5481 aNodes->length( 1 );
5482 aNodes[ 0 ] = theNodeId;
5484 TPythonDump pyDump; // suppress dump by the next line
5486 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5488 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5492 SMESH_CATCH( SMESH::throwCorbaException );
5496 //================================================================================
5498 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5499 This method provided for convenience works as DoubleNodes() described above.
5500 \param theNodes - group of nodes to be doubled.
5501 \param theModifiedElems - group of elements to be updated.
5502 \return TRUE if operation has been completed successfully, FALSE otherwise
5503 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5505 //================================================================================
5507 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5508 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5509 throw (SALOME::SALOME_Exception)
5512 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5515 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5516 SMESH::long_array_var aModifiedElems;
5517 if ( !CORBA::is_nil( theModifiedElems ) )
5518 aModifiedElems = theModifiedElems->GetListOfID();
5521 aModifiedElems = new SMESH::long_array;
5522 aModifiedElems->length( 0 );
5525 TPythonDump pyDump; // suppress dump by the next line
5527 bool done = DoubleNodes( aNodes, aModifiedElems );
5529 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5533 SMESH_CATCH( SMESH::throwCorbaException );
5537 //================================================================================
5539 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5540 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5541 * \param theNodes - group of nodes to be doubled.
5542 * \param theModifiedElems - group of elements to be updated.
5543 * \return a new group with newly created nodes
5544 * \sa DoubleNodeGroup()
5546 //================================================================================
5548 SMESH::SMESH_Group_ptr
5549 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5550 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5551 throw (SALOME::SALOME_Exception)
5554 SMESH::SMESH_Group_var aNewGroup;
5556 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5557 return aNewGroup._retn();
5560 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5561 SMESH::long_array_var aModifiedElems;
5562 if ( !CORBA::is_nil( theModifiedElems ) )
5563 aModifiedElems = theModifiedElems->GetListOfID();
5565 aModifiedElems = new SMESH::long_array;
5566 aModifiedElems->length( 0 );
5569 TPythonDump pyDump; // suppress dump by the next line
5571 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5574 // Create group with newly created nodes
5575 SMESH::long_array_var anIds = GetLastCreatedNodes();
5576 if (anIds->length() > 0) {
5577 string anUnindexedName (theNodes->GetName());
5578 string aNewName = generateGroupName(anUnindexedName + "_double");
5579 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5580 aNewGroup->Add(anIds);
5581 pyDump << aNewGroup << " = ";
5585 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5586 << theModifiedElems << " )";
5588 return aNewGroup._retn();
5590 SMESH_CATCH( SMESH::throwCorbaException );
5594 //================================================================================
5596 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5597 This method provided for convenience works as DoubleNodes() described above.
5598 \param theNodes - list of groups of nodes to be doubled
5599 \param theModifiedElems - list of groups of elements to be updated.
5600 \return TRUE if operation has been completed successfully, FALSE otherwise
5601 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5603 //================================================================================
5605 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5606 const SMESH::ListOfGroups& theModifiedElems )
5607 throw (SALOME::SALOME_Exception)
5612 std::list< int > aNodes;
5614 for ( i = 0, n = theNodes.length(); i < n; i++ )
5616 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5617 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5619 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5620 for ( j = 0, m = aCurr->length(); j < m; j++ )
5621 aNodes.push_back( aCurr[ j ] );
5625 std::list< int > anElems;
5626 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5628 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5629 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5631 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5632 for ( j = 0, m = aCurr->length(); j < m; j++ )
5633 anElems.push_back( aCurr[ j ] );
5637 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5639 declareMeshModified( /*isReComputeSafe=*/false );
5641 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5645 SMESH_CATCH( SMESH::throwCorbaException );
5649 //================================================================================
5651 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5652 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5653 * \param theNodes - group of nodes to be doubled.
5654 * \param theModifiedElems - group of elements to be updated.
5655 * \return a new group with newly created nodes
5656 * \sa DoubleNodeGroups()
5658 //================================================================================
5660 SMESH::SMESH_Group_ptr
5661 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5662 const SMESH::ListOfGroups& theModifiedElems )
5663 throw (SALOME::SALOME_Exception)
5665 SMESH::SMESH_Group_var aNewGroup;
5667 TPythonDump pyDump; // suppress dump by the next line
5669 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5673 // Create group with newly created nodes
5674 SMESH::long_array_var anIds = GetLastCreatedNodes();
5675 if (anIds->length() > 0) {
5676 string anUnindexedName (theNodes[0]->GetName());
5677 string aNewName = generateGroupName(anUnindexedName + "_double");
5678 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5679 aNewGroup->Add(anIds);
5680 pyDump << aNewGroup << " = ";
5684 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5685 << theModifiedElems << " )";
5687 return aNewGroup._retn();
5691 //================================================================================
5693 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5694 \param theElems - the list of elements (edges or faces) to be replicated
5695 The nodes for duplication could be found from these elements
5696 \param theNodesNot - list of nodes to NOT replicate
5697 \param theAffectedElems - the list of elements (cells and edges) to which the
5698 replicated nodes should be associated to.
5699 \return TRUE if operation has been completed successfully, FALSE otherwise
5700 \sa DoubleNodeGroup(), DoubleNodeGroups()
5702 //================================================================================
5704 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5705 const SMESH::long_array& theNodesNot,
5706 const SMESH::long_array& theAffectedElems )
5707 throw (SALOME::SALOME_Exception)
5712 SMESHDS_Mesh* aMeshDS = getMeshDS();
5713 TIDSortedElemSet anElems, aNodes, anAffected;
5714 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5715 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5716 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5718 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5720 // Update Python script
5721 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5722 << theNodesNot << ", " << theAffectedElems << " )";
5724 declareMeshModified( /*isReComputeSafe=*/false );
5727 SMESH_CATCH( SMESH::throwCorbaException );
5731 //================================================================================
5733 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5734 \param theElems - the list of elements (edges or faces) to be replicated
5735 The nodes for duplication could be found from these elements
5736 \param theNodesNot - list of nodes to NOT replicate
5737 \param theShape - shape to detect affected elements (element which geometric center
5738 located on or inside shape).
5739 The replicated nodes should be associated to affected elements.
5740 \return TRUE if operation has been completed successfully, FALSE otherwise
5741 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5743 //================================================================================
5745 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5746 const SMESH::long_array& theNodesNot,
5747 GEOM::GEOM_Object_ptr theShape )
5748 throw (SALOME::SALOME_Exception)
5754 SMESHDS_Mesh* aMeshDS = getMeshDS();
5755 TIDSortedElemSet anElems, aNodes;
5756 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5757 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5759 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5760 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5762 // Update Python script
5763 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5764 << theNodesNot << ", " << theShape << " )";
5766 declareMeshModified( /*isReComputeSafe=*/false );
5769 SMESH_CATCH( SMESH::throwCorbaException );
5773 //================================================================================
5775 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5776 \param theElems - group of of elements (edges or faces) to be replicated
5777 \param theNodesNot - group of nodes not to replicated
5778 \param theAffectedElems - group of elements to which the replicated nodes
5779 should be associated to.
5780 \return TRUE if operation has been completed successfully, FALSE otherwise
5781 \sa DoubleNodes(), DoubleNodeGroups()
5783 //================================================================================
5786 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5787 SMESH::SMESH_GroupBase_ptr theNodesNot,
5788 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5789 throw (SALOME::SALOME_Exception)
5792 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5798 SMESHDS_Mesh* aMeshDS = getMeshDS();
5799 TIDSortedElemSet anElems, aNodes, anAffected;
5800 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5801 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5802 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5804 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5806 // Update Python script
5807 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5808 << theNodesNot << ", " << theAffectedElems << " )";
5810 declareMeshModified( /*isReComputeSafe=*/false );
5813 SMESH_CATCH( SMESH::throwCorbaException );
5817 //================================================================================
5819 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5820 * Works as DoubleNodeElemGroup(), but returns a new group with newly created 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 a new group with newly created elements
5826 * \sa DoubleNodeElemGroup()
5828 //================================================================================
5830 SMESH::SMESH_Group_ptr
5831 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5832 SMESH::SMESH_GroupBase_ptr theNodesNot,
5833 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5834 throw (SALOME::SALOME_Exception)
5837 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5841 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5842 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5844 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5846 << theNodesNot << ", "
5847 << theAffectedElems << " )";
5849 return elemGroup._retn();
5852 //================================================================================
5854 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5855 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5856 * \param theElems - group of of elements (edges or faces) to be replicated
5857 * \param theNodesNot - group of nodes not to replicated
5858 * \param theAffectedElems - group of elements to which the replicated nodes
5859 * should be associated to.
5860 * \return a new group with newly created elements
5861 * \sa DoubleNodeElemGroup()
5863 //================================================================================
5865 SMESH::ListOfGroups*
5866 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5867 SMESH::SMESH_GroupBase_ptr theNodesNot,
5868 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5869 CORBA::Boolean theElemGroupNeeded,
5870 CORBA::Boolean theNodeGroupNeeded)
5871 throw (SALOME::SALOME_Exception)
5874 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5875 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5876 aTwoGroups->length( 2 );
5878 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5879 return aTwoGroups._retn();
5884 SMESHDS_Mesh* aMeshDS = getMeshDS();
5885 TIDSortedElemSet anElems, aNodes, anAffected;
5886 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5887 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5888 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5891 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5893 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5899 // Create group with newly created elements
5900 CORBA::String_var elemGroupName = theElems->GetName();
5901 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5902 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5904 SMESH::long_array_var anIds = GetLastCreatedElems();
5905 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5906 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5907 aNewElemGroup->Add(anIds);
5909 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5911 SMESH::long_array_var anIds = GetLastCreatedNodes();
5912 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5913 aNewNodeGroup->Add(anIds);
5917 // Update Python script
5920 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5921 else pyDump << aNewElemGroup << ", ";
5922 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5923 else pyDump << aNewNodeGroup << " ] = ";
5925 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5926 << theNodesNot << ", "
5927 << theAffectedElems << ", "
5928 << theElemGroupNeeded << ", "
5929 << theNodeGroupNeeded <<" )";
5931 aTwoGroups[0] = aNewElemGroup._retn();
5932 aTwoGroups[1] = aNewNodeGroup._retn();
5933 return aTwoGroups._retn();
5935 SMESH_CATCH( SMESH::throwCorbaException );
5939 //================================================================================
5941 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5942 \param theElems - group of of elements (edges or faces) to be replicated
5943 \param theNodesNot - group of nodes not to replicated
5944 \param theShape - shape to detect affected elements (element which geometric center
5945 located on or inside shape).
5946 The replicated nodes should be associated to affected elements.
5947 \return TRUE if operation has been completed successfully, FALSE otherwise
5948 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5950 //================================================================================
5953 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5954 SMESH::SMESH_GroupBase_ptr theNodesNot,
5955 GEOM::GEOM_Object_ptr theShape )
5956 throw (SALOME::SALOME_Exception)
5959 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5965 SMESHDS_Mesh* aMeshDS = getMeshDS();
5966 TIDSortedElemSet anElems, aNodes, anAffected;
5967 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5968 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5970 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5971 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5974 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5976 // Update Python script
5977 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5978 << theNodesNot << ", " << theShape << " )";
5981 SMESH_CATCH( SMESH::throwCorbaException );
5985 //================================================================================
5987 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5988 * \param [in] theGrpList - groups
5989 * \param [in] theMeshDS - mesh
5990 * \param [out] theElemSet - set of elements
5991 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5993 //================================================================================
5995 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5996 SMESHDS_Mesh* theMeshDS,
5997 TIDSortedElemSet& theElemSet,
5998 const bool theIsNodeGrp)
6000 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6002 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6003 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6004 : aGrp->GetType() != SMESH::NODE ) )
6006 SMESH::long_array_var anIDs = aGrp->GetIDs();
6007 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6012 //================================================================================
6014 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6015 This method provided for convenience works as DoubleNodes() described above.
6016 \param theElems - list of groups of elements (edges or faces) to be replicated
6017 \param theNodesNot - list of groups of nodes not to replicated
6018 \param theAffectedElems - group of elements to which the replicated nodes
6019 should be associated to.
6020 \return TRUE if operation has been completed successfully, FALSE otherwise
6021 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6023 //================================================================================
6026 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6027 const SMESH::ListOfGroups& theNodesNot,
6028 const SMESH::ListOfGroups& theAffectedElems)
6029 throw (SALOME::SALOME_Exception)
6035 SMESHDS_Mesh* aMeshDS = getMeshDS();
6036 TIDSortedElemSet anElems, aNodes, anAffected;
6037 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6038 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6039 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6041 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6043 // Update Python script
6044 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6045 << &theNodesNot << ", " << &theAffectedElems << " )";
6047 declareMeshModified( /*isReComputeSafe=*/false );
6050 SMESH_CATCH( SMESH::throwCorbaException );
6054 //================================================================================
6056 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6057 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6058 \param theElems - list of groups of elements (edges or faces) to be replicated
6059 \param theNodesNot - list of groups of nodes not to replicated
6060 \param theAffectedElems - group of elements to which the replicated nodes
6061 should be associated to.
6062 * \return a new group with newly created elements
6063 * \sa DoubleNodeElemGroups()
6065 //================================================================================
6067 SMESH::SMESH_Group_ptr
6068 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6069 const SMESH::ListOfGroups& theNodesNot,
6070 const SMESH::ListOfGroups& theAffectedElems)
6071 throw (SALOME::SALOME_Exception)
6074 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6078 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6079 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6081 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6083 << theNodesNot << ", "
6084 << theAffectedElems << " )";
6086 return elemGroup._retn();
6089 //================================================================================
6091 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6092 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6093 \param theElems - list of groups of elements (edges or faces) to be replicated
6094 \param theNodesNot - list of groups of nodes not to replicated
6095 \param theAffectedElems - group of elements to which the replicated nodes
6096 should be associated to.
6097 * \return a new group with newly created elements
6098 * \sa DoubleNodeElemGroups()
6100 //================================================================================
6102 SMESH::ListOfGroups*
6103 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6104 const SMESH::ListOfGroups& theNodesNot,
6105 const SMESH::ListOfGroups& theAffectedElems,
6106 CORBA::Boolean theElemGroupNeeded,
6107 CORBA::Boolean theNodeGroupNeeded)
6108 throw (SALOME::SALOME_Exception)
6111 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6112 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6113 aTwoGroups->length( 2 );
6118 SMESHDS_Mesh* aMeshDS = getMeshDS();
6119 TIDSortedElemSet anElems, aNodes, anAffected;
6120 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6121 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6122 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6124 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6126 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6131 // Create group with newly created elements
6132 CORBA::String_var elemGroupName = theElems[0]->GetName();
6133 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
6134 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6136 SMESH::long_array_var anIds = GetLastCreatedElems();
6137 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6138 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6139 aNewElemGroup->Add(anIds);
6141 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6143 SMESH::long_array_var anIds = GetLastCreatedNodes();
6144 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6145 aNewNodeGroup->Add(anIds);
6149 // Update Python script
6152 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6153 else pyDump << aNewElemGroup << ", ";
6154 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6155 else pyDump << aNewNodeGroup << " ] = ";
6157 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6158 << &theNodesNot << ", "
6159 << &theAffectedElems << ", "
6160 << theElemGroupNeeded << ", "
6161 << theNodeGroupNeeded << " )";
6163 aTwoGroups[0] = aNewElemGroup._retn();
6164 aTwoGroups[1] = aNewNodeGroup._retn();
6165 return aTwoGroups._retn();
6167 SMESH_CATCH( SMESH::throwCorbaException );
6171 //================================================================================
6173 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6174 This method provided for convenience works as DoubleNodes() described above.
6175 \param theElems - list of groups of elements (edges or faces) to be replicated
6176 \param theNodesNot - list of groups of nodes not to replicated
6177 \param theShape - shape to detect affected elements (element which geometric center
6178 located on or inside shape).
6179 The replicated nodes should be associated to affected elements.
6180 \return TRUE if operation has been completed successfully, FALSE otherwise
6181 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6183 //================================================================================
6186 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6187 const SMESH::ListOfGroups& theNodesNot,
6188 GEOM::GEOM_Object_ptr theShape )
6189 throw (SALOME::SALOME_Exception)
6195 SMESHDS_Mesh* aMeshDS = getMeshDS();
6196 TIDSortedElemSet anElems, aNodes;
6197 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6198 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6200 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6201 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6203 // Update Python script
6204 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6205 << &theNodesNot << ", " << theShape << " )";
6207 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6210 SMESH_CATCH( SMESH::throwCorbaException );
6214 //================================================================================
6216 \brief Identify the elements that will be affected by node duplication (actual
6217 duplication is not performed.
6218 This method is the first step of DoubleNodeElemGroupsInRegion.
6219 \param theElems - list of groups of elements (edges or faces) to be replicated
6220 \param theNodesNot - list of groups of nodes not to replicated
6221 \param theShape - shape to detect affected elements (element which geometric center
6222 located on or inside shape).
6223 The replicated nodes should be associated to affected elements.
6224 \return groups of affected elements
6225 \sa DoubleNodeElemGroupsInRegion()
6227 //================================================================================
6228 SMESH::ListOfGroups*
6229 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6230 const SMESH::ListOfGroups& theNodesNot,
6231 GEOM::GEOM_Object_ptr theShape )
6232 throw (SALOME::SALOME_Exception)
6235 MESSAGE("AffectedElemGroupsInRegion");
6236 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6237 bool isEdgeGroup = false;
6238 bool isFaceGroup = false;
6239 bool isVolumeGroup = false;
6240 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6241 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6242 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6246 ::SMESH_MeshEditor aMeshEditor(myMesh);
6248 SMESHDS_Mesh* aMeshDS = getMeshDS();
6249 TIDSortedElemSet anElems, aNodes;
6250 listOfGroupToSet(theElems, aMeshDS, anElems, false);
6251 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6253 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6254 TIDSortedElemSet anAffected;
6255 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6258 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6263 int lg = anAffected.size();
6264 MESSAGE("lg="<< lg);
6265 SMESH::long_array_var volumeIds = new SMESH::long_array;
6266 volumeIds->length(lg);
6267 SMESH::long_array_var faceIds = new SMESH::long_array;
6268 faceIds->length(lg);
6269 SMESH::long_array_var edgeIds = new SMESH::long_array;
6270 edgeIds->length(lg);
6275 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6276 for (; eIt != anAffected.end(); ++eIt)
6278 const SMDS_MeshElement* anElem = *eIt;
6281 int elemId = anElem->GetID();
6282 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6283 volumeIds[ivol++] = elemId;
6284 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6285 faceIds[iface++] = elemId;
6286 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6287 edgeIds[iedge++] = elemId;
6289 volumeIds->length(ivol);
6290 faceIds->length(iface);
6291 edgeIds->length(iedge);
6293 aNewVolumeGroup->Add(volumeIds);
6294 aNewFaceGroup->Add(faceIds);
6295 aNewEdgeGroup->Add(edgeIds);
6296 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6297 isFaceGroup = (aNewFaceGroup->Size() > 0);
6298 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6302 if (isEdgeGroup) nbGroups++;
6303 if (isFaceGroup) nbGroups++;
6304 if (isVolumeGroup) nbGroups++;
6305 aListOfGroups->length(nbGroups);
6308 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6309 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6310 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6312 // Update Python script
6315 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6316 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6317 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6319 pyDump << this << ".AffectedElemGroupsInRegion( "
6320 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6322 return aListOfGroups._retn();
6324 SMESH_CATCH( SMESH::throwCorbaException );
6328 //================================================================================
6330 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6331 The created 2D mesh elements based on nodes of free faces of boundary volumes
6332 \return TRUE if operation has been completed successfully, FALSE otherwise
6334 //================================================================================
6336 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6337 throw (SALOME::SALOME_Exception)
6342 bool aResult = getEditor().Make2DMeshFrom3D();
6344 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6346 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6349 SMESH_CATCH( SMESH::throwCorbaException );
6353 //================================================================================
6355 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6356 * The list of groups must contain at least two groups. The groups have to be disjoint:
6357 * no common element into two different groups.
6358 * The nodes of the internal faces at the boundaries of the groups are doubled.
6359 * Optionally, the internal faces are replaced by flat elements.
6360 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6361 * The flat elements are stored in groups of volumes.
6362 * These groups are named according to the position of the group in the list:
6363 * 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.
6364 * 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.
6365 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6366 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6367 * \param theDomains - list of groups of volumes
6368 * \param createJointElems - if TRUE, create the elements
6369 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6370 * the boundary between \a theDomains and the rest mesh
6371 * \return TRUE if operation has been completed successfully, FALSE otherwise
6373 //================================================================================
6376 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6377 CORBA::Boolean createJointElems,
6378 CORBA::Boolean onAllBoundaries )
6379 throw (SALOME::SALOME_Exception)
6386 SMESHDS_Mesh* aMeshDS = getMeshDS();
6388 // MESSAGE("theDomains.length = "<<theDomains.length());
6389 if ( theDomains.length() <= 1 && !onAllBoundaries )
6390 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6392 vector<TIDSortedElemSet> domains;
6393 domains.resize( theDomains.length() );
6395 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6397 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6398 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6400 // if ( aGrp->GetType() != SMESH::VOLUME )
6401 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6402 SMESH::long_array_var anIDs = aGrp->GetIDs();
6403 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6407 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6408 // TODO publish the groups of flat elements in study
6410 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6412 // Update Python script
6413 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6414 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6416 SMESH_CATCH( SMESH::throwCorbaException );
6418 myMesh_i->CreateGroupServants(); // publish created groups if any
6423 //================================================================================
6425 * \brief Double nodes on some external faces and create flat elements.
6426 * Flat elements are mainly used by some types of mechanic calculations.
6428 * Each group of the list must be constituted of faces.
6429 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6430 * @param theGroupsOfFaces - list of groups of faces
6431 * @return TRUE if operation has been completed successfully, FALSE otherwise
6433 //================================================================================
6436 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6437 throw (SALOME::SALOME_Exception)
6442 SMESHDS_Mesh* aMeshDS = getMeshDS();
6444 vector<TIDSortedElemSet> faceGroups;
6447 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6449 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6450 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6452 TIDSortedElemSet faceGroup;
6454 faceGroups.push_back(faceGroup);
6455 SMESH::long_array_var anIDs = aGrp->GetIDs();
6456 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6460 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6461 // TODO publish the groups of flat elements in study
6463 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6465 // Update Python script
6466 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6469 SMESH_CATCH( SMESH::throwCorbaException );
6473 //================================================================================
6475 * \brief Identify all the elements around a geom shape, get the faces delimiting
6478 * Build groups of volume to remove, groups of faces to replace on the skin of the
6479 * object, groups of faces to remove inside the object, (idem edges).
6480 * Build ordered list of nodes at the border of each group of faces to replace
6481 * (to be used to build a geom subshape).
6483 //================================================================================
6485 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6486 GEOM::GEOM_Object_ptr theShape,
6487 const char* groupName,
6488 const SMESH::double_array& theNodesCoords,
6489 SMESH::array_of_long_array_out GroupsOfNodes)
6490 throw (SALOME::SALOME_Exception)
6495 std::vector<std::vector<int> > aListOfListOfNodes;
6496 ::SMESH_MeshEditor aMeshEditor( myMesh );
6498 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6499 if ( !theNodeSearcher )
6500 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6502 vector<double> nodesCoords;
6503 for (int i = 0; i < theNodesCoords.length(); i++)
6505 nodesCoords.push_back( theNodesCoords[i] );
6508 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6509 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6510 nodesCoords, aListOfListOfNodes);
6512 GroupsOfNodes = new SMESH::array_of_long_array;
6513 GroupsOfNodes->length( aListOfListOfNodes.size() );
6514 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6515 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6517 vector<int>& aListOfNodes = *llIt;
6518 vector<int>::iterator lIt = aListOfNodes.begin();;
6519 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6520 aGroup.length( aListOfNodes.size() );
6521 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6522 aGroup[ j ] = (*lIt);
6524 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6527 << ", '" << groupName << "', "
6528 << theNodesCoords << " )";
6530 SMESH_CATCH( SMESH::throwCorbaException );
6533 // issue 20749 ===================================================================
6535 * \brief Creates missing boundary elements
6536 * \param elements - elements whose boundary is to be checked
6537 * \param dimension - defines type of boundary elements to create
6538 * \param groupName - a name of group to store created boundary elements in,
6539 * "" means not to create the group
6540 * \param meshName - a name of new mesh to store created boundary elements in,
6541 * "" means not to create the new mesh
6542 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6543 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6544 * boundary elements will be copied into the new mesh
6545 * \param group - returns the create group, if any
6546 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6548 // ================================================================================
6550 SMESH::SMESH_Mesh_ptr
6551 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6552 SMESH::Bnd_Dimension dim,
6553 const char* groupName,
6554 const char* meshName,
6555 CORBA::Boolean toCopyElements,
6556 CORBA::Boolean toCopyExistingBondary,
6557 SMESH::SMESH_Group_out group)
6558 throw (SALOME::SALOME_Exception)
6563 if ( dim > SMESH::BND_1DFROM2D )
6564 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6566 SMESHDS_Mesh* aMeshDS = getMeshDS();
6568 SMESH::SMESH_Mesh_var mesh_var;
6569 SMESH::SMESH_Group_var group_var;
6573 TIDSortedElemSet elements;
6574 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6575 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6579 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6580 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6582 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6584 // group of new boundary elements
6585 SMESH_Group* smesh_group = 0;
6586 if ( strlen(groupName) )
6588 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6589 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6590 smesh_group = group_i->GetSmeshGroup();
6594 getEditor().MakeBoundaryMesh( elements,
6595 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6599 toCopyExistingBondary);
6602 smesh_mesh->GetMeshDS()->Modified();
6605 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6607 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6608 if ( mesh_var->_is_nil() )
6609 pyDump << myMesh_i->_this() << ", ";
6611 pyDump << mesh_var << ", ";
6612 if ( group_var->_is_nil() )
6613 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6615 pyDump << group_var << " = ";
6616 pyDump << this << ".MakeBoundaryMesh( "
6618 << "SMESH." << dimName[int(dim)] << ", "
6619 << "'" << groupName << "', "
6620 << "'" << meshName<< "', "
6621 << toCopyElements << ", "
6622 << toCopyExistingBondary << ")";
6624 group = group_var._retn();
6625 return mesh_var._retn();
6627 SMESH_CATCH( SMESH::throwCorbaException );
6628 return SMESH::SMESH_Mesh::_nil();
6631 //================================================================================
6633 * \brief Creates missing boundary elements
6634 * \param dimension - defines type of boundary elements to create
6635 * \param groupName - a name of group to store all boundary elements in,
6636 * "" means not to create the group
6637 * \param meshName - a name of a new mesh, which is a copy of the initial
6638 * mesh + created boundary elements; "" means not to create the new mesh
6639 * \param toCopyAll - if true, the whole initial mesh will be copied into
6640 * the new mesh else only boundary elements will be copied into the new mesh
6641 * \param groups - optional groups of elements to make boundary around
6642 * \param mesh - returns the mesh where elements were added to
6643 * \param group - returns the created group, if any
6644 * \retval long - number of added boundary elements
6646 //================================================================================
6648 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6649 const char* groupName,
6650 const char* meshName,
6651 CORBA::Boolean toCopyAll,
6652 const SMESH::ListOfIDSources& groups,
6653 SMESH::SMESH_Mesh_out mesh,
6654 SMESH::SMESH_Group_out group)
6655 throw (SALOME::SALOME_Exception)
6660 if ( dim > SMESH::BND_1DFROM2D )
6661 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6663 // separate groups belonging to this and other mesh
6664 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6665 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6666 groupsOfThisMesh ->length( groups.length() );
6667 groupsOfOtherMesh->length( groups.length() );
6668 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6669 for ( int i = 0; i < groups.length(); ++i )
6671 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6672 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6673 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6675 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6676 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6677 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6679 groupsOfThisMesh->length( nbGroups );
6680 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6685 if ( nbGroupsOfOtherMesh > 0 )
6687 // process groups belonging to another mesh
6688 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6689 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6690 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6691 groupsOfOtherMesh, mesh, group );
6694 SMESH::SMESH_Mesh_var mesh_var;
6695 SMESH::SMESH_Group_var group_var;
6698 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6699 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6703 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6705 /*toCopyGroups=*/false,
6706 /*toKeepIDs=*/true);
6708 mesh_var = makeMesh(meshName);
6710 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6711 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6714 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6715 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6717 // group of boundary elements
6718 SMESH_Group* smesh_group = 0;
6719 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6720 if ( strlen(groupName) )
6722 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6723 group_var = mesh_i->CreateGroup( groupType, groupName );
6724 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6725 smesh_group = group_i->GetSmeshGroup();
6728 TIDSortedElemSet elements;
6730 if ( groups.length() > 0 )
6732 for ( int i = 0; i < nbGroups; ++i )
6735 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6737 SMESH::Bnd_Dimension bdim =
6738 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6739 nbAdded += getEditor().MakeBoundaryMesh( elements,
6740 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6743 /*toCopyElements=*/false,
6744 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6745 /*toAddExistingBondary=*/true,
6746 /*aroundElements=*/true);
6752 nbAdded += getEditor().MakeBoundaryMesh( elements,
6753 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6756 /*toCopyElements=*/false,
6757 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6758 /*toAddExistingBondary=*/true);
6760 tgtMesh->GetMeshDS()->Modified();
6762 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6764 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6765 pyDump << "nbAdded, ";
6766 if ( mesh_var->_is_nil() )
6767 pyDump << myMesh_i->_this() << ", ";
6769 pyDump << mesh_var << ", ";
6770 if ( group_var->_is_nil() )
6771 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6773 pyDump << group_var << " = ";
6774 pyDump << this << ".MakeBoundaryElements( "
6775 << "SMESH." << dimName[int(dim)] << ", "
6776 << "'" << groupName << "', "
6777 << "'" << meshName<< "', "
6778 << toCopyAll << ", "
6781 mesh = mesh_var._retn();
6782 group = group_var._retn();
6785 SMESH_CATCH( SMESH::throwCorbaException );