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 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1068 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1070 // Update Python script
1071 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1073 declareMeshModified( /*isReComputeSafe=*/false );
1074 return elem ? elem->GetID() : 0;
1076 SMESH_CATCH( SMESH::throwCorbaException );
1080 //=============================================================================
1082 * AddQuadPolygonalFace
1084 //=============================================================================
1086 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1087 throw (SALOME::SALOME_Exception)
1092 int NbNodes = IDsOfNodes.length();
1093 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1094 for (int i = 0; i < NbNodes; i++)
1095 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1097 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1099 // Update Python script
1100 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1102 declareMeshModified( /*isReComputeSafe=*/false );
1103 return elem ? elem->GetID() : 0;
1105 SMESH_CATCH( SMESH::throwCorbaException );
1109 //=============================================================================
1111 * Create volume, either linear and quadratic (this is determed
1112 * by number of given nodes)
1114 //=============================================================================
1116 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1117 throw (SALOME::SALOME_Exception)
1122 int NbNodes = IDsOfNodes.length();
1123 vector< const SMDS_MeshNode*> n(NbNodes);
1124 for(int i=0;i<NbNodes;i++)
1125 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1127 SMDS_MeshElement* elem = 0;
1130 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1131 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1132 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1133 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1134 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1135 n[6],n[7],n[8],n[9]);
1137 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1138 n[6],n[7],n[8],n[9],n[10],n[11]);
1140 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1141 n[7],n[8],n[9],n[10],n[11],n[12]);
1143 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1144 n[9],n[10],n[11],n[12],n[13],n[14]);
1146 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1147 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1148 n[15],n[16],n[17],n[18],n[19]);
1150 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1151 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1152 n[15],n[16],n[17],n[18],n[19],
1153 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1157 // Update Python script
1158 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1160 declareMeshModified( /*isReComputeSafe=*/false );
1161 return elem ? elem->GetID() : 0;
1163 SMESH_CATCH( SMESH::throwCorbaException );
1167 //=============================================================================
1169 * AddPolyhedralVolume
1171 //=============================================================================
1172 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1173 const SMESH::long_array & Quantities)
1174 throw (SALOME::SALOME_Exception)
1179 int NbNodes = IDsOfNodes.length();
1180 std::vector<const SMDS_MeshNode*> n (NbNodes);
1181 for (int i = 0; i < NbNodes; i++)
1183 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1184 if (!aNode) return 0;
1188 int NbFaces = Quantities.length();
1189 std::vector<int> q (NbFaces);
1190 for (int j = 0; j < NbFaces; j++)
1191 q[j] = Quantities[j];
1193 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1195 // Update Python script
1196 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1197 << IDsOfNodes << ", " << Quantities << " )";
1199 declareMeshModified( /*isReComputeSafe=*/false );
1200 return elem ? elem->GetID() : 0;
1202 SMESH_CATCH( SMESH::throwCorbaException );
1206 //=============================================================================
1208 * AddPolyhedralVolumeByFaces
1210 //=============================================================================
1212 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1213 throw (SALOME::SALOME_Exception)
1218 int NbFaces = IdsOfFaces.length();
1219 std::vector<const SMDS_MeshNode*> poly_nodes;
1220 std::vector<int> quantities (NbFaces);
1222 for (int i = 0; i < NbFaces; i++) {
1223 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1224 quantities[i] = aFace->NbNodes();
1226 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1227 while (It->more()) {
1228 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1232 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1234 // Update Python script
1235 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1236 << IdsOfFaces << " )";
1238 declareMeshModified( /*isReComputeSafe=*/false );
1239 return elem ? elem->GetID() : 0;
1241 SMESH_CATCH( SMESH::throwCorbaException );
1245 //=============================================================================
1247 // \brief Create 0D elements on all nodes of the given object except those
1248 // nodes on which a 0D element already exists.
1249 // \param theObject object on whose nodes 0D elements will be created.
1250 // \param theGroupName optional name of a group to add 0D elements created
1251 // and/or found on nodes of \a theObject.
1252 // \return an object (a new group or a temporary SMESH_IDSource) holding
1253 // ids of new and/or found 0D elements.
1255 //=============================================================================
1257 SMESH::SMESH_IDSource_ptr
1258 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1259 const char* theGroupName)
1260 throw (SALOME::SALOME_Exception)
1265 SMESH::SMESH_IDSource_var result;
1268 TIDSortedElemSet elements, elems0D;
1269 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1270 getEditor().Create0DElementsOnAllNodes( elements, elems0D );
1272 SMESH::long_array_var newElems = new SMESH::long_array;
1273 newElems->length( elems0D.size() );
1274 TIDSortedElemSet::iterator eIt = elems0D.begin();
1275 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1276 newElems[ i ] = (*eIt)->GetID();
1278 SMESH::SMESH_GroupBase_var groupToFill;
1279 if ( theGroupName && strlen( theGroupName ))
1281 // Get existing group named theGroupName
1282 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1283 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1284 SMESH::SMESH_GroupBase_var group = groups[i];
1285 if ( !group->_is_nil() ) {
1286 CORBA::String_var name = group->GetName();
1287 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1288 groupToFill = group;
1293 if ( groupToFill->_is_nil() )
1294 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1295 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1296 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1299 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1301 group_i->Add( newElems );
1302 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1303 pyDump << groupToFill;
1307 result = MakeIDSource( newElems, SMESH::ELEM0D );
1308 pyDump << "elem0DIDs";
1311 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1312 << theObject << ", '" << theGroupName << "' )";
1314 return result._retn();
1316 SMESH_CATCH( SMESH::throwCorbaException );
1320 //=============================================================================
1322 * \brief Bind a node to a vertex
1323 * \param NodeID - node ID
1324 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1325 * \retval boolean - false if NodeID or VertexID is invalid
1327 //=============================================================================
1329 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1330 throw (SALOME::SALOME_Exception)
1334 SMESHDS_Mesh * mesh = getMeshDS();
1335 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1337 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1339 if ( mesh->MaxShapeIndex() < VertexID )
1340 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1342 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1343 if ( shape.ShapeType() != TopAbs_VERTEX )
1344 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1346 mesh->SetNodeOnVertex( node, VertexID );
1348 myMesh->SetIsModified( true );
1350 SMESH_CATCH( SMESH::throwCorbaException );
1353 //=============================================================================
1355 * \brief Store node position on an edge
1356 * \param NodeID - node ID
1357 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1358 * \param paramOnEdge - parameter on edge where the node is located
1359 * \retval boolean - false if any parameter is invalid
1361 //=============================================================================
1363 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1364 CORBA::Double paramOnEdge)
1365 throw (SALOME::SALOME_Exception)
1369 SMESHDS_Mesh * mesh = getMeshDS();
1370 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1372 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1374 if ( mesh->MaxShapeIndex() < EdgeID )
1375 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1377 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1378 if ( shape.ShapeType() != TopAbs_EDGE )
1379 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1382 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1383 if ( paramOnEdge < f || paramOnEdge > l )
1384 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1386 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1388 myMesh->SetIsModified( true );
1390 SMESH_CATCH( SMESH::throwCorbaException );
1393 //=============================================================================
1395 * \brief Store node position on a face
1396 * \param NodeID - node ID
1397 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1398 * \param u - U parameter on face where the node is located
1399 * \param v - V parameter on face where the node is located
1400 * \retval boolean - false if any parameter is invalid
1402 //=============================================================================
1404 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1405 CORBA::Double u, CORBA::Double v)
1406 throw (SALOME::SALOME_Exception)
1409 SMESHDS_Mesh * mesh = getMeshDS();
1410 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1412 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1414 if ( mesh->MaxShapeIndex() < FaceID )
1415 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1417 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1418 if ( shape.ShapeType() != TopAbs_FACE )
1419 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1421 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1422 bool isOut = ( u < surf.FirstUParameter() ||
1423 u > surf.LastUParameter() ||
1424 v < surf.FirstVParameter() ||
1425 v > surf.LastVParameter() );
1429 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1430 << " u( " << surf.FirstUParameter()
1431 << "," << surf.LastUParameter()
1432 << ") v( " << surf.FirstVParameter()
1433 << "," << surf.LastVParameter() << ")" );
1435 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1438 mesh->SetNodeOnFace( node, FaceID, u, v );
1439 myMesh->SetIsModified( true );
1441 SMESH_CATCH( SMESH::throwCorbaException );
1444 //=============================================================================
1446 * \brief Bind a node to a solid
1447 * \param NodeID - node ID
1448 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1449 * \retval boolean - false if NodeID or SolidID is invalid
1451 //=============================================================================
1453 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1454 throw (SALOME::SALOME_Exception)
1457 SMESHDS_Mesh * mesh = getMeshDS();
1458 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1460 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1462 if ( mesh->MaxShapeIndex() < SolidID )
1463 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1465 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1466 if ( shape.ShapeType() != TopAbs_SOLID &&
1467 shape.ShapeType() != TopAbs_SHELL)
1468 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1470 mesh->SetNodeInVolume( node, SolidID );
1472 SMESH_CATCH( SMESH::throwCorbaException );
1475 //=============================================================================
1477 * \brief Bind an element to a shape
1478 * \param ElementID - element ID
1479 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1481 //=============================================================================
1483 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1484 CORBA::Long ShapeID)
1485 throw (SALOME::SALOME_Exception)
1488 SMESHDS_Mesh * mesh = getMeshDS();
1489 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1491 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1493 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1494 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1496 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1497 if ( shape.ShapeType() != TopAbs_EDGE &&
1498 shape.ShapeType() != TopAbs_FACE &&
1499 shape.ShapeType() != TopAbs_SOLID &&
1500 shape.ShapeType() != TopAbs_SHELL )
1501 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1503 mesh->SetMeshElementOnShape( elem, ShapeID );
1505 myMesh->SetIsModified( true );
1507 SMESH_CATCH( SMESH::throwCorbaException );
1510 //=============================================================================
1514 //=============================================================================
1516 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1517 CORBA::Long NodeID2)
1518 throw (SALOME::SALOME_Exception)
1523 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1524 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1528 // Update Python script
1529 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1530 << NodeID1 << ", " << NodeID2 << " )";
1532 int ret = getEditor().InverseDiag ( n1, n2 );
1534 declareMeshModified( /*isReComputeSafe=*/false );
1537 SMESH_CATCH( SMESH::throwCorbaException );
1541 //=============================================================================
1545 //=============================================================================
1547 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1548 CORBA::Long NodeID2)
1549 throw (SALOME::SALOME_Exception)
1554 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1555 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1559 // Update Python script
1560 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1561 << NodeID1 << ", " << NodeID2 << " )";
1564 bool stat = getEditor().DeleteDiag ( n1, n2 );
1566 declareMeshModified( /*isReComputeSafe=*/!stat );
1570 SMESH_CATCH( SMESH::throwCorbaException );
1574 //=============================================================================
1578 //=============================================================================
1580 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1581 throw (SALOME::SALOME_Exception)
1586 for (int i = 0; i < IDsOfElements.length(); i++)
1588 CORBA::Long index = IDsOfElements[i];
1589 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1591 getEditor().Reorient( elem );
1593 // Update Python script
1594 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1596 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1599 SMESH_CATCH( SMESH::throwCorbaException );
1603 //=============================================================================
1607 //=============================================================================
1609 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1610 throw (SALOME::SALOME_Exception)
1615 TPythonDump aTPythonDump; // suppress dump in Reorient()
1617 prepareIdSource( theObject );
1619 SMESH::long_array_var anElementsId = theObject->GetIDs();
1620 CORBA::Boolean isDone = Reorient(anElementsId);
1622 // Update Python script
1623 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1625 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1628 SMESH_CATCH( SMESH::throwCorbaException );
1632 //=======================================================================
1633 //function : Reorient2D
1634 //purpose : Reorient faces contained in \a the2Dgroup.
1635 // the2Dgroup - the mesh or its part to reorient
1636 // theDirection - desired direction of normal of \a theFace
1637 // theFace - ID of face whose orientation is checked.
1638 // It can be < 1 then \a thePoint is used to find a face.
1639 // thePoint - is used to find a face if \a theFace < 1.
1640 // return number of reoriented elements.
1641 //=======================================================================
1643 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1644 const SMESH::DirStruct& theDirection,
1645 CORBA::Long theFace,
1646 const SMESH::PointStruct& thePoint)
1647 throw (SALOME::SALOME_Exception)
1650 initData(/*deleteSearchers=*/false);
1652 TIDSortedElemSet elements;
1653 IDSource_Error error;
1654 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1655 if ( error == IDSource_EMPTY )
1657 if ( error == IDSource_INVALID )
1658 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1661 const SMDS_MeshElement* face = 0;
1664 face = getMeshDS()->FindElement( theFace );
1666 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1667 if ( face->GetType() != SMDSAbs_Face )
1668 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1672 // create theElementSearcher if needed
1673 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1674 if ( !theElementSearcher )
1676 if ( elements.empty() ) // search in the whole mesh
1678 if ( myMesh->NbFaces() == 0 )
1679 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1681 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1685 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1686 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1688 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1692 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1693 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1696 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1697 if ( !elements.empty() && !elements.count( face ))
1698 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1701 const SMESH::PointStruct * P = &theDirection.PS;
1702 gp_Vec dirVec( P->x, P->y, P->z );
1703 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1704 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1706 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1709 declareMeshModified( /*isReComputeSafe=*/false );
1711 TPythonDump() << this << ".Reorient2D( "
1712 << the2Dgroup << ", "
1713 << theDirection << ", "
1715 << thePoint << " )";
1719 SMESH_CATCH( SMESH::throwCorbaException );
1723 //=======================================================================
1724 //function : Reorient2DBy3D
1725 //purpose : Reorient faces basing on orientation of adjacent volumes.
1726 //=======================================================================
1728 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1729 SMESH::SMESH_IDSource_ptr volumeGroup,
1730 CORBA::Boolean outsideNormal)
1731 throw (SALOME::SALOME_Exception)
1736 TIDSortedElemSet volumes;
1737 IDSource_Error volsError;
1738 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1741 for ( size_t i = 0; i < faceGroups.length(); ++i )
1743 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1745 TIDSortedElemSet faces;
1746 IDSource_Error error;
1747 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1748 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1749 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1750 if ( error == IDSource_OK && volsError != IDSource_OK )
1751 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1753 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1755 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1760 declareMeshModified( /*isReComputeSafe=*/false );
1762 TPythonDump() << this << ".Reorient2DBy3D( "
1763 << faceGroups << ", "
1764 << volumeGroup << ", "
1765 << outsideNormal << " )";
1769 SMESH_CATCH( SMESH::throwCorbaException );
1773 //=============================================================================
1775 * \brief Fuse neighbour triangles into quadrangles.
1777 //=============================================================================
1779 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1780 SMESH::NumericalFunctor_ptr Criterion,
1781 CORBA::Double MaxAngle)
1782 throw (SALOME::SALOME_Exception)
1787 SMESHDS_Mesh* aMesh = getMeshDS();
1788 TIDSortedElemSet faces,copyFaces;
1789 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1790 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1791 TIDSortedElemSet* workElements = & faces;
1793 if ( myIsPreviewMode ) {
1794 SMDSAbs_ElementType select = SMDSAbs_Face;
1795 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1796 workElements = & copyFaces;
1799 SMESH::NumericalFunctor_i* aNumericalFunctor =
1800 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1801 SMESH::Controls::NumericalFunctorPtr aCrit;
1802 if ( !aNumericalFunctor )
1803 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1805 aCrit = aNumericalFunctor->GetNumericalFunctor();
1807 if ( !myIsPreviewMode ) {
1808 // Update Python script
1809 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1810 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1813 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1815 declareMeshModified( /*isReComputeSafe=*/!stat );
1818 SMESH_CATCH( SMESH::throwCorbaException );
1822 //=============================================================================
1824 * \brief Fuse neighbour triangles into quadrangles.
1826 //=============================================================================
1828 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1829 SMESH::NumericalFunctor_ptr Criterion,
1830 CORBA::Double MaxAngle)
1831 throw (SALOME::SALOME_Exception)
1836 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1838 prepareIdSource( theObject );
1839 SMESH::long_array_var anElementsId = theObject->GetIDs();
1840 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1842 if ( !myIsPreviewMode ) {
1843 SMESH::NumericalFunctor_i* aNumericalFunctor =
1844 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1846 // Update Python script
1847 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1848 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1853 SMESH_CATCH( SMESH::throwCorbaException );
1857 //=============================================================================
1859 * \brief Split quadrangles into triangles.
1861 //=============================================================================
1863 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1864 SMESH::NumericalFunctor_ptr Criterion)
1865 throw (SALOME::SALOME_Exception)
1870 SMESHDS_Mesh* aMesh = getMeshDS();
1871 TIDSortedElemSet faces;
1872 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1874 SMESH::NumericalFunctor_i* aNumericalFunctor =
1875 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1876 SMESH::Controls::NumericalFunctorPtr aCrit;
1877 if ( !aNumericalFunctor )
1878 aCrit.reset( new SMESH::Controls::AspectRatio() );
1880 aCrit = aNumericalFunctor->GetNumericalFunctor();
1883 // Update Python script
1884 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1886 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1888 declareMeshModified( /*isReComputeSafe=*/false );
1891 SMESH_CATCH( SMESH::throwCorbaException );
1895 //=============================================================================
1897 * \brief Split quadrangles into triangles.
1899 //=============================================================================
1901 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1902 SMESH::NumericalFunctor_ptr Criterion)
1903 throw (SALOME::SALOME_Exception)
1908 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1910 prepareIdSource( theObject );
1911 SMESH::long_array_var anElementsId = theObject->GetIDs();
1912 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1914 SMESH::NumericalFunctor_i* aNumericalFunctor =
1915 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1917 // Update Python script
1918 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1920 declareMeshModified( /*isReComputeSafe=*/false );
1923 SMESH_CATCH( SMESH::throwCorbaException );
1927 //================================================================================
1929 * \brief Split each of quadrangles into 4 triangles.
1930 * \param [in] theObject - theQuads Container of quadrangles to split.
1932 //================================================================================
1934 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1935 throw (SALOME::SALOME_Exception)
1940 TIDSortedElemSet faces;
1941 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1943 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1945 getEditor().QuadTo4Tri( faces );
1946 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1948 SMESH_CATCH( SMESH::throwCorbaException );
1951 //=============================================================================
1953 * \brief Split quadrangles into triangles.
1955 //=============================================================================
1957 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1958 CORBA::Boolean Diag13)
1959 throw (SALOME::SALOME_Exception)
1964 SMESHDS_Mesh* aMesh = getMeshDS();
1965 TIDSortedElemSet faces;
1966 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1968 // Update Python script
1969 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1970 << IDsOfElements << ", " << Diag13 << " )";
1972 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1974 declareMeshModified( /*isReComputeSafe=*/ !stat );
1977 SMESH_CATCH( SMESH::throwCorbaException );
1981 //=============================================================================
1983 * \brief Split quadrangles into triangles.
1985 //=============================================================================
1987 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1988 CORBA::Boolean Diag13)
1989 throw (SALOME::SALOME_Exception)
1994 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
1996 prepareIdSource( theObject );
1997 SMESH::long_array_var anElementsId = theObject->GetIDs();
1998 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2000 // Update Python script
2001 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2002 << theObject << ", " << Diag13 << " )";
2004 declareMeshModified( /*isReComputeSafe=*/!isDone );
2007 SMESH_CATCH( SMESH::throwCorbaException );
2012 //=============================================================================
2014 * Find better splitting of the given quadrangle.
2015 * \param IDOfQuad ID of the quadrangle to be splitted.
2016 * \param Criterion A criterion to choose a diagonal for splitting.
2017 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2018 * diagonal is better, 0 if error occurs.
2020 //=============================================================================
2022 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2023 SMESH::NumericalFunctor_ptr Criterion)
2024 throw (SALOME::SALOME_Exception)
2029 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2030 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2032 SMESH::NumericalFunctor_i* aNumericalFunctor =
2033 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2034 SMESH::Controls::NumericalFunctorPtr aCrit;
2035 if (aNumericalFunctor)
2036 aCrit = aNumericalFunctor->GetNumericalFunctor();
2038 aCrit.reset(new SMESH::Controls::AspectRatio());
2040 int id = getEditor().BestSplit(quad, aCrit);
2041 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2045 SMESH_CATCH( SMESH::throwCorbaException );
2049 //================================================================================
2051 * \brief Split volumic elements into tetrahedrons
2053 //================================================================================
2055 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2056 CORBA::Short methodFlags)
2057 throw (SALOME::SALOME_Exception)
2062 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2063 const int noneFacet = -1;
2064 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2065 while( volIt->more() )
2066 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2068 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2069 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2071 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2072 << elems << ", " << methodFlags << " )";
2074 SMESH_CATCH( SMESH::throwCorbaException );
2077 //================================================================================
2079 * \brief Split hexahedra into triangular prisms
2080 * \param elems - elements to split
2081 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2082 * to split into triangles
2083 * \param methodFlags - flags passing splitting method:
2084 * 1 - split the hexahedron into 2 prisms
2085 * 2 - split the hexahedron into 4 prisms
2087 //================================================================================
2089 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr elems,
2090 const SMESH::PointStruct & startHexPoint,
2091 const SMESH::DirStruct& facetToSplitNormal,
2092 CORBA::Short methodFlags,
2093 CORBA::Boolean allDomains)
2094 throw (SALOME::SALOME_Exception)
2098 prepareIdSource( elems );
2100 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2103 gp_Dir( facetToSplitNormal.PS.x,
2104 facetToSplitNormal.PS.y,
2105 facetToSplitNormal.PS.z ));
2106 TIDSortedElemSet elemSet;
2107 SMESH::long_array_var anElementsId = elems->GetIDs();
2108 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2109 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2111 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2112 while ( !elemSet.empty() )
2114 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2118 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2119 for ( ; ef != elemFacets.end(); ++ef )
2120 elemSet.erase( ef->first );
2123 if ( methodFlags == 2 )
2124 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2126 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2128 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2129 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2131 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2133 << startHexPoint << ", "
2134 << facetToSplitNormal<< ", "
2135 << methodFlags<< ", "
2136 << allDomains << " )";
2138 SMESH_CATCH( SMESH::throwCorbaException );
2141 //=======================================================================
2144 //=======================================================================
2147 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2148 const SMESH::long_array & IDsOfFixedNodes,
2149 CORBA::Long MaxNbOfIterations,
2150 CORBA::Double MaxAspectRatio,
2151 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2152 throw (SALOME::SALOME_Exception)
2154 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2155 MaxAspectRatio, Method, false );
2159 //=======================================================================
2160 //function : SmoothParametric
2162 //=======================================================================
2165 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2166 const SMESH::long_array & IDsOfFixedNodes,
2167 CORBA::Long MaxNbOfIterations,
2168 CORBA::Double MaxAspectRatio,
2169 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2170 throw (SALOME::SALOME_Exception)
2172 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2173 MaxAspectRatio, Method, true );
2177 //=======================================================================
2178 //function : SmoothObject
2180 //=======================================================================
2183 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2184 const SMESH::long_array & IDsOfFixedNodes,
2185 CORBA::Long MaxNbOfIterations,
2186 CORBA::Double MaxAspectRatio,
2187 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2188 throw (SALOME::SALOME_Exception)
2190 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2191 MaxAspectRatio, Method, false);
2195 //=======================================================================
2196 //function : SmoothParametricObject
2198 //=======================================================================
2201 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2202 const SMESH::long_array & IDsOfFixedNodes,
2203 CORBA::Long MaxNbOfIterations,
2204 CORBA::Double MaxAspectRatio,
2205 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2206 throw (SALOME::SALOME_Exception)
2208 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2209 MaxAspectRatio, Method, true);
2213 //=============================================================================
2217 //=============================================================================
2220 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2221 const SMESH::long_array & IDsOfFixedNodes,
2222 CORBA::Long MaxNbOfIterations,
2223 CORBA::Double MaxAspectRatio,
2224 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2226 throw (SALOME::SALOME_Exception)
2231 SMESHDS_Mesh* aMesh = getMeshDS();
2233 TIDSortedElemSet elements;
2234 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2236 set<const SMDS_MeshNode*> fixedNodes;
2237 for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
2238 CORBA::Long index = IDsOfFixedNodes[i];
2239 const SMDS_MeshNode * node = aMesh->FindNode(index);
2241 fixedNodes.insert( node );
2243 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2244 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2245 method = ::SMESH_MeshEditor::CENTROIDAL;
2247 getEditor().Smooth(elements, fixedNodes, method,
2248 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2250 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2252 // Update Python script
2253 TPythonDump() << "isDone = " << this << "."
2254 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2255 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2256 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2257 << "SMESH.SMESH_MeshEditor."
2258 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2259 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2263 SMESH_CATCH( SMESH::throwCorbaException );
2267 //=============================================================================
2271 //=============================================================================
2274 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2275 const SMESH::long_array & IDsOfFixedNodes,
2276 CORBA::Long MaxNbOfIterations,
2277 CORBA::Double MaxAspectRatio,
2278 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2280 throw (SALOME::SALOME_Exception)
2285 TPythonDump aTPythonDump; // suppress dump in smooth()
2287 prepareIdSource( theObject );
2288 SMESH::long_array_var anElementsId = theObject->GetIDs();
2289 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2290 MaxAspectRatio, Method, IsParametric);
2292 // Update Python script
2293 aTPythonDump << "isDone = " << this << "."
2294 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2295 << theObject << ", " << IDsOfFixedNodes << ", "
2296 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2297 << "SMESH.SMESH_MeshEditor."
2298 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2299 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2303 SMESH_CATCH( SMESH::throwCorbaException );
2307 //=============================================================================
2311 //=============================================================================
2313 void SMESH_MeshEditor_i::RenumberNodes()
2314 throw (SALOME::SALOME_Exception)
2317 // Update Python script
2318 TPythonDump() << this << ".RenumberNodes()";
2320 getMeshDS()->Renumber( true );
2322 SMESH_CATCH( SMESH::throwCorbaException );
2325 //=============================================================================
2329 //=============================================================================
2331 void SMESH_MeshEditor_i::RenumberElements()
2332 throw (SALOME::SALOME_Exception)
2335 // Update Python script
2336 TPythonDump() << this << ".RenumberElements()";
2338 getMeshDS()->Renumber( false );
2340 SMESH_CATCH( SMESH::throwCorbaException );
2343 //=======================================================================
2345 * \brief Return groups by their IDs
2347 //=======================================================================
2349 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2350 throw (SALOME::SALOME_Exception)
2355 myMesh_i->CreateGroupServants();
2356 return myMesh_i->GetGroups( *groupIDs );
2358 SMESH_CATCH( SMESH::throwCorbaException );
2362 //=======================================================================
2363 //function : RotationSweepObjects
2365 //=======================================================================
2367 SMESH::ListOfGroups*
2368 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2369 const SMESH::ListOfIDSources & theEdges,
2370 const SMESH::ListOfIDSources & theFaces,
2371 const SMESH::AxisStruct & theAxis,
2372 CORBA::Double theAngleInRadians,
2373 CORBA::Long theNbOfSteps,
2374 CORBA::Double theTolerance,
2375 const bool theMakeGroups)
2376 throw (SALOME::SALOME_Exception)
2381 TIDSortedElemSet elemsNodes[2];
2382 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2383 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2384 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2386 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2387 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2388 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2389 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2391 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2392 bool makeWalls=true;
2393 if ( myIsPreviewMode )
2395 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2396 TPreviewMesh * tmpMesh = getPreviewMesh();
2397 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2398 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2399 workElements = & copyElements[0];
2400 //makeWalls = false; -- faces are needed for preview
2403 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2405 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2406 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2408 ::SMESH_MeshEditor::PGroupIDs groupIds =
2409 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2410 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2412 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2414 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2416 if ( !myIsPreviewMode )
2418 dumpGroupsList( aPythonDump, aGroups );
2419 aPythonDump << this<< ".RotationSweepObjects( "
2424 << TVar( theAngleInRadians ) << ", "
2425 << TVar( theNbOfSteps ) << ", "
2426 << TVar( theTolerance ) << ", "
2427 << theMakeGroups << " )";
2431 getPreviewMesh()->Remove( SMDSAbs_Volume );
2434 return aGroups ? aGroups : new SMESH::ListOfGroups;
2436 SMESH_CATCH( SMESH::throwCorbaException );
2440 namespace MeshEditor_I
2443 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2445 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2447 bool myIsExtrusionByNormal;
2449 static int makeFlags( CORBA::Boolean MakeGroups,
2450 CORBA::Boolean ByAverageNormal = false,
2451 CORBA::Boolean UseInputElemsOnly = false,
2452 CORBA::Long Flags = 0,
2453 CORBA::Boolean MakeBoundary = true )
2455 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2456 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2457 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2458 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2462 ExtrusionParams(const SMESH::DirStruct & theDir,
2463 CORBA::Long theNbOfSteps,
2464 CORBA::Boolean theMakeGroups):
2465 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2469 makeFlags( theMakeGroups )),
2470 myIsExtrusionByNormal( false )
2474 ExtrusionParams(const SMESH::DirStruct & theDir,
2475 CORBA::Long theNbOfSteps,
2476 CORBA::Boolean theMakeGroups,
2477 CORBA::Long theExtrFlags,
2478 CORBA::Double theSewTolerance):
2479 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2483 makeFlags( theMakeGroups, false, false,
2484 theExtrFlags, false ),
2486 myIsExtrusionByNormal( false )
2489 // params for extrusion by normal
2490 ExtrusionParams(CORBA::Double theStepSize,
2491 CORBA::Long theNbOfSteps,
2492 CORBA::Short theDim,
2493 CORBA::Boolean theByAverageNormal,
2494 CORBA::Boolean theUseInputElemsOnly,
2495 CORBA::Boolean theMakeGroups ):
2496 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2498 makeFlags( theMakeGroups,
2499 theByAverageNormal, theUseInputElemsOnly ),
2501 myIsExtrusionByNormal( true )
2507 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2512 //=======================================================================
2514 * \brief Generate dim+1 elements by extrusion of elements along vector
2515 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2516 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2517 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2518 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2519 * \param [in] nbOfSteps - number of elements to generate from one element
2520 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2521 * corresponding to groups the input elements included in.
2522 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2524 //=======================================================================
2526 SMESH::ListOfGroups*
2527 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2528 const SMESH::ListOfIDSources & theEdges,
2529 const SMESH::ListOfIDSources & theFaces,
2530 const SMESH::DirStruct & theStepVector,
2531 CORBA::Long theNbOfSteps,
2532 CORBA::Boolean theToMakeGroups)
2533 throw (SALOME::SALOME_Exception)
2538 ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
2540 TIDSortedElemSet elemsNodes[2];
2541 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2542 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2543 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2545 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2546 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2547 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2548 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2550 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2551 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2552 if ( myIsPreviewMode )
2554 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2555 // previewType = SMDSAbs_Edge;
2557 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2558 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2559 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2560 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2561 workElements = & copyElements[0];
2563 params.SetNoGroups();
2565 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2567 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2568 ::SMESH_MeshEditor::PGroupIDs groupIds =
2569 getEditor().ExtrusionSweep( workElements, params, aHistory );
2571 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2573 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2575 if ( !myIsPreviewMode )
2577 dumpGroupsList( aPythonDump, aGroups );
2578 aPythonDump << this<< ".ExtrusionSweepObjects( "
2582 << theStepVector << ", "
2583 << TVar( theNbOfSteps ) << ", "
2584 << theToMakeGroups << " )";
2588 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2591 return aGroups ? aGroups : new SMESH::ListOfGroups;
2593 SMESH_CATCH( SMESH::throwCorbaException );
2597 //=======================================================================
2598 //function : ExtrusionByNormal
2600 //=======================================================================
2602 SMESH::ListOfGroups*
2603 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2604 CORBA::Double stepSize,
2605 CORBA::Long nbOfSteps,
2606 CORBA::Boolean byAverageNormal,
2607 CORBA::Boolean useInputElemsOnly,
2608 CORBA::Boolean makeGroups,
2610 throw (SALOME::SALOME_Exception)
2615 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2617 ExtrusionParams params( stepSize, nbOfSteps, dim,
2618 byAverageNormal, useInputElemsOnly, makeGroups );
2620 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2621 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2623 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2624 if (( elemTypes->length() == 1 ) &&
2625 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2626 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2629 TIDSortedElemSet elemsNodes[2];
2630 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2631 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2633 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2634 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2635 if ( myIsPreviewMode )
2637 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2638 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2639 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2640 workElements = & copyElements[0];
2642 params.SetNoGroups();
2645 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2646 ::SMESH_MeshEditor::PGroupIDs groupIds =
2647 getEditor().ExtrusionSweep( workElements, params, aHistory );
2649 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2651 if (!myIsPreviewMode) {
2652 dumpGroupsList(aPythonDump, aGroups);
2653 aPythonDump << this << ".ExtrusionByNormal( " << objects
2654 << ", " << TVar( stepSize )
2655 << ", " << TVar( nbOfSteps )
2656 << ", " << byAverageNormal
2657 << ", " << useInputElemsOnly
2658 << ", " << makeGroups
2664 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2667 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2669 return aGroups ? aGroups : new SMESH::ListOfGroups;
2671 SMESH_CATCH( SMESH::throwCorbaException );
2675 //=======================================================================
2676 //function : AdvancedExtrusion
2678 //=======================================================================
2680 SMESH::ListOfGroups*
2681 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2682 const SMESH::DirStruct & theStepVector,
2683 CORBA::Long theNbOfSteps,
2684 CORBA::Long theExtrFlags,
2685 CORBA::Double theSewTolerance,
2686 CORBA::Boolean theMakeGroups)
2687 throw (SALOME::SALOME_Exception)
2692 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2694 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2695 theExtrFlags, theSewTolerance );
2697 TIDSortedElemSet elemsNodes[2];
2698 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2700 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2701 ::SMESH_MeshEditor::PGroupIDs groupIds =
2702 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2704 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2706 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2708 if ( !myIsPreviewMode ) {
2709 dumpGroupsList(aPythonDump, aGroups);
2710 aPythonDump << this << ".AdvancedExtrusion( "
2711 << theIDsOfElements << ", "
2712 << theStepVector << ", "
2713 << theNbOfSteps << ", "
2714 << theExtrFlags << ", "
2715 << theSewTolerance << ", "
2716 << theMakeGroups << " )";
2720 getPreviewMesh()->Remove( SMDSAbs_Volume );
2723 return aGroups ? aGroups : new SMESH::ListOfGroups;
2725 SMESH_CATCH( SMESH::throwCorbaException );
2729 //================================================================================
2731 * \brief Convert extrusion error to IDL enum
2733 //================================================================================
2737 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2739 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2743 RETCASE( EXTR_NO_ELEMENTS );
2744 RETCASE( EXTR_PATH_NOT_EDGE );
2745 RETCASE( EXTR_BAD_PATH_SHAPE );
2746 RETCASE( EXTR_BAD_STARTING_NODE );
2747 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2748 RETCASE( EXTR_CANT_GET_TANGENT );
2750 return SMESH::SMESH_MeshEditor::EXTR_OK;
2754 //=======================================================================
2755 //function : extrusionAlongPath
2757 //=======================================================================
2758 SMESH::ListOfGroups*
2759 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2760 const SMESH::ListOfIDSources & theEdges,
2761 const SMESH::ListOfIDSources & theFaces,
2762 SMESH::SMESH_IDSource_ptr thePathMesh,
2763 GEOM::GEOM_Object_ptr thePathShape,
2764 CORBA::Long theNodeStart,
2765 CORBA::Boolean theHasAngles,
2766 const SMESH::double_array & theAngles,
2767 CORBA::Boolean theLinearVariation,
2768 CORBA::Boolean theHasRefPoint,
2769 const SMESH::PointStruct & theRefPoint,
2771 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2772 throw (SALOME::SALOME_Exception)
2777 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2779 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2780 if ( thePathMesh->_is_nil() )
2781 return aGroups._retn();
2784 SMESH_subMesh* aSubMesh = 0;
2785 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2786 if ( thePathShape->_is_nil() )
2788 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2789 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2791 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2792 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2793 if ( !aMeshImp ) return aGroups._retn();
2794 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2795 if ( !aSubMesh ) return aGroups._retn();
2797 else if ( !aMeshImp ||
2798 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2800 return aGroups._retn();
2805 if ( !aMeshImp ) return aGroups._retn();
2806 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2807 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2808 if ( !aSubMesh || !aSubMesh->GetSubMeshDS() )
2809 return aGroups._retn();
2812 SMDS_MeshNode* nodeStart =
2813 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2815 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2816 return aGroups._retn();
2819 TIDSortedElemSet elemsNodes[2];
2820 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2821 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2822 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2824 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2825 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2826 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2827 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2829 list<double> angles;
2830 for (int i = 0; i < theAngles.length(); i++) {
2831 angles.push_back( theAngles[i] );
2834 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2836 int nbOldGroups = myMesh->NbGroup();
2838 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2839 if ( myIsPreviewMode )
2841 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2842 TPreviewMesh * tmpMesh = getPreviewMesh();
2843 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2844 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2845 workElements = & copyElements[0];
2846 theMakeGroups = false;
2849 ::SMESH_MeshEditor::Extrusion_Error error;
2851 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2852 theHasAngles, angles, theLinearVariation,
2853 theHasRefPoint, refPnt, theMakeGroups );
2855 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2856 theHasAngles, angles, theLinearVariation,
2857 theHasRefPoint, refPnt, theMakeGroups );
2859 declareMeshModified( /*isReComputeSafe=*/true );
2860 theError = convExtrError( error );
2862 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2863 if ( theMakeGroups ) {
2864 list<int> groupIDs = myMesh->GetGroupIds();
2865 list<int>::iterator newBegin = groupIDs.begin();
2866 std::advance( newBegin, nbOldGroups ); // skip old groups
2867 groupIDs.erase( groupIDs.begin(), newBegin );
2868 aGroups = getGroups( & groupIDs );
2869 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2872 if ( !myIsPreviewMode ) {
2873 aPythonDump << "(" << aGroups << ", error) = "
2874 << this << ".ExtrusionAlongPathObjects( "
2878 << thePathMesh << ", "
2879 << thePathShape << ", "
2880 << theNodeStart << ", "
2881 << theHasAngles << ", "
2882 << theAngles << ", "
2883 << theLinearVariation << ", "
2884 << theHasRefPoint << ", "
2885 << "SMESH.PointStruct( "
2886 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2887 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2888 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2889 << theMakeGroups << " )";
2893 getPreviewMesh()->Remove( SMDSAbs_Volume );
2896 return aGroups._retn();
2898 SMESH_CATCH( SMESH::throwCorbaException );
2902 //================================================================================
2904 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2905 * of given angles along path steps
2906 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2907 * which proceeds the extrusion
2908 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2909 * is used to define the sub-mesh for the path
2911 //================================================================================
2913 SMESH::double_array*
2914 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2915 GEOM::GEOM_Object_ptr thePathShape,
2916 const SMESH::double_array & theAngles)
2918 SMESH::double_array_var aResult = new SMESH::double_array();
2919 int nbAngles = theAngles.length();
2920 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2922 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2923 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2924 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2925 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2926 return aResult._retn();
2927 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2928 if ( nbSteps == nbAngles )
2930 aResult.inout() = theAngles;
2934 aResult->length( nbSteps );
2935 double rAn2St = double( nbAngles ) / double( nbSteps );
2936 double angPrev = 0, angle;
2937 for ( int iSt = 0; iSt < nbSteps; ++iSt )
2939 double angCur = rAn2St * ( iSt+1 );
2940 double angCurFloor = floor( angCur );
2941 double angPrevFloor = floor( angPrev );
2942 if ( angPrevFloor == angCurFloor )
2943 angle = rAn2St * theAngles[ int( angCurFloor ) ];
2946 int iP = int( angPrevFloor );
2947 double angPrevCeil = ceil(angPrev);
2948 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2950 int iC = int( angCurFloor );
2951 if ( iC < nbAngles )
2952 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2954 iP = int( angPrevCeil );
2956 angle += theAngles[ iC ];
2958 aResult[ iSt ] = angle;
2963 // Update Python script
2964 TPythonDump() << "rotAngles = " << theAngles;
2965 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
2966 << thePathMesh << ", "
2967 << thePathShape << ", "
2970 return aResult._retn();
2973 //=======================================================================
2976 //=======================================================================
2978 SMESH::ListOfGroups*
2979 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
2980 const SMESH::AxisStruct & theAxis,
2981 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2982 CORBA::Boolean theCopy,
2984 ::SMESH_Mesh* theTargetMesh)
2985 throw (SALOME::SALOME_Exception)
2990 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2991 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2993 if ( theTargetMesh )
2997 switch ( theMirrorType ) {
2998 case SMESH::SMESH_MeshEditor::POINT:
2999 aTrsf.SetMirror( P );
3001 case SMESH::SMESH_MeshEditor::AXIS:
3002 aTrsf.SetMirror( gp_Ax1( P, V ));
3005 aTrsf.SetMirror( gp_Ax2( P, V ));
3008 TIDSortedElemSet copyElements;
3009 TIDSortedElemSet* workElements = & theElements;
3011 if ( myIsPreviewMode )
3013 TPreviewMesh * tmpMesh = getPreviewMesh();
3014 tmpMesh->Copy( theElements, copyElements);
3015 if ( !theCopy && !theTargetMesh )
3017 TIDSortedElemSet elemsAround, elemsAroundCopy;
3018 getElementsAround( theElements, getMeshDS(), elemsAround );
3019 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3021 workElements = & copyElements;
3022 theMakeGroups = false;
3025 ::SMESH_MeshEditor::PGroupIDs groupIds =
3026 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3028 if ( theCopy && !myIsPreviewMode)
3030 if ( theTargetMesh )
3032 theTargetMesh->GetMeshDS()->Modified();
3036 declareMeshModified( /*isReComputeSafe=*/false );
3039 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3041 SMESH_CATCH( SMESH::throwCorbaException );
3045 //=======================================================================
3048 //=======================================================================
3050 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3051 const SMESH::AxisStruct & theAxis,
3052 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3053 CORBA::Boolean theCopy)
3054 throw (SALOME::SALOME_Exception)
3056 if ( !myIsPreviewMode ) {
3057 TPythonDump() << this << ".Mirror( "
3058 << theIDsOfElements << ", "
3060 << mirrorTypeName(theMirrorType) << ", "
3063 if ( theIDsOfElements.length() > 0 )
3065 TIDSortedElemSet elements;
3066 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3067 mirror(elements, theAxis, theMirrorType, theCopy, false);
3072 //=======================================================================
3073 //function : MirrorObject
3075 //=======================================================================
3077 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3078 const SMESH::AxisStruct & theAxis,
3079 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3080 CORBA::Boolean theCopy)
3081 throw (SALOME::SALOME_Exception)
3083 if ( !myIsPreviewMode ) {
3084 TPythonDump() << this << ".MirrorObject( "
3085 << theObject << ", "
3087 << mirrorTypeName(theMirrorType) << ", "
3090 TIDSortedElemSet elements;
3092 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3094 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3095 mirror(elements, theAxis, theMirrorType, theCopy, false);
3098 //=======================================================================
3099 //function : MirrorMakeGroups
3101 //=======================================================================
3103 SMESH::ListOfGroups*
3104 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3105 const SMESH::AxisStruct& theMirror,
3106 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3107 throw (SALOME::SALOME_Exception)
3109 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3111 SMESH::ListOfGroups * aGroups = 0;
3112 if ( theIDsOfElements.length() > 0 )
3114 TIDSortedElemSet elements;
3115 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3116 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3118 if (!myIsPreviewMode) {
3119 dumpGroupsList(aPythonDump, aGroups);
3120 aPythonDump << this << ".MirrorMakeGroups( "
3121 << theIDsOfElements << ", "
3122 << theMirror << ", "
3123 << mirrorTypeName(theMirrorType) << " )";
3128 //=======================================================================
3129 //function : MirrorObjectMakeGroups
3131 //=======================================================================
3133 SMESH::ListOfGroups*
3134 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3135 const SMESH::AxisStruct& theMirror,
3136 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3137 throw (SALOME::SALOME_Exception)
3139 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3141 SMESH::ListOfGroups * aGroups = 0;
3142 TIDSortedElemSet elements;
3143 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3144 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3146 if (!myIsPreviewMode)
3148 dumpGroupsList(aPythonDump,aGroups);
3149 aPythonDump << this << ".MirrorObjectMakeGroups( "
3150 << theObject << ", "
3151 << theMirror << ", "
3152 << mirrorTypeName(theMirrorType) << " )";
3157 //=======================================================================
3158 //function : MirrorMakeMesh
3160 //=======================================================================
3162 SMESH::SMESH_Mesh_ptr
3163 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3164 const SMESH::AxisStruct& theMirror,
3165 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3166 CORBA::Boolean theCopyGroups,
3167 const char* theMeshName)
3168 throw (SALOME::SALOME_Exception)
3170 SMESH_Mesh_i* mesh_i;
3171 SMESH::SMESH_Mesh_var mesh;
3172 { // open new scope to dump "MakeMesh" command
3173 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3175 TPythonDump pydump; // to prevent dump at mesh creation
3177 mesh = makeMesh( theMeshName );
3178 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3179 if (mesh_i && theIDsOfElements.length() > 0 )
3181 TIDSortedElemSet elements;
3182 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3183 mirror(elements, theMirror, theMirrorType,
3184 false, theCopyGroups, & mesh_i->GetImpl());
3185 mesh_i->CreateGroupServants();
3188 if (!myIsPreviewMode) {
3189 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3190 << theIDsOfElements << ", "
3191 << theMirror << ", "
3192 << mirrorTypeName(theMirrorType) << ", "
3193 << theCopyGroups << ", '"
3194 << theMeshName << "' )";
3199 if (!myIsPreviewMode && mesh_i)
3200 mesh_i->GetGroups();
3202 return mesh._retn();
3205 //=======================================================================
3206 //function : MirrorObjectMakeMesh
3208 //=======================================================================
3210 SMESH::SMESH_Mesh_ptr
3211 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3212 const SMESH::AxisStruct& theMirror,
3213 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3214 CORBA::Boolean theCopyGroups,
3215 const char* theMeshName)
3216 throw (SALOME::SALOME_Exception)
3218 SMESH_Mesh_i* mesh_i;
3219 SMESH::SMESH_Mesh_var mesh;
3220 { // open new scope to dump "MakeMesh" command
3221 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3223 TPythonDump pydump; // to prevent dump at mesh creation
3225 mesh = makeMesh( theMeshName );
3226 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3227 TIDSortedElemSet elements;
3229 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3231 mirror(elements, theMirror, theMirrorType,
3232 false, theCopyGroups, & mesh_i->GetImpl());
3233 mesh_i->CreateGroupServants();
3235 if (!myIsPreviewMode) {
3236 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3237 << theObject << ", "
3238 << theMirror << ", "
3239 << mirrorTypeName(theMirrorType) << ", "
3240 << theCopyGroups << ", '"
3241 << theMeshName << "' )";
3246 if (!myIsPreviewMode && mesh_i)
3247 mesh_i->GetGroups();
3249 return mesh._retn();
3252 //=======================================================================
3253 //function : translate
3255 //=======================================================================
3257 SMESH::ListOfGroups*
3258 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3259 const SMESH::DirStruct & theVector,
3260 CORBA::Boolean theCopy,
3262 ::SMESH_Mesh* theTargetMesh)
3263 throw (SALOME::SALOME_Exception)
3268 if ( theTargetMesh )
3272 const SMESH::PointStruct * P = &theVector.PS;
3273 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3275 TIDSortedElemSet copyElements;
3276 TIDSortedElemSet* workElements = &theElements;
3278 if ( myIsPreviewMode )
3280 TPreviewMesh * tmpMesh = getPreviewMesh();
3281 tmpMesh->Copy( theElements, copyElements);
3282 if ( !theCopy && !theTargetMesh )
3284 TIDSortedElemSet elemsAround, elemsAroundCopy;
3285 getElementsAround( theElements, getMeshDS(), elemsAround );
3286 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3288 workElements = & copyElements;
3289 theMakeGroups = false;
3292 ::SMESH_MeshEditor::PGroupIDs groupIds =
3293 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3295 if ( theCopy && !myIsPreviewMode )
3297 if ( theTargetMesh )
3299 theTargetMesh->GetMeshDS()->Modified();
3303 declareMeshModified( /*isReComputeSafe=*/false );
3307 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3309 SMESH_CATCH( SMESH::throwCorbaException );
3313 //=======================================================================
3314 //function : Translate
3316 //=======================================================================
3318 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3319 const SMESH::DirStruct & theVector,
3320 CORBA::Boolean theCopy)
3321 throw (SALOME::SALOME_Exception)
3323 if (!myIsPreviewMode) {
3324 TPythonDump() << this << ".Translate( "
3325 << theIDsOfElements << ", "
3326 << theVector << ", "
3329 if (theIDsOfElements.length()) {
3330 TIDSortedElemSet elements;
3331 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3332 translate(elements, theVector, theCopy, false);
3336 //=======================================================================
3337 //function : TranslateObject
3339 //=======================================================================
3341 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3342 const SMESH::DirStruct & theVector,
3343 CORBA::Boolean theCopy)
3344 throw (SALOME::SALOME_Exception)
3346 if (!myIsPreviewMode) {
3347 TPythonDump() << this << ".TranslateObject( "
3348 << theObject << ", "
3349 << theVector << ", "
3352 TIDSortedElemSet elements;
3354 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3356 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3357 translate(elements, theVector, theCopy, false);
3360 //=======================================================================
3361 //function : TranslateMakeGroups
3363 //=======================================================================
3365 SMESH::ListOfGroups*
3366 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3367 const SMESH::DirStruct& theVector)
3368 throw (SALOME::SALOME_Exception)
3370 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3372 SMESH::ListOfGroups * aGroups = 0;
3373 if (theIDsOfElements.length()) {
3374 TIDSortedElemSet elements;
3375 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3376 aGroups = translate(elements,theVector,true,true);
3378 if (!myIsPreviewMode) {
3379 dumpGroupsList(aPythonDump, aGroups);
3380 aPythonDump << this << ".TranslateMakeGroups( "
3381 << theIDsOfElements << ", "
3382 << theVector << " )";
3387 //=======================================================================
3388 //function : TranslateObjectMakeGroups
3390 //=======================================================================
3392 SMESH::ListOfGroups*
3393 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3394 const SMESH::DirStruct& theVector)
3395 throw (SALOME::SALOME_Exception)
3397 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3399 SMESH::ListOfGroups * aGroups = 0;
3400 TIDSortedElemSet elements;
3401 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3402 aGroups = translate(elements, theVector, true, true);
3404 if (!myIsPreviewMode) {
3405 dumpGroupsList(aPythonDump, aGroups);
3406 aPythonDump << this << ".TranslateObjectMakeGroups( "
3407 << theObject << ", "
3408 << theVector << " )";
3413 //=======================================================================
3414 //function : TranslateMakeMesh
3416 //=======================================================================
3418 SMESH::SMESH_Mesh_ptr
3419 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3420 const SMESH::DirStruct& theVector,
3421 CORBA::Boolean theCopyGroups,
3422 const char* theMeshName)
3423 throw (SALOME::SALOME_Exception)
3425 SMESH_Mesh_i* mesh_i;
3426 SMESH::SMESH_Mesh_var mesh;
3428 { // open new scope to dump "MakeMesh" command
3429 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3431 TPythonDump pydump; // to prevent dump at mesh creation
3433 mesh = makeMesh( theMeshName );
3434 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3436 if ( mesh_i && theIDsOfElements.length() )
3438 TIDSortedElemSet elements;
3439 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3440 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3441 mesh_i->CreateGroupServants();
3444 if ( !myIsPreviewMode ) {
3445 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3446 << theIDsOfElements << ", "
3447 << theVector << ", "
3448 << theCopyGroups << ", '"
3449 << theMeshName << "' )";
3454 if (!myIsPreviewMode && mesh_i)
3455 mesh_i->GetGroups();
3457 return mesh._retn();
3460 //=======================================================================
3461 //function : TranslateObjectMakeMesh
3463 //=======================================================================
3465 SMESH::SMESH_Mesh_ptr
3466 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3467 const SMESH::DirStruct& theVector,
3468 CORBA::Boolean theCopyGroups,
3469 const char* theMeshName)
3470 throw (SALOME::SALOME_Exception)
3473 SMESH_Mesh_i* mesh_i;
3474 SMESH::SMESH_Mesh_var mesh;
3475 { // open new scope to dump "MakeMesh" command
3476 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3478 TPythonDump pydump; // to prevent dump at mesh creation
3479 mesh = makeMesh( theMeshName );
3480 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3482 TIDSortedElemSet elements;
3484 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3486 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3487 mesh_i->CreateGroupServants();
3489 if ( !myIsPreviewMode ) {
3490 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3491 << theObject << ", "
3492 << theVector << ", "
3493 << theCopyGroups << ", '"
3494 << theMeshName << "' )";
3499 if (!myIsPreviewMode && mesh_i)
3500 mesh_i->GetGroups();
3502 return mesh._retn();
3504 SMESH_CATCH( SMESH::throwCorbaException );
3508 //=======================================================================
3511 //=======================================================================
3513 SMESH::ListOfGroups*
3514 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3515 const SMESH::AxisStruct & theAxis,
3516 CORBA::Double theAngle,
3517 CORBA::Boolean theCopy,
3519 ::SMESH_Mesh* theTargetMesh)
3520 throw (SALOME::SALOME_Exception)
3525 if ( theTargetMesh )
3528 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3529 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3532 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3534 TIDSortedElemSet copyElements;
3535 TIDSortedElemSet* workElements = &theElements;
3536 if ( myIsPreviewMode ) {
3537 TPreviewMesh * tmpMesh = getPreviewMesh();
3538 tmpMesh->Copy( theElements, copyElements );
3539 if ( !theCopy && !theTargetMesh )
3541 TIDSortedElemSet elemsAround, elemsAroundCopy;
3542 getElementsAround( theElements, getMeshDS(), elemsAround );
3543 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3545 workElements = ©Elements;
3546 theMakeGroups = false;
3549 ::SMESH_MeshEditor::PGroupIDs groupIds =
3550 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3552 if ( theCopy && !myIsPreviewMode)
3554 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3555 else declareMeshModified( /*isReComputeSafe=*/false );
3558 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3560 SMESH_CATCH( SMESH::throwCorbaException );
3564 //=======================================================================
3567 //=======================================================================
3569 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3570 const SMESH::AxisStruct & theAxis,
3571 CORBA::Double theAngle,
3572 CORBA::Boolean theCopy)
3573 throw (SALOME::SALOME_Exception)
3575 if (!myIsPreviewMode) {
3576 TPythonDump() << this << ".Rotate( "
3577 << theIDsOfElements << ", "
3579 << TVar( theAngle ) << ", "
3582 if (theIDsOfElements.length() > 0)
3584 TIDSortedElemSet elements;
3585 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3586 rotate(elements,theAxis,theAngle,theCopy,false);
3590 //=======================================================================
3591 //function : RotateObject
3593 //=======================================================================
3595 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3596 const SMESH::AxisStruct & theAxis,
3597 CORBA::Double theAngle,
3598 CORBA::Boolean theCopy)
3599 throw (SALOME::SALOME_Exception)
3601 if ( !myIsPreviewMode ) {
3602 TPythonDump() << this << ".RotateObject( "
3603 << theObject << ", "
3605 << TVar( theAngle ) << ", "
3608 TIDSortedElemSet elements;
3609 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3610 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3611 rotate(elements,theAxis,theAngle,theCopy,false);
3614 //=======================================================================
3615 //function : RotateMakeGroups
3617 //=======================================================================
3619 SMESH::ListOfGroups*
3620 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3621 const SMESH::AxisStruct& theAxis,
3622 CORBA::Double theAngle)
3623 throw (SALOME::SALOME_Exception)
3625 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3627 SMESH::ListOfGroups * aGroups = 0;
3628 if (theIDsOfElements.length() > 0)
3630 TIDSortedElemSet elements;
3631 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3632 aGroups = rotate(elements,theAxis,theAngle,true,true);
3634 if (!myIsPreviewMode) {
3635 dumpGroupsList(aPythonDump, aGroups);
3636 aPythonDump << this << ".RotateMakeGroups( "
3637 << theIDsOfElements << ", "
3639 << TVar( theAngle ) << " )";
3644 //=======================================================================
3645 //function : RotateObjectMakeGroups
3647 //=======================================================================
3649 SMESH::ListOfGroups*
3650 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3651 const SMESH::AxisStruct& theAxis,
3652 CORBA::Double theAngle)
3653 throw (SALOME::SALOME_Exception)
3655 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3657 SMESH::ListOfGroups * aGroups = 0;
3658 TIDSortedElemSet elements;
3659 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3660 aGroups = rotate(elements, theAxis, theAngle, true, true);
3662 if (!myIsPreviewMode) {
3663 dumpGroupsList(aPythonDump, aGroups);
3664 aPythonDump << this << ".RotateObjectMakeGroups( "
3665 << theObject << ", "
3667 << TVar( theAngle ) << " )";
3672 //=======================================================================
3673 //function : RotateMakeMesh
3675 //=======================================================================
3677 SMESH::SMESH_Mesh_ptr
3678 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3679 const SMESH::AxisStruct& theAxis,
3680 CORBA::Double theAngleInRadians,
3681 CORBA::Boolean theCopyGroups,
3682 const char* theMeshName)
3683 throw (SALOME::SALOME_Exception)
3686 SMESH::SMESH_Mesh_var mesh;
3687 SMESH_Mesh_i* mesh_i;
3689 { // open new scope to dump "MakeMesh" command
3690 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3692 TPythonDump pydump; // to prevent dump at mesh creation
3694 mesh = makeMesh( theMeshName );
3695 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3697 if ( mesh_i && theIDsOfElements.length() > 0 )
3699 TIDSortedElemSet elements;
3700 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3701 rotate(elements, theAxis, theAngleInRadians,
3702 false, theCopyGroups, & mesh_i->GetImpl());
3703 mesh_i->CreateGroupServants();
3705 if ( !myIsPreviewMode ) {
3706 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3707 << theIDsOfElements << ", "
3709 << TVar( theAngleInRadians ) << ", "
3710 << theCopyGroups << ", '"
3711 << theMeshName << "' )";
3716 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3717 mesh_i->GetGroups();
3719 return mesh._retn();
3721 SMESH_CATCH( SMESH::throwCorbaException );
3725 //=======================================================================
3726 //function : RotateObjectMakeMesh
3728 //=======================================================================
3730 SMESH::SMESH_Mesh_ptr
3731 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3732 const SMESH::AxisStruct& theAxis,
3733 CORBA::Double theAngleInRadians,
3734 CORBA::Boolean theCopyGroups,
3735 const char* theMeshName)
3736 throw (SALOME::SALOME_Exception)
3739 SMESH::SMESH_Mesh_var mesh;
3740 SMESH_Mesh_i* mesh_i;
3742 {// open new scope to dump "MakeMesh" command
3743 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3745 TPythonDump pydump; // to prevent dump at mesh creation
3746 mesh = makeMesh( theMeshName );
3747 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3749 TIDSortedElemSet elements;
3751 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3753 rotate(elements, theAxis, theAngleInRadians,
3754 false, theCopyGroups, & mesh_i->GetImpl());
3755 mesh_i->CreateGroupServants();
3757 if ( !myIsPreviewMode ) {
3758 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3759 << theObject << ", "
3761 << TVar( theAngleInRadians ) << ", "
3762 << theCopyGroups << ", '"
3763 << theMeshName << "' )";
3768 if (!myIsPreviewMode && mesh_i)
3769 mesh_i->GetGroups();
3771 return mesh._retn();
3773 SMESH_CATCH( SMESH::throwCorbaException );
3777 //=======================================================================
3780 //=======================================================================
3782 SMESH::ListOfGroups*
3783 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3784 const SMESH::PointStruct& thePoint,
3785 const SMESH::double_array& theScaleFact,
3786 CORBA::Boolean theCopy,
3788 ::SMESH_Mesh* theTargetMesh)
3789 throw (SALOME::SALOME_Exception)
3793 if ( theScaleFact.length() < 1 )
3794 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3795 if ( theScaleFact.length() == 2 )
3796 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3798 if ( theTargetMesh )
3801 TIDSortedElemSet elements;
3802 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3803 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3808 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3809 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3813 #if OCC_VERSION_LARGE > 0x06070100
3814 // fight against orthogonalization
3815 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3816 // 0, S[1], 0, thePoint.y * (1-S[1]),
3817 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3818 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3819 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3820 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3821 loc.SetCoord( thePoint.x * (1-S[0]),
3822 thePoint.y * (1-S[1]),
3823 thePoint.z * (1-S[2]));
3824 M.SetDiagonal( S[0], S[1], S[2] );
3827 double tol = std::numeric_limits<double>::max();
3828 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3829 0, S[1], 0, thePoint.y * (1-S[1]),
3830 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3833 TIDSortedElemSet copyElements;
3834 TIDSortedElemSet* workElements = &elements;
3835 if ( myIsPreviewMode )
3837 TPreviewMesh * tmpMesh = getPreviewMesh();
3838 tmpMesh->Copy( elements, copyElements);
3839 if ( !theCopy && !theTargetMesh )
3841 TIDSortedElemSet elemsAround, elemsAroundCopy;
3842 getElementsAround( elements, getMeshDS(), elemsAround );
3843 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3845 workElements = & copyElements;
3846 theMakeGroups = false;
3849 ::SMESH_MeshEditor::PGroupIDs groupIds =
3850 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3852 if ( theCopy && !myIsPreviewMode )
3854 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3855 else declareMeshModified( /*isReComputeSafe=*/false );
3857 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3859 SMESH_CATCH( SMESH::throwCorbaException );
3863 //=======================================================================
3866 //=======================================================================
3868 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3869 const SMESH::PointStruct& thePoint,
3870 const SMESH::double_array& theScaleFact,
3871 CORBA::Boolean theCopy)
3872 throw (SALOME::SALOME_Exception)
3874 if ( !myIsPreviewMode ) {
3875 TPythonDump() << this << ".Scale( "
3876 << theObject << ", "
3878 << TVar( theScaleFact ) << ", "
3881 scale(theObject, thePoint, theScaleFact, theCopy, false);
3885 //=======================================================================
3886 //function : ScaleMakeGroups
3888 //=======================================================================
3890 SMESH::ListOfGroups*
3891 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3892 const SMESH::PointStruct& thePoint,
3893 const SMESH::double_array& theScaleFact)
3894 throw (SALOME::SALOME_Exception)
3896 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3898 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3899 if (!myIsPreviewMode) {
3900 dumpGroupsList(aPythonDump, aGroups);
3901 aPythonDump << this << ".Scale("
3904 << TVar( theScaleFact ) << ",True,True)";
3910 //=======================================================================
3911 //function : ScaleMakeMesh
3913 //=======================================================================
3915 SMESH::SMESH_Mesh_ptr
3916 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3917 const SMESH::PointStruct& thePoint,
3918 const SMESH::double_array& theScaleFact,
3919 CORBA::Boolean theCopyGroups,
3920 const char* theMeshName)
3921 throw (SALOME::SALOME_Exception)
3923 SMESH_Mesh_i* mesh_i;
3924 SMESH::SMESH_Mesh_var mesh;
3925 { // open new scope to dump "MakeMesh" command
3926 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3928 TPythonDump pydump; // to prevent dump at mesh creation
3929 mesh = makeMesh( theMeshName );
3930 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3934 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3935 mesh_i->CreateGroupServants();
3937 if ( !myIsPreviewMode )
3938 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3939 << theObject << ", "
3941 << TVar( theScaleFact ) << ", "
3942 << theCopyGroups << ", '"
3943 << theMeshName << "' )";
3947 if (!myIsPreviewMode && mesh_i)
3948 mesh_i->GetGroups();
3950 return mesh._retn();
3954 //=======================================================================
3955 //function : findCoincidentNodes
3957 //=======================================================================
3959 void SMESH_MeshEditor_i::
3960 findCoincidentNodes (TIDSortedNodeSet & Nodes,
3961 CORBA::Double Tolerance,
3962 SMESH::array_of_long_array_out GroupsOfNodes,
3963 CORBA::Boolean SeparateCornersAndMedium)
3965 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3966 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
3968 GroupsOfNodes = new SMESH::array_of_long_array;
3969 GroupsOfNodes->length( aListOfListOfNodes.size() );
3970 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3971 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3973 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3974 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3975 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3976 aGroup.length( aListOfNodes.size() );
3977 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3978 aGroup[ j ] = (*lIt)->GetID();
3982 //=======================================================================
3983 //function : FindCoincidentNodes
3985 //=======================================================================
3987 void SMESH_MeshEditor_i::
3988 FindCoincidentNodes (CORBA::Double Tolerance,
3989 SMESH::array_of_long_array_out GroupsOfNodes,
3990 CORBA::Boolean SeparateCornersAndMedium)
3991 throw (SALOME::SALOME_Exception)
3996 TIDSortedNodeSet nodes; // no input nodes
3997 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
3999 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4000 << Tolerance << ", "
4001 << SeparateCornersAndMedium << " )";
4003 SMESH_CATCH( SMESH::throwCorbaException );
4006 //=======================================================================
4007 //function : FindCoincidentNodesOnPart
4009 //=======================================================================
4011 void SMESH_MeshEditor_i::
4012 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4013 CORBA::Double Tolerance,
4014 SMESH::array_of_long_array_out GroupsOfNodes,
4015 CORBA::Boolean SeparateCornersAndMedium)
4016 throw (SALOME::SALOME_Exception)
4021 TIDSortedNodeSet nodes;
4022 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4024 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4026 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4028 << Tolerance << ", "
4029 << SeparateCornersAndMedium << " )";
4031 SMESH_CATCH( SMESH::throwCorbaException );
4034 //================================================================================
4036 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4037 * ExceptSubMeshOrGroups
4039 //================================================================================
4041 void SMESH_MeshEditor_i::
4042 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4043 CORBA::Double theTolerance,
4044 SMESH::array_of_long_array_out theGroupsOfNodes,
4045 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4046 CORBA::Boolean theSeparateCornersAndMedium)
4047 throw (SALOME::SALOME_Exception)
4052 TIDSortedNodeSet nodes;
4053 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4055 for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4057 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4059 while ( nodeIt->more() )
4060 nodes.erase( cast2Node( nodeIt->next() ));
4062 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4064 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4066 << theTolerance << ", "
4067 << theExceptSubMeshOrGroups << ", "
4068 << theSeparateCornersAndMedium << " )";
4070 SMESH_CATCH( SMESH::throwCorbaException );
4073 //=======================================================================
4074 //function : MergeNodes
4076 //=======================================================================
4078 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
4079 throw (SALOME::SALOME_Exception)
4084 SMESHDS_Mesh* aMesh = getMeshDS();
4086 TPythonDump aTPythonDump;
4087 aTPythonDump << this << ".MergeNodes([";
4088 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4089 for (int i = 0; i < GroupsOfNodes.length(); i++)
4091 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4092 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4093 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4094 for ( int j = 0; j < aNodeGroup.length(); j++ )
4096 CORBA::Long index = aNodeGroup[ j ];
4097 const SMDS_MeshNode * node = aMesh->FindNode(index);
4099 aListOfNodes.push_back( node );
4101 if ( aListOfNodes.size() < 2 )
4102 aListOfListOfNodes.pop_back();
4104 if ( i > 0 ) aTPythonDump << ", ";
4105 aTPythonDump << aNodeGroup;
4107 getEditor().MergeNodes( aListOfListOfNodes );
4109 aTPythonDump << "])";
4111 declareMeshModified( /*isReComputeSafe=*/false );
4113 SMESH_CATCH( SMESH::throwCorbaException );
4116 //=======================================================================
4117 //function : FindEqualElements
4119 //=======================================================================
4121 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4122 SMESH::array_of_long_array_out GroupsOfElementsID)
4123 throw (SALOME::SALOME_Exception)
4128 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4129 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4131 TIDSortedElemSet elems;
4132 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4134 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4135 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4137 GroupsOfElementsID = new SMESH::array_of_long_array;
4138 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4140 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4141 aListOfListOfElementsID.begin();
4142 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4144 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4145 list<int>& listOfIDs = *arraysIt;
4146 aGroup.length( listOfIDs.size() );
4147 list<int>::iterator idIt = listOfIDs.begin();
4148 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4149 aGroup[ k ] = *idIt;
4152 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4156 SMESH_CATCH( SMESH::throwCorbaException );
4159 //=======================================================================
4160 //function : MergeElements
4162 //=======================================================================
4164 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4165 throw (SALOME::SALOME_Exception)
4170 TPythonDump aTPythonDump;
4171 aTPythonDump << this << ".MergeElements( [";
4173 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4175 for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4176 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4177 aListOfListOfElementsID.push_back( list< int >() );
4178 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4179 for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4180 CORBA::Long id = anElemsIDGroup[ j ];
4181 aListOfElemsID.push_back( id );
4183 if ( aListOfElemsID.size() < 2 )
4184 aListOfListOfElementsID.pop_back();
4185 if ( i > 0 ) aTPythonDump << ", ";
4186 aTPythonDump << anElemsIDGroup;
4189 getEditor().MergeElements(aListOfListOfElementsID);
4191 declareMeshModified( /*isReComputeSafe=*/true );
4193 aTPythonDump << "] )";
4195 SMESH_CATCH( SMESH::throwCorbaException );
4198 //=======================================================================
4199 //function : MergeEqualElements
4201 //=======================================================================
4203 void SMESH_MeshEditor_i::MergeEqualElements()
4204 throw (SALOME::SALOME_Exception)
4209 getEditor().MergeEqualElements();
4211 declareMeshModified( /*isReComputeSafe=*/true );
4213 TPythonDump() << this << ".MergeEqualElements()";
4215 SMESH_CATCH( SMESH::throwCorbaException );
4218 //=============================================================================
4220 * Move the node to a given point
4222 //=============================================================================
4224 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4228 throw (SALOME::SALOME_Exception)
4231 initData(/*deleteSearchers=*/false);
4233 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4237 if ( theNodeSearcher )
4238 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4240 if ( myIsPreviewMode ) // make preview data
4242 // in a preview mesh, make edges linked to a node
4243 TPreviewMesh& tmpMesh = *getPreviewMesh();
4244 TIDSortedElemSet linkedNodes;
4245 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4246 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4247 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4248 for ( ; nIt != linkedNodes.end(); ++nIt )
4250 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4251 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4255 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4256 // fill preview data
4258 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4259 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4261 getMeshDS()->MoveNode(node, x, y, z);
4263 if ( !myIsPreviewMode )
4265 // Update Python script
4266 TPythonDump() << "isDone = " << this << ".MoveNode( "
4267 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4268 declareMeshModified( /*isReComputeSafe=*/false );
4271 SMESH_CATCH( SMESH::throwCorbaException );
4276 //================================================================================
4278 * \brief Return ID of node closest to a given point
4280 //================================================================================
4282 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4285 throw (SALOME::SALOME_Exception)
4288 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4290 if ( !theNodeSearcher ) {
4291 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4294 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4295 return node->GetID();
4297 SMESH_CATCH( SMESH::throwCorbaException );
4301 //================================================================================
4303 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4304 * move the node closest to the point to point's location and return ID of the node
4306 //================================================================================
4308 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4311 CORBA::Long theNodeID)
4312 throw (SALOME::SALOME_Exception)
4315 // We keep theNodeSearcher until any mesh modification:
4316 // 1) initData() deletes theNodeSearcher at any edition,
4317 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4319 initData(/*deleteSearchers=*/false);
4321 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4323 int nodeID = theNodeID;
4324 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4325 if ( !node ) // preview moving node
4327 if ( !theNodeSearcher ) {
4328 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4331 node = theNodeSearcher->FindClosestTo( p );
4334 nodeID = node->GetID();
4335 if ( myIsPreviewMode ) // make preview data
4337 // in a preview mesh, make edges linked to a node
4338 TPreviewMesh tmpMesh = *getPreviewMesh();
4339 TIDSortedElemSet linkedNodes;
4340 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4341 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4342 for ( ; nIt != linkedNodes.end(); ++nIt )
4344 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4345 tmpMesh.Copy( &edge );
4348 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4350 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4351 // fill preview data
4353 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4355 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4359 getMeshDS()->MoveNode(node, x, y, z);
4363 if ( !myIsPreviewMode )
4365 TPythonDump() << "nodeID = " << this
4366 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4367 << ", " << nodeID << " )";
4369 declareMeshModified( /*isReComputeSafe=*/false );
4374 SMESH_CATCH( SMESH::throwCorbaException );
4378 //=======================================================================
4380 * Return elements of given type where the given point is IN or ON.
4382 * 'ALL' type means elements of any type excluding nodes
4384 //=======================================================================
4386 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4389 SMESH::ElementType type)
4390 throw (SALOME::SALOME_Exception)
4393 SMESH::long_array_var res = new SMESH::long_array;
4394 vector< const SMDS_MeshElement* > foundElems;
4396 theSearchersDeleter.Set( myMesh );
4397 if ( !theElementSearcher ) {
4398 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4400 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4401 SMDSAbs_ElementType( type ),
4403 res->length( foundElems.size() );
4404 for ( int i = 0; i < foundElems.size(); ++i )
4405 res[i] = foundElems[i]->GetID();
4409 SMESH_CATCH( SMESH::throwCorbaException );
4413 //=======================================================================
4414 //function : FindAmongElementsByPoint
4415 //purpose : Searching among the given elements, return elements of given type
4416 // where the given point is IN or ON.
4417 // 'ALL' type means elements of any type excluding nodes
4418 //=======================================================================
4421 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4425 SMESH::ElementType type)
4426 throw (SALOME::SALOME_Exception)
4429 SMESH::long_array_var res = new SMESH::long_array;
4431 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4432 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4433 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4434 type != types[0] ) // but search of elements of dim > 0
4437 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4438 return FindElementsByPoint( x,y,z, type );
4440 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4442 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4443 if ( !theElementSearcher )
4445 // create a searcher from elementIDs
4446 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4447 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4449 if ( !idSourceToSet( elementIDs, meshDS, elements,
4450 SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4453 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4454 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4456 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4459 vector< const SMDS_MeshElement* > foundElems;
4461 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4462 SMDSAbs_ElementType( type ),
4464 res->length( foundElems.size() );
4465 for ( int i = 0; i < foundElems.size(); ++i )
4466 res[i] = foundElems[i]->GetID();
4470 SMESH_CATCH( SMESH::throwCorbaException );
4474 //=======================================================================
4475 //function : GetPointState
4476 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4477 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4478 //=======================================================================
4480 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4483 throw (SALOME::SALOME_Exception)
4486 theSearchersDeleter.Set( myMesh );
4487 if ( !theElementSearcher ) {
4488 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4490 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4492 SMESH_CATCH( SMESH::throwCorbaException );
4496 //=======================================================================
4497 //function : convError
4499 //=======================================================================
4501 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4503 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4507 RETCASE( SEW_BORDER1_NOT_FOUND );
4508 RETCASE( SEW_BORDER2_NOT_FOUND );
4509 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4510 RETCASE( SEW_BAD_SIDE_NODES );
4511 RETCASE( SEW_VOLUMES_TO_SPLIT );
4512 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4513 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4514 RETCASE( SEW_BAD_SIDE1_NODES );
4515 RETCASE( SEW_BAD_SIDE2_NODES );
4517 return SMESH::SMESH_MeshEditor::SEW_OK;
4520 //=======================================================================
4521 //function : SewFreeBorders
4523 //=======================================================================
4525 SMESH::SMESH_MeshEditor::Sew_Error
4526 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4527 CORBA::Long SecondNodeID1,
4528 CORBA::Long LastNodeID1,
4529 CORBA::Long FirstNodeID2,
4530 CORBA::Long SecondNodeID2,
4531 CORBA::Long LastNodeID2,
4532 CORBA::Boolean CreatePolygons,
4533 CORBA::Boolean CreatePolyedrs)
4534 throw (SALOME::SALOME_Exception)
4539 SMESHDS_Mesh* aMesh = getMeshDS();
4541 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4542 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4543 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4544 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4545 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4546 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4548 if (!aBorderFirstNode ||
4549 !aBorderSecondNode||
4551 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4552 if (!aSide2FirstNode ||
4553 !aSide2SecondNode ||
4555 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4557 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4558 << FirstNodeID1 << ", "
4559 << SecondNodeID1 << ", "
4560 << LastNodeID1 << ", "
4561 << FirstNodeID2 << ", "
4562 << SecondNodeID2 << ", "
4563 << LastNodeID2 << ", "
4564 << CreatePolygons<< ", "
4565 << CreatePolyedrs<< " )";
4567 SMESH::SMESH_MeshEditor::Sew_Error error =
4568 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4579 declareMeshModified( /*isReComputeSafe=*/false );
4582 SMESH_CATCH( SMESH::throwCorbaException );
4583 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4587 //=======================================================================
4588 //function : SewConformFreeBorders
4590 //=======================================================================
4592 SMESH::SMESH_MeshEditor::Sew_Error
4593 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4594 CORBA::Long SecondNodeID1,
4595 CORBA::Long LastNodeID1,
4596 CORBA::Long FirstNodeID2,
4597 CORBA::Long SecondNodeID2)
4598 throw (SALOME::SALOME_Exception)
4603 SMESHDS_Mesh* aMesh = getMeshDS();
4605 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4606 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4607 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4608 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4609 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4610 const SMDS_MeshNode* aSide2ThirdNode = 0;
4612 if (!aBorderFirstNode ||
4613 !aBorderSecondNode||
4615 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4616 if (!aSide2FirstNode ||
4618 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4620 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4621 << FirstNodeID1 << ", "
4622 << SecondNodeID1 << ", "
4623 << LastNodeID1 << ", "
4624 << FirstNodeID2 << ", "
4625 << SecondNodeID2 << " )";
4627 SMESH::SMESH_MeshEditor::Sew_Error error =
4628 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4637 declareMeshModified( /*isReComputeSafe=*/false );
4640 SMESH_CATCH( SMESH::throwCorbaException );
4641 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4645 //=======================================================================
4646 //function : SewBorderToSide
4648 //=======================================================================
4650 SMESH::SMESH_MeshEditor::Sew_Error
4651 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4652 CORBA::Long SecondNodeIDOnFreeBorder,
4653 CORBA::Long LastNodeIDOnFreeBorder,
4654 CORBA::Long FirstNodeIDOnSide,
4655 CORBA::Long LastNodeIDOnSide,
4656 CORBA::Boolean CreatePolygons,
4657 CORBA::Boolean CreatePolyedrs)
4658 throw (SALOME::SALOME_Exception)
4663 SMESHDS_Mesh* aMesh = getMeshDS();
4665 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4666 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4667 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4668 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4669 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4670 const SMDS_MeshNode* aSide2ThirdNode = 0;
4672 if (!aBorderFirstNode ||
4673 !aBorderSecondNode||
4675 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4676 if (!aSide2FirstNode ||
4678 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4680 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4681 << FirstNodeIDOnFreeBorder << ", "
4682 << SecondNodeIDOnFreeBorder << ", "
4683 << LastNodeIDOnFreeBorder << ", "
4684 << FirstNodeIDOnSide << ", "
4685 << LastNodeIDOnSide << ", "
4686 << CreatePolygons << ", "
4687 << CreatePolyedrs << ") ";
4689 SMESH::SMESH_MeshEditor::Sew_Error error =
4690 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4700 declareMeshModified( /*isReComputeSafe=*/false );
4703 SMESH_CATCH( SMESH::throwCorbaException );
4704 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4708 //=======================================================================
4709 //function : SewSideElements
4711 //=======================================================================
4713 SMESH::SMESH_MeshEditor::Sew_Error
4714 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4715 const SMESH::long_array& IDsOfSide2Elements,
4716 CORBA::Long NodeID1OfSide1ToMerge,
4717 CORBA::Long NodeID1OfSide2ToMerge,
4718 CORBA::Long NodeID2OfSide1ToMerge,
4719 CORBA::Long NodeID2OfSide2ToMerge)
4720 throw (SALOME::SALOME_Exception)
4725 SMESHDS_Mesh* aMesh = getMeshDS();
4727 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
4728 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
4729 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4730 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4732 if (!aFirstNode1ToMerge ||
4733 !aFirstNode2ToMerge )
4734 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4735 if (!aSecondNode1ToMerge||
4736 !aSecondNode2ToMerge)
4737 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4739 TIDSortedElemSet aSide1Elems, aSide2Elems;
4740 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4741 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4743 TPythonDump() << "error = " << this << ".SewSideElements( "
4744 << IDsOfSide1Elements << ", "
4745 << IDsOfSide2Elements << ", "
4746 << NodeID1OfSide1ToMerge << ", "
4747 << NodeID1OfSide2ToMerge << ", "
4748 << NodeID2OfSide1ToMerge << ", "
4749 << NodeID2OfSide2ToMerge << ")";
4751 SMESH::SMESH_MeshEditor::Sew_Error error =
4752 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
4755 aSecondNode1ToMerge,
4756 aSecondNode2ToMerge));
4758 declareMeshModified( /*isReComputeSafe=*/false );
4761 SMESH_CATCH( SMESH::throwCorbaException );
4762 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4765 //================================================================================
4767 * \brief Set new nodes for given element
4768 * \param ide - element id
4769 * \param newIDs - new node ids
4770 * \retval CORBA::Boolean - true if result is OK
4772 //================================================================================
4774 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4775 const SMESH::long_array& newIDs)
4776 throw (SALOME::SALOME_Exception)
4781 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
4782 if(!elem) return false;
4784 int nbn = newIDs.length();
4786 vector<const SMDS_MeshNode*> aNodes(nbn);
4789 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
4792 aNodes[nbn1] = aNode;
4795 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4796 << ide << ", " << newIDs << " )";
4798 MESSAGE("ChangeElementNodes");
4799 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4801 declareMeshModified( /*isReComputeSafe=*/ !res );
4805 SMESH_CATCH( SMESH::throwCorbaException );
4809 //=======================================================================
4811 * \brief Makes a part of the mesh quadratic or bi-quadratic
4813 //=======================================================================
4815 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
4816 CORBA::Boolean theToBiQuad,
4817 SMESH::SMESH_IDSource_ptr theObject)
4818 throw (SALOME::SALOME_Exception)
4823 TIDSortedElemSet elems;
4825 if ( !( elemsOK = CORBA::is_nil( theObject )))
4827 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
4828 SMDSAbs_All, /*emptyIfIsMesh=*/true );
4832 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
4833 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4835 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
4836 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
4838 declareMeshModified( /*isReComputeSafe=*/false );
4841 SMESH_CATCH( SMESH::throwCorbaException );
4844 //=======================================================================
4845 //function : ConvertFromQuadratic
4847 //=======================================================================
4849 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4850 throw (SALOME::SALOME_Exception)
4855 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
4856 TPythonDump() << this << ".ConvertFromQuadratic()";
4857 declareMeshModified( /*isReComputeSafe=*/!isDone );
4860 SMESH_CATCH( SMESH::throwCorbaException );
4864 //=======================================================================
4865 //function : ConvertToQuadratic
4867 //=======================================================================
4869 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4870 throw (SALOME::SALOME_Exception)
4872 convertToQuadratic( theForce3d, false );
4873 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
4876 //================================================================================
4878 * \brief Makes a part of the mesh quadratic
4880 //================================================================================
4882 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
4883 SMESH::SMESH_IDSource_ptr theObject)
4884 throw (SALOME::SALOME_Exception)
4886 convertToQuadratic( theForce3d, false, theObject );
4887 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
4890 //================================================================================
4892 * \brief Makes a part of the mesh bi-quadratic
4894 //================================================================================
4896 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
4897 SMESH::SMESH_IDSource_ptr theObject)
4898 throw (SALOME::SALOME_Exception)
4900 convertToQuadratic( theForce3d, true, theObject );
4901 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
4904 //================================================================================
4906 * \brief Makes a part of the mesh linear
4908 //================================================================================
4910 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
4911 throw (SALOME::SALOME_Exception)
4918 TIDSortedElemSet elems;
4919 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
4921 if ( elems.empty() )
4923 ConvertFromQuadratic();
4925 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
4927 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4931 getEditor().ConvertFromQuadratic(elems);
4934 declareMeshModified( /*isReComputeSafe=*/false );
4936 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
4938 SMESH_CATCH( SMESH::throwCorbaException );
4941 //=======================================================================
4942 //function : makeMesh
4943 //purpose : create a named imported mesh
4944 //=======================================================================
4946 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4948 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4949 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4950 SALOMEDS::Study_var study = gen->GetCurrentStudy();
4951 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
4952 gen->SetName( meshSO, theMeshName, "Mesh" );
4953 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4955 return mesh._retn();
4958 //=======================================================================
4959 //function : dumpGroupsList
4961 //=======================================================================
4963 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
4964 const SMESH::ListOfGroups * theGroupList)
4966 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
4967 if ( isDumpGroupList )
4968 theDumpPython << theGroupList << " = ";
4971 //================================================================================
4973 \brief Generates the unique group name.
4974 \param thePrefix name prefix
4977 //================================================================================
4979 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
4981 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4982 set<string> groupNames;
4984 // Get existing group names
4985 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
4986 SMESH::SMESH_GroupBase_var aGroup = groups[i];
4987 if (CORBA::is_nil(aGroup))
4990 CORBA::String_var name = aGroup->GetName();
4991 groupNames.insert( name.in() );
4995 string name = thePrefix;
4998 while (!groupNames.insert(name).second)
4999 name = SMESH_Comment( thePrefix ) << "_" << index++;
5004 //================================================================================
5006 * \brief Prepare SMESH_IDSource for work
5008 //================================================================================
5010 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5012 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5014 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5015 filter->SetMesh( mesh );
5018 //================================================================================
5020 * \brief Retrieve elements of given type from SMESH_IDSource
5022 //================================================================================
5024 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5025 const SMESHDS_Mesh* theMeshDS,
5026 TIDSortedElemSet& theElemSet,
5027 const SMDSAbs_ElementType theType,
5028 const bool emptyIfIsMesh,
5029 IDSource_Error* error)
5032 if ( error ) *error = IDSource_OK;
5034 if ( CORBA::is_nil( theIDSource ) )
5036 if ( error ) *error = IDSource_INVALID;
5039 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5041 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5042 *error = IDSource_EMPTY;
5045 prepareIdSource( theIDSource );
5046 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5047 if ( anIDs->length() == 0 )
5049 if ( error ) *error = IDSource_EMPTY;
5052 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5053 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5055 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5057 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5061 if ( error ) *error = IDSource_INVALID;
5067 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5068 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5070 if ( error ) *error = IDSource_INVALID;
5077 //================================================================================
5079 * \brief Duplicates given elements, i.e. creates new elements based on the
5080 * same nodes as the given ones.
5081 * \param theElements - container of elements to duplicate.
5082 * \param theGroupName - a name of group to contain the generated elements.
5083 * If a group with such a name already exists, the new elements
5084 * are added to the existng group, else a new group is created.
5085 * If \a theGroupName is empty, new elements are not added
5087 * \return a group where the new elements are added. NULL if theGroupName == "".
5090 //================================================================================
5092 SMESH::SMESH_Group_ptr
5093 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5094 const char* theGroupName)
5095 throw (SALOME::SALOME_Exception)
5097 SMESH::SMESH_Group_var newGroup;
5104 TIDSortedElemSet elems;
5105 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5107 getEditor().DoubleElements( elems );
5109 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5112 SMESH::ElementType type =
5113 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5114 // find existing group
5115 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5116 for ( size_t i = 0; i < groups->length(); ++i )
5117 if ( groups[i]->GetType() == type )
5119 CORBA::String_var name = groups[i]->GetName();
5120 if ( strcmp( name, theGroupName ) == 0 ) {
5121 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5125 // create a new group
5126 if ( newGroup->_is_nil() )
5127 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5129 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5131 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5132 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5133 for ( int i = 1; i <= aSeq.Length(); i++ )
5134 groupDS->SMDSGroup().Add( aSeq(i) );
5139 if ( !newGroup->_is_nil() )
5140 pyDump << newGroup << " = ";
5141 pyDump << this << ".DoubleElements( "
5142 << theElements << ", " << "'" << theGroupName <<"')";
5144 SMESH_CATCH( SMESH::throwCorbaException );
5146 return newGroup._retn();
5149 //================================================================================
5151 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5152 \param theNodes - identifiers of nodes to be doubled
5153 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5154 nodes. If list of element identifiers is empty then nodes are doubled but
5155 they not assigned to elements
5156 \return TRUE if operation has been completed successfully, FALSE otherwise
5157 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5159 //================================================================================
5161 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5162 const SMESH::long_array& theModifiedElems )
5163 throw (SALOME::SALOME_Exception)
5168 list< int > aListOfNodes;
5170 for ( i = 0, n = theNodes.length(); i < n; i++ )
5171 aListOfNodes.push_back( theNodes[ i ] );
5173 list< int > aListOfElems;
5174 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5175 aListOfElems.push_back( theModifiedElems[ i ] );
5177 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5179 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5181 // Update Python script
5182 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5186 SMESH_CATCH( SMESH::throwCorbaException );
5190 //================================================================================
5192 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5193 This method provided for convenience works as DoubleNodes() described above.
5194 \param theNodeId - identifier of node to be doubled.
5195 \param theModifiedElems - identifiers of elements to be updated.
5196 \return TRUE if operation has been completed successfully, FALSE otherwise
5197 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5199 //================================================================================
5201 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5202 const SMESH::long_array& theModifiedElems )
5203 throw (SALOME::SALOME_Exception)
5206 SMESH::long_array_var aNodes = new SMESH::long_array;
5207 aNodes->length( 1 );
5208 aNodes[ 0 ] = theNodeId;
5210 TPythonDump pyDump; // suppress dump by the next line
5212 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5214 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5218 SMESH_CATCH( SMESH::throwCorbaException );
5222 //================================================================================
5224 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5225 This method provided for convenience works as DoubleNodes() described above.
5226 \param theNodes - group of nodes to be doubled.
5227 \param theModifiedElems - group of elements to be updated.
5228 \return TRUE if operation has been completed successfully, FALSE otherwise
5229 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5231 //================================================================================
5233 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5234 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5235 throw (SALOME::SALOME_Exception)
5238 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5241 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5242 SMESH::long_array_var aModifiedElems;
5243 if ( !CORBA::is_nil( theModifiedElems ) )
5244 aModifiedElems = theModifiedElems->GetListOfID();
5247 aModifiedElems = new SMESH::long_array;
5248 aModifiedElems->length( 0 );
5251 TPythonDump pyDump; // suppress dump by the next line
5253 bool done = DoubleNodes( aNodes, aModifiedElems );
5255 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5259 SMESH_CATCH( SMESH::throwCorbaException );
5263 //================================================================================
5265 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5266 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5267 * \param theNodes - group of nodes to be doubled.
5268 * \param theModifiedElems - group of elements to be updated.
5269 * \return a new group with newly created nodes
5270 * \sa DoubleNodeGroup()
5272 //================================================================================
5274 SMESH::SMESH_Group_ptr
5275 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5276 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5277 throw (SALOME::SALOME_Exception)
5280 SMESH::SMESH_Group_var aNewGroup;
5282 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5283 return aNewGroup._retn();
5286 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5287 SMESH::long_array_var aModifiedElems;
5288 if ( !CORBA::is_nil( theModifiedElems ) )
5289 aModifiedElems = theModifiedElems->GetListOfID();
5291 aModifiedElems = new SMESH::long_array;
5292 aModifiedElems->length( 0 );
5295 TPythonDump pyDump; // suppress dump by the next line
5297 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5300 // Create group with newly created nodes
5301 SMESH::long_array_var anIds = GetLastCreatedNodes();
5302 if (anIds->length() > 0) {
5303 string anUnindexedName (theNodes->GetName());
5304 string aNewName = generateGroupName(anUnindexedName + "_double");
5305 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5306 aNewGroup->Add(anIds);
5307 pyDump << aNewGroup << " = ";
5311 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5312 << theModifiedElems << " )";
5314 return aNewGroup._retn();
5316 SMESH_CATCH( SMESH::throwCorbaException );
5320 //================================================================================
5322 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5323 This method provided for convenience works as DoubleNodes() described above.
5324 \param theNodes - list of groups of nodes to be doubled
5325 \param theModifiedElems - list of groups of elements to be updated.
5326 \return TRUE if operation has been completed successfully, FALSE otherwise
5327 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5329 //================================================================================
5331 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5332 const SMESH::ListOfGroups& theModifiedElems )
5333 throw (SALOME::SALOME_Exception)
5338 std::list< int > aNodes;
5340 for ( i = 0, n = theNodes.length(); i < n; i++ )
5342 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5343 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5345 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5346 for ( j = 0, m = aCurr->length(); j < m; j++ )
5347 aNodes.push_back( aCurr[ j ] );
5351 std::list< int > anElems;
5352 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5354 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5355 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5357 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5358 for ( j = 0, m = aCurr->length(); j < m; j++ )
5359 anElems.push_back( aCurr[ j ] );
5363 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5365 declareMeshModified( /*isReComputeSafe=*/false );
5367 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5371 SMESH_CATCH( SMESH::throwCorbaException );
5375 //================================================================================
5377 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5378 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5379 * \param theNodes - group of nodes to be doubled.
5380 * \param theModifiedElems - group of elements to be updated.
5381 * \return a new group with newly created nodes
5382 * \sa DoubleNodeGroups()
5384 //================================================================================
5386 SMESH::SMESH_Group_ptr
5387 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5388 const SMESH::ListOfGroups& theModifiedElems )
5389 throw (SALOME::SALOME_Exception)
5391 SMESH::SMESH_Group_var aNewGroup;
5393 TPythonDump pyDump; // suppress dump by the next line
5395 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5399 // Create group with newly created nodes
5400 SMESH::long_array_var anIds = GetLastCreatedNodes();
5401 if (anIds->length() > 0) {
5402 string anUnindexedName (theNodes[0]->GetName());
5403 string aNewName = generateGroupName(anUnindexedName + "_double");
5404 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5405 aNewGroup->Add(anIds);
5406 pyDump << aNewGroup << " = ";
5410 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5411 << theModifiedElems << " )";
5413 return aNewGroup._retn();
5417 //================================================================================
5419 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5420 \param theElems - the list of elements (edges or faces) to be replicated
5421 The nodes for duplication could be found from these elements
5422 \param theNodesNot - list of nodes to NOT replicate
5423 \param theAffectedElems - the list of elements (cells and edges) to which the
5424 replicated nodes should be associated to.
5425 \return TRUE if operation has been completed successfully, FALSE otherwise
5426 \sa DoubleNodeGroup(), DoubleNodeGroups()
5428 //================================================================================
5430 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5431 const SMESH::long_array& theNodesNot,
5432 const SMESH::long_array& theAffectedElems )
5433 throw (SALOME::SALOME_Exception)
5438 SMESHDS_Mesh* aMeshDS = getMeshDS();
5439 TIDSortedElemSet anElems, aNodes, anAffected;
5440 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5441 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5442 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5444 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5446 // Update Python script
5447 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5448 << theNodesNot << ", " << theAffectedElems << " )";
5450 declareMeshModified( /*isReComputeSafe=*/false );
5453 SMESH_CATCH( SMESH::throwCorbaException );
5457 //================================================================================
5459 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5460 \param theElems - the list of elements (edges or faces) to be replicated
5461 The nodes for duplication could be found from these elements
5462 \param theNodesNot - list of nodes to NOT replicate
5463 \param theShape - shape to detect affected elements (element which geometric center
5464 located on or inside shape).
5465 The replicated nodes should be associated to affected elements.
5466 \return TRUE if operation has been completed successfully, FALSE otherwise
5467 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5469 //================================================================================
5471 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5472 const SMESH::long_array& theNodesNot,
5473 GEOM::GEOM_Object_ptr theShape )
5474 throw (SALOME::SALOME_Exception)
5480 SMESHDS_Mesh* aMeshDS = getMeshDS();
5481 TIDSortedElemSet anElems, aNodes;
5482 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5483 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5485 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5486 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5488 // Update Python script
5489 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5490 << theNodesNot << ", " << theShape << " )";
5492 declareMeshModified( /*isReComputeSafe=*/false );
5495 SMESH_CATCH( SMESH::throwCorbaException );
5499 //================================================================================
5501 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5502 \param theElems - group of of elements (edges or faces) to be replicated
5503 \param theNodesNot - group of nodes not to replicated
5504 \param theAffectedElems - group of elements to which the replicated nodes
5505 should be associated to.
5506 \return TRUE if operation has been completed successfully, FALSE otherwise
5507 \sa DoubleNodes(), DoubleNodeGroups()
5509 //================================================================================
5512 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5513 SMESH::SMESH_GroupBase_ptr theNodesNot,
5514 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5515 throw (SALOME::SALOME_Exception)
5518 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5524 SMESHDS_Mesh* aMeshDS = getMeshDS();
5525 TIDSortedElemSet anElems, aNodes, anAffected;
5526 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5527 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5528 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5530 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5532 // Update Python script
5533 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5534 << theNodesNot << ", " << theAffectedElems << " )";
5536 declareMeshModified( /*isReComputeSafe=*/false );
5539 SMESH_CATCH( SMESH::throwCorbaException );
5543 //================================================================================
5545 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5546 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5547 * \param theElems - group of of elements (edges or faces) to be replicated
5548 * \param theNodesNot - group of nodes not to replicated
5549 * \param theAffectedElems - group of elements to which the replicated nodes
5550 * should be associated to.
5551 * \return a new group with newly created elements
5552 * \sa DoubleNodeElemGroup()
5554 //================================================================================
5556 SMESH::SMESH_Group_ptr
5557 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5558 SMESH::SMESH_GroupBase_ptr theNodesNot,
5559 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5560 throw (SALOME::SALOME_Exception)
5563 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5567 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5568 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5570 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5572 << theNodesNot << ", "
5573 << theAffectedElems << " )";
5575 return elemGroup._retn();
5578 //================================================================================
5580 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5581 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5582 * \param theElems - group of of elements (edges or faces) to be replicated
5583 * \param theNodesNot - group of nodes not to replicated
5584 * \param theAffectedElems - group of elements to which the replicated nodes
5585 * should be associated to.
5586 * \return a new group with newly created elements
5587 * \sa DoubleNodeElemGroup()
5589 //================================================================================
5591 SMESH::ListOfGroups*
5592 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5593 SMESH::SMESH_GroupBase_ptr theNodesNot,
5594 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5595 CORBA::Boolean theElemGroupNeeded,
5596 CORBA::Boolean theNodeGroupNeeded)
5597 throw (SALOME::SALOME_Exception)
5600 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5601 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5602 aTwoGroups->length( 2 );
5604 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5605 return aTwoGroups._retn();
5610 SMESHDS_Mesh* aMeshDS = getMeshDS();
5611 TIDSortedElemSet anElems, aNodes, anAffected;
5612 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5613 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5614 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5617 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5619 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5625 // Create group with newly created elements
5626 CORBA::String_var elemGroupName = theElems->GetName();
5627 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5628 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5630 SMESH::long_array_var anIds = GetLastCreatedElems();
5631 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5632 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5633 aNewElemGroup->Add(anIds);
5635 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5637 SMESH::long_array_var anIds = GetLastCreatedNodes();
5638 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5639 aNewNodeGroup->Add(anIds);
5643 // Update Python script
5646 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5647 else pyDump << aNewElemGroup << ", ";
5648 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5649 else pyDump << aNewNodeGroup << " ] = ";
5651 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5652 << theNodesNot << ", "
5653 << theAffectedElems << ", "
5654 << theElemGroupNeeded << ", "
5655 << theNodeGroupNeeded <<" )";
5657 aTwoGroups[0] = aNewElemGroup._retn();
5658 aTwoGroups[1] = aNewNodeGroup._retn();
5659 return aTwoGroups._retn();
5661 SMESH_CATCH( SMESH::throwCorbaException );
5665 //================================================================================
5667 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5668 \param theElems - group of of elements (edges or faces) to be replicated
5669 \param theNodesNot - group of nodes not to replicated
5670 \param theShape - shape to detect affected elements (element which geometric center
5671 located on or inside shape).
5672 The replicated nodes should be associated to affected elements.
5673 \return TRUE if operation has been completed successfully, FALSE otherwise
5674 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5676 //================================================================================
5679 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5680 SMESH::SMESH_GroupBase_ptr theNodesNot,
5681 GEOM::GEOM_Object_ptr theShape )
5682 throw (SALOME::SALOME_Exception)
5685 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5691 SMESHDS_Mesh* aMeshDS = getMeshDS();
5692 TIDSortedElemSet anElems, aNodes, anAffected;
5693 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5694 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5696 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5697 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5700 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5702 // Update Python script
5703 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5704 << theNodesNot << ", " << theShape << " )";
5707 SMESH_CATCH( SMESH::throwCorbaException );
5711 //================================================================================
5713 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5714 * \param [in] theGrpList - groups
5715 * \param [in] theMeshDS - mesh
5716 * \param [out] theElemSet - set of elements
5717 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5719 //================================================================================
5721 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5722 SMESHDS_Mesh* theMeshDS,
5723 TIDSortedElemSet& theElemSet,
5724 const bool theIsNodeGrp)
5726 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5728 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5729 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5730 : aGrp->GetType() != SMESH::NODE ) )
5732 SMESH::long_array_var anIDs = aGrp->GetIDs();
5733 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5738 //================================================================================
5740 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5741 This method provided for convenience works as DoubleNodes() described above.
5742 \param theElems - list of groups of elements (edges or faces) to be replicated
5743 \param theNodesNot - list of groups of nodes not to replicated
5744 \param theAffectedElems - group of elements to which the replicated nodes
5745 should be associated to.
5746 \return TRUE if operation has been completed successfully, FALSE otherwise
5747 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5749 //================================================================================
5752 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5753 const SMESH::ListOfGroups& theNodesNot,
5754 const SMESH::ListOfGroups& theAffectedElems)
5755 throw (SALOME::SALOME_Exception)
5761 SMESHDS_Mesh* aMeshDS = getMeshDS();
5762 TIDSortedElemSet anElems, aNodes, anAffected;
5763 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5764 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5765 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5767 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5769 // Update Python script
5770 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5771 << &theNodesNot << ", " << &theAffectedElems << " )";
5773 declareMeshModified( /*isReComputeSafe=*/false );
5776 SMESH_CATCH( SMESH::throwCorbaException );
5780 //================================================================================
5782 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5783 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5784 \param theElems - list of groups of elements (edges or faces) to be replicated
5785 \param theNodesNot - list of groups of nodes not to replicated
5786 \param theAffectedElems - group of elements to which the replicated nodes
5787 should be associated to.
5788 * \return a new group with newly created elements
5789 * \sa DoubleNodeElemGroups()
5791 //================================================================================
5793 SMESH::SMESH_Group_ptr
5794 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5795 const SMESH::ListOfGroups& theNodesNot,
5796 const SMESH::ListOfGroups& theAffectedElems)
5797 throw (SALOME::SALOME_Exception)
5800 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
5804 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5805 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5807 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
5809 << theNodesNot << ", "
5810 << theAffectedElems << " )";
5812 return elemGroup._retn();
5815 //================================================================================
5817 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5818 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5819 \param theElems - list of groups of elements (edges or faces) to be replicated
5820 \param theNodesNot - list of groups of nodes not to replicated
5821 \param theAffectedElems - group of elements to which the replicated nodes
5822 should be associated to.
5823 * \return a new group with newly created elements
5824 * \sa DoubleNodeElemGroups()
5826 //================================================================================
5828 SMESH::ListOfGroups*
5829 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
5830 const SMESH::ListOfGroups& theNodesNot,
5831 const SMESH::ListOfGroups& theAffectedElems,
5832 CORBA::Boolean theElemGroupNeeded,
5833 CORBA::Boolean theNodeGroupNeeded)
5834 throw (SALOME::SALOME_Exception)
5837 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5838 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5839 aTwoGroups->length( 2 );
5844 SMESHDS_Mesh* aMeshDS = getMeshDS();
5845 TIDSortedElemSet anElems, aNodes, anAffected;
5846 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5847 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5848 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5850 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5852 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5857 // Create group with newly created elements
5858 CORBA::String_var elemGroupName = theElems[0]->GetName();
5859 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5860 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5862 SMESH::long_array_var anIds = GetLastCreatedElems();
5863 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5864 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5865 aNewElemGroup->Add(anIds);
5867 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5869 SMESH::long_array_var anIds = GetLastCreatedNodes();
5870 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5871 aNewNodeGroup->Add(anIds);
5875 // Update Python script
5878 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5879 else pyDump << aNewElemGroup << ", ";
5880 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5881 else pyDump << aNewNodeGroup << " ] = ";
5883 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
5884 << &theNodesNot << ", "
5885 << &theAffectedElems << ", "
5886 << theElemGroupNeeded << ", "
5887 << theNodeGroupNeeded << " )";
5889 aTwoGroups[0] = aNewElemGroup._retn();
5890 aTwoGroups[1] = aNewNodeGroup._retn();
5891 return aTwoGroups._retn();
5893 SMESH_CATCH( SMESH::throwCorbaException );
5897 //================================================================================
5899 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5900 This method provided for convenience works as DoubleNodes() described above.
5901 \param theElems - list of groups of elements (edges or faces) to be replicated
5902 \param theNodesNot - list of groups of nodes not to replicated
5903 \param theShape - shape to detect affected elements (element which geometric center
5904 located on or inside shape).
5905 The replicated nodes should be associated to affected elements.
5906 \return TRUE if operation has been completed successfully, FALSE otherwise
5907 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5909 //================================================================================
5912 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5913 const SMESH::ListOfGroups& theNodesNot,
5914 GEOM::GEOM_Object_ptr theShape )
5915 throw (SALOME::SALOME_Exception)
5921 SMESHDS_Mesh* aMeshDS = getMeshDS();
5922 TIDSortedElemSet anElems, aNodes;
5923 listOfGroupToSet(theElems, aMeshDS, anElems,false );
5924 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5926 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5927 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5929 // Update Python script
5930 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5931 << &theNodesNot << ", " << theShape << " )";
5933 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5936 SMESH_CATCH( SMESH::throwCorbaException );
5940 //================================================================================
5942 \brief Identify the elements that will be affected by node duplication (actual
5943 duplication is not performed.
5944 This method is the first step of DoubleNodeElemGroupsInRegion.
5945 \param theElems - list of groups of elements (edges or faces) to be replicated
5946 \param theNodesNot - list of groups of nodes not to replicated
5947 \param theShape - shape to detect affected elements (element which geometric center
5948 located on or inside shape).
5949 The replicated nodes should be associated to affected elements.
5950 \return groups of affected elements
5951 \sa DoubleNodeElemGroupsInRegion()
5953 //================================================================================
5954 SMESH::ListOfGroups*
5955 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
5956 const SMESH::ListOfGroups& theNodesNot,
5957 GEOM::GEOM_Object_ptr theShape )
5958 throw (SALOME::SALOME_Exception)
5961 MESSAGE("AffectedElemGroupsInRegion");
5962 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
5963 bool isEdgeGroup = false;
5964 bool isFaceGroup = false;
5965 bool isVolumeGroup = false;
5966 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
5967 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
5968 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
5972 ::SMESH_MeshEditor aMeshEditor(myMesh);
5974 SMESHDS_Mesh* aMeshDS = getMeshDS();
5975 TIDSortedElemSet anElems, aNodes;
5976 listOfGroupToSet(theElems, aMeshDS, anElems, false);
5977 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
5979 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
5980 TIDSortedElemSet anAffected;
5981 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
5984 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5989 int lg = anAffected.size();
5990 MESSAGE("lg="<< lg);
5991 SMESH::long_array_var volumeIds = new SMESH::long_array;
5992 volumeIds->length(lg);
5993 SMESH::long_array_var faceIds = new SMESH::long_array;
5994 faceIds->length(lg);
5995 SMESH::long_array_var edgeIds = new SMESH::long_array;
5996 edgeIds->length(lg);
6001 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6002 for (; eIt != anAffected.end(); ++eIt)
6004 const SMDS_MeshElement* anElem = *eIt;
6007 int elemId = anElem->GetID();
6008 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6009 volumeIds[ivol++] = elemId;
6010 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6011 faceIds[iface++] = elemId;
6012 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6013 edgeIds[iedge++] = elemId;
6015 volumeIds->length(ivol);
6016 faceIds->length(iface);
6017 edgeIds->length(iedge);
6019 aNewVolumeGroup->Add(volumeIds);
6020 aNewFaceGroup->Add(faceIds);
6021 aNewEdgeGroup->Add(edgeIds);
6022 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6023 isFaceGroup = (aNewFaceGroup->Size() > 0);
6024 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6028 if (isEdgeGroup) nbGroups++;
6029 if (isFaceGroup) nbGroups++;
6030 if (isVolumeGroup) nbGroups++;
6031 aListOfGroups->length(nbGroups);
6034 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6035 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6036 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6038 // Update Python script
6041 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6042 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6043 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6045 pyDump << this << ".AffectedElemGroupsInRegion( "
6046 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6048 return aListOfGroups._retn();
6050 SMESH_CATCH( SMESH::throwCorbaException );
6054 //================================================================================
6056 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6057 The created 2D mesh elements based on nodes of free faces of boundary volumes
6058 \return TRUE if operation has been completed successfully, FALSE otherwise
6060 //================================================================================
6062 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6063 throw (SALOME::SALOME_Exception)
6068 bool aResult = getEditor().Make2DMeshFrom3D();
6070 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6072 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6075 SMESH_CATCH( SMESH::throwCorbaException );
6079 //================================================================================
6081 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6082 * The list of groups must contain at least two groups. The groups have to be disjoint:
6083 * no common element into two different groups.
6084 * The nodes of the internal faces at the boundaries of the groups are doubled.
6085 * Optionally, the internal faces are replaced by flat elements.
6086 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6087 * The flat elements are stored in groups of volumes.
6088 * These groups are named according to the position of the group in the list:
6089 * 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.
6090 * 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.
6091 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6092 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6093 * \param theDomains - list of groups of volumes
6094 * \param createJointElems - if TRUE, create the elements
6095 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6096 * the boundary between \a theDomains and the rest mesh
6097 * \return TRUE if operation has been completed successfully, FALSE otherwise
6099 //================================================================================
6102 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6103 CORBA::Boolean createJointElems,
6104 CORBA::Boolean onAllBoundaries )
6105 throw (SALOME::SALOME_Exception)
6112 SMESHDS_Mesh* aMeshDS = getMeshDS();
6114 // MESSAGE("theDomains.length = "<<theDomains.length());
6115 if ( theDomains.length() <= 1 && !onAllBoundaries )
6116 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6118 vector<TIDSortedElemSet> domains;
6119 domains.resize( theDomains.length() );
6121 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6123 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6124 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6126 // if ( aGrp->GetType() != SMESH::VOLUME )
6127 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6128 SMESH::long_array_var anIDs = aGrp->GetIDs();
6129 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6133 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6134 // TODO publish the groups of flat elements in study
6136 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6138 // Update Python script
6139 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6140 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6142 SMESH_CATCH( SMESH::throwCorbaException );
6144 myMesh_i->CreateGroupServants(); // publish created groups if any
6149 //================================================================================
6151 * \brief Double nodes on some external faces and create flat elements.
6152 * Flat elements are mainly used by some types of mechanic calculations.
6154 * Each group of the list must be constituted of faces.
6155 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6156 * @param theGroupsOfFaces - list of groups of faces
6157 * @return TRUE if operation has been completed successfully, FALSE otherwise
6159 //================================================================================
6162 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6163 throw (SALOME::SALOME_Exception)
6168 SMESHDS_Mesh* aMeshDS = getMeshDS();
6170 vector<TIDSortedElemSet> faceGroups;
6173 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6175 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6176 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6178 TIDSortedElemSet faceGroup;
6180 faceGroups.push_back(faceGroup);
6181 SMESH::long_array_var anIDs = aGrp->GetIDs();
6182 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6186 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6187 // TODO publish the groups of flat elements in study
6189 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6191 // Update Python script
6192 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6195 SMESH_CATCH( SMESH::throwCorbaException );
6199 //================================================================================
6201 * \brief Identify all the elements around a geom shape, get the faces delimiting
6204 * Build groups of volume to remove, groups of faces to replace on the skin of the
6205 * object, groups of faces to remove inside the object, (idem edges).
6206 * Build ordered list of nodes at the border of each group of faces to replace
6207 * (to be used to build a geom subshape).
6209 //================================================================================
6211 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6212 GEOM::GEOM_Object_ptr theShape,
6213 const char* groupName,
6214 const SMESH::double_array& theNodesCoords,
6215 SMESH::array_of_long_array_out GroupsOfNodes)
6216 throw (SALOME::SALOME_Exception)
6221 std::vector<std::vector<int> > aListOfListOfNodes;
6222 ::SMESH_MeshEditor aMeshEditor( myMesh );
6224 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6225 if ( !theNodeSearcher )
6226 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6228 vector<double> nodesCoords;
6229 for (int i = 0; i < theNodesCoords.length(); i++)
6231 nodesCoords.push_back( theNodesCoords[i] );
6234 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6235 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6236 nodesCoords, aListOfListOfNodes);
6238 GroupsOfNodes = new SMESH::array_of_long_array;
6239 GroupsOfNodes->length( aListOfListOfNodes.size() );
6240 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6241 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6243 vector<int>& aListOfNodes = *llIt;
6244 vector<int>::iterator lIt = aListOfNodes.begin();;
6245 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6246 aGroup.length( aListOfNodes.size() );
6247 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6248 aGroup[ j ] = (*lIt);
6250 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6253 << ", '" << groupName << "', "
6254 << theNodesCoords << " )";
6256 SMESH_CATCH( SMESH::throwCorbaException );
6259 // issue 20749 ===================================================================
6261 * \brief Creates missing boundary elements
6262 * \param elements - elements whose boundary is to be checked
6263 * \param dimension - defines type of boundary elements to create
6264 * \param groupName - a name of group to store created boundary elements in,
6265 * "" means not to create the group
6266 * \param meshName - a name of new mesh to store created boundary elements in,
6267 * "" means not to create the new mesh
6268 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6269 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6270 * boundary elements will be copied into the new mesh
6271 * \param group - returns the create group, if any
6272 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6274 // ================================================================================
6276 SMESH::SMESH_Mesh_ptr
6277 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6278 SMESH::Bnd_Dimension dim,
6279 const char* groupName,
6280 const char* meshName,
6281 CORBA::Boolean toCopyElements,
6282 CORBA::Boolean toCopyExistingBondary,
6283 SMESH::SMESH_Group_out group)
6284 throw (SALOME::SALOME_Exception)
6289 if ( dim > SMESH::BND_1DFROM2D )
6290 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6292 SMESHDS_Mesh* aMeshDS = getMeshDS();
6294 SMESH::SMESH_Mesh_var mesh_var;
6295 SMESH::SMESH_Group_var group_var;
6299 TIDSortedElemSet elements;
6300 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6301 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6305 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6306 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6308 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6310 // group of new boundary elements
6311 SMESH_Group* smesh_group = 0;
6312 if ( strlen(groupName) )
6314 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6315 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6316 smesh_group = group_i->GetSmeshGroup();
6320 getEditor().MakeBoundaryMesh( elements,
6321 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6325 toCopyExistingBondary);
6328 smesh_mesh->GetMeshDS()->Modified();
6331 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6333 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6334 if ( mesh_var->_is_nil() )
6335 pyDump << myMesh_i->_this() << ", ";
6337 pyDump << mesh_var << ", ";
6338 if ( group_var->_is_nil() )
6339 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6341 pyDump << group_var << " = ";
6342 pyDump << this << ".MakeBoundaryMesh( "
6344 << "SMESH." << dimName[int(dim)] << ", "
6345 << "'" << groupName << "', "
6346 << "'" << meshName<< "', "
6347 << toCopyElements << ", "
6348 << toCopyExistingBondary << ")";
6350 group = group_var._retn();
6351 return mesh_var._retn();
6353 SMESH_CATCH( SMESH::throwCorbaException );
6354 return SMESH::SMESH_Mesh::_nil();
6357 //================================================================================
6359 * \brief Creates missing boundary elements
6360 * \param dimension - defines type of boundary elements to create
6361 * \param groupName - a name of group to store all boundary elements in,
6362 * "" means not to create the group
6363 * \param meshName - a name of a new mesh, which is a copy of the initial
6364 * mesh + created boundary elements; "" means not to create the new mesh
6365 * \param toCopyAll - if true, the whole initial mesh will be copied into
6366 * the new mesh else only boundary elements will be copied into the new mesh
6367 * \param groups - optional groups of elements to make boundary around
6368 * \param mesh - returns the mesh where elements were added to
6369 * \param group - returns the created group, if any
6370 * \retval long - number of added boundary elements
6372 //================================================================================
6374 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6375 const char* groupName,
6376 const char* meshName,
6377 CORBA::Boolean toCopyAll,
6378 const SMESH::ListOfIDSources& groups,
6379 SMESH::SMESH_Mesh_out mesh,
6380 SMESH::SMESH_Group_out group)
6381 throw (SALOME::SALOME_Exception)
6386 if ( dim > SMESH::BND_1DFROM2D )
6387 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6389 // separate groups belonging to this and other mesh
6390 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6391 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6392 groupsOfThisMesh->length( groups.length() );
6393 groupsOfOtherMesh->length( groups.length() );
6394 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6395 for ( int i = 0; i < groups.length(); ++i )
6397 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6398 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6399 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6401 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6402 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6403 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6405 groupsOfThisMesh->length( nbGroups );
6406 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6411 if ( nbGroupsOfOtherMesh > 0 )
6413 // process groups belonging to another mesh
6414 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6415 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6416 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6417 groupsOfOtherMesh, mesh, group );
6420 SMESH::SMESH_Mesh_var mesh_var;
6421 SMESH::SMESH_Group_var group_var;
6424 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6425 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6429 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6431 /*toCopyGroups=*/false,
6432 /*toKeepIDs=*/true);
6434 mesh_var = makeMesh(meshName);
6436 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6437 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6440 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6441 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6443 // group of boundary elements
6444 SMESH_Group* smesh_group = 0;
6445 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6446 if ( strlen(groupName) )
6448 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6449 group_var = mesh_i->CreateGroup( groupType, groupName );
6450 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6451 smesh_group = group_i->GetSmeshGroup();
6454 TIDSortedElemSet elements;
6456 if ( groups.length() > 0 )
6458 for ( int i = 0; i < nbGroups; ++i )
6461 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6463 SMESH::Bnd_Dimension bdim =
6464 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6465 nbAdded += getEditor().MakeBoundaryMesh( elements,
6466 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6469 /*toCopyElements=*/false,
6470 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6471 /*toAddExistingBondary=*/true,
6472 /*aroundElements=*/true);
6478 nbAdded += getEditor().MakeBoundaryMesh( elements,
6479 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6482 /*toCopyElements=*/false,
6483 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6484 /*toAddExistingBondary=*/true);
6486 tgtMesh->GetMeshDS()->Modified();
6488 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6490 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6491 pyDump << "nbAdded, ";
6492 if ( mesh_var->_is_nil() )
6493 pyDump << myMesh_i->_this() << ", ";
6495 pyDump << mesh_var << ", ";
6496 if ( group_var->_is_nil() )
6497 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6499 pyDump << group_var << " = ";
6500 pyDump << this << ".MakeBoundaryElements( "
6501 << "SMESH." << dimName[int(dim)] << ", "
6502 << "'" << groupName << "', "
6503 << "'" << meshName<< "', "
6504 << toCopyAll << ", "
6507 mesh = mesh_var._retn();
6508 group = group_var._retn();
6511 SMESH_CATCH( SMESH::throwCorbaException );