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::FindCoincidentNodes (CORBA::Double Tolerance,
3960 SMESH::array_of_long_array_out GroupsOfNodes)
3961 throw (SALOME::SALOME_Exception)
3966 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3967 TIDSortedNodeSet nodes; // no input nodes
3968 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3970 GroupsOfNodes = new SMESH::array_of_long_array;
3971 GroupsOfNodes->length( aListOfListOfNodes.size() );
3972 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3973 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3974 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3975 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3976 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3977 aGroup.length( aListOfNodes.size() );
3978 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3979 aGroup[ j ] = (*lIt)->GetID();
3981 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3982 << Tolerance << " )";
3984 SMESH_CATCH( SMESH::throwCorbaException );
3987 //=======================================================================
3988 //function : FindCoincidentNodesOnPart
3990 //=======================================================================
3992 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
3993 CORBA::Double Tolerance,
3994 SMESH::array_of_long_array_out GroupsOfNodes)
3995 throw (SALOME::SALOME_Exception)
4000 TIDSortedNodeSet nodes;
4001 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4003 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4005 getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
4007 GroupsOfNodes = new SMESH::array_of_long_array;
4008 GroupsOfNodes->length( aListOfListOfNodes.size() );
4009 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4010 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4012 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4013 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4014 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4015 aGroup.length( aListOfNodes.size() );
4016 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4017 aGroup[ j ] = (*lIt)->GetID();
4019 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4021 << Tolerance << " )";
4023 SMESH_CATCH( SMESH::throwCorbaException );
4026 //================================================================================
4028 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4029 * ExceptSubMeshOrGroups
4031 //================================================================================
4033 void SMESH_MeshEditor_i::
4034 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4035 CORBA::Double theTolerance,
4036 SMESH::array_of_long_array_out theGroupsOfNodes,
4037 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups)
4038 throw (SALOME::SALOME_Exception)
4043 TIDSortedNodeSet nodes;
4044 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4046 for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4048 TIDSortedNodeSet exceptNodes;
4049 idSourceToNodeSet( theExceptSubMeshOrGroups[i], getMeshDS(), exceptNodes );
4050 TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
4051 for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
4052 nodes.erase( *avoidNode );
4054 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4056 getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
4058 theGroupsOfNodes = new SMESH::array_of_long_array;
4059 theGroupsOfNodes->length( aListOfListOfNodes.size() );
4060 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4061 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4063 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4064 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4065 SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
4066 aGroup.length( aListOfNodes.size() );
4067 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4068 aGroup[ j ] = (*lIt)->GetID();
4070 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4072 << theTolerance << ", "
4073 << theExceptSubMeshOrGroups << " )";
4075 SMESH_CATCH( SMESH::throwCorbaException );
4078 //=======================================================================
4079 //function : MergeNodes
4081 //=======================================================================
4083 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
4084 throw (SALOME::SALOME_Exception)
4089 SMESHDS_Mesh* aMesh = getMeshDS();
4091 TPythonDump aTPythonDump;
4092 aTPythonDump << this << ".MergeNodes([";
4093 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4094 for (int i = 0; i < GroupsOfNodes.length(); i++)
4096 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4097 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4098 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4099 for ( int j = 0; j < aNodeGroup.length(); j++ )
4101 CORBA::Long index = aNodeGroup[ j ];
4102 const SMDS_MeshNode * node = aMesh->FindNode(index);
4104 aListOfNodes.push_back( node );
4106 if ( aListOfNodes.size() < 2 )
4107 aListOfListOfNodes.pop_back();
4109 if ( i > 0 ) aTPythonDump << ", ";
4110 aTPythonDump << aNodeGroup;
4112 getEditor().MergeNodes( aListOfListOfNodes );
4114 aTPythonDump << "])";
4116 declareMeshModified( /*isReComputeSafe=*/false );
4118 SMESH_CATCH( SMESH::throwCorbaException );
4121 //=======================================================================
4122 //function : FindEqualElements
4124 //=======================================================================
4126 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4127 SMESH::array_of_long_array_out GroupsOfElementsID)
4128 throw (SALOME::SALOME_Exception)
4133 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4134 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4136 TIDSortedElemSet elems;
4137 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4139 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4140 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4142 GroupsOfElementsID = new SMESH::array_of_long_array;
4143 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4145 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4146 aListOfListOfElementsID.begin();
4147 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4149 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4150 list<int>& listOfIDs = *arraysIt;
4151 aGroup.length( listOfIDs.size() );
4152 list<int>::iterator idIt = listOfIDs.begin();
4153 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4154 aGroup[ k ] = *idIt;
4157 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4161 SMESH_CATCH( SMESH::throwCorbaException );
4164 //=======================================================================
4165 //function : MergeElements
4167 //=======================================================================
4169 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4170 throw (SALOME::SALOME_Exception)
4175 TPythonDump aTPythonDump;
4176 aTPythonDump << this << ".MergeElements( [";
4178 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4180 for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4181 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4182 aListOfListOfElementsID.push_back( list< int >() );
4183 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4184 for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4185 CORBA::Long id = anElemsIDGroup[ j ];
4186 aListOfElemsID.push_back( id );
4188 if ( aListOfElemsID.size() < 2 )
4189 aListOfListOfElementsID.pop_back();
4190 if ( i > 0 ) aTPythonDump << ", ";
4191 aTPythonDump << anElemsIDGroup;
4194 getEditor().MergeElements(aListOfListOfElementsID);
4196 declareMeshModified( /*isReComputeSafe=*/true );
4198 aTPythonDump << "] )";
4200 SMESH_CATCH( SMESH::throwCorbaException );
4203 //=======================================================================
4204 //function : MergeEqualElements
4206 //=======================================================================
4208 void SMESH_MeshEditor_i::MergeEqualElements()
4209 throw (SALOME::SALOME_Exception)
4214 getEditor().MergeEqualElements();
4216 declareMeshModified( /*isReComputeSafe=*/true );
4218 TPythonDump() << this << ".MergeEqualElements()";
4220 SMESH_CATCH( SMESH::throwCorbaException );
4223 //=============================================================================
4225 * Move the node to a given point
4227 //=============================================================================
4229 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4233 throw (SALOME::SALOME_Exception)
4236 initData(/*deleteSearchers=*/false);
4238 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4242 if ( theNodeSearcher )
4243 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4245 if ( myIsPreviewMode ) // make preview data
4247 // in a preview mesh, make edges linked to a node
4248 TPreviewMesh& tmpMesh = *getPreviewMesh();
4249 TIDSortedElemSet linkedNodes;
4250 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4251 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4252 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4253 for ( ; nIt != linkedNodes.end(); ++nIt )
4255 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4256 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4260 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4261 // fill preview data
4263 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4264 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4266 getMeshDS()->MoveNode(node, x, y, z);
4268 if ( !myIsPreviewMode )
4270 // Update Python script
4271 TPythonDump() << "isDone = " << this << ".MoveNode( "
4272 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4273 declareMeshModified( /*isReComputeSafe=*/false );
4276 SMESH_CATCH( SMESH::throwCorbaException );
4281 //================================================================================
4283 * \brief Return ID of node closest to a given point
4285 //================================================================================
4287 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4290 throw (SALOME::SALOME_Exception)
4293 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4295 if ( !theNodeSearcher ) {
4296 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4299 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4300 return node->GetID();
4302 SMESH_CATCH( SMESH::throwCorbaException );
4306 //================================================================================
4308 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4309 * move the node closest to the point to point's location and return ID of the node
4311 //================================================================================
4313 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4316 CORBA::Long theNodeID)
4317 throw (SALOME::SALOME_Exception)
4320 // We keep theNodeSearcher until any mesh modification:
4321 // 1) initData() deletes theNodeSearcher at any edition,
4322 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4324 initData(/*deleteSearchers=*/false);
4326 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4328 int nodeID = theNodeID;
4329 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4330 if ( !node ) // preview moving node
4332 if ( !theNodeSearcher ) {
4333 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4336 node = theNodeSearcher->FindClosestTo( p );
4339 nodeID = node->GetID();
4340 if ( myIsPreviewMode ) // make preview data
4342 // in a preview mesh, make edges linked to a node
4343 TPreviewMesh tmpMesh = *getPreviewMesh();
4344 TIDSortedElemSet linkedNodes;
4345 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4346 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4347 for ( ; nIt != linkedNodes.end(); ++nIt )
4349 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4350 tmpMesh.Copy( &edge );
4353 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4355 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4356 // fill preview data
4358 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4360 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4364 getMeshDS()->MoveNode(node, x, y, z);
4368 if ( !myIsPreviewMode )
4370 TPythonDump() << "nodeID = " << this
4371 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4372 << ", " << nodeID << " )";
4374 declareMeshModified( /*isReComputeSafe=*/false );
4379 SMESH_CATCH( SMESH::throwCorbaException );
4383 //=======================================================================
4385 * Return elements of given type where the given point is IN or ON.
4387 * 'ALL' type means elements of any type excluding nodes
4389 //=======================================================================
4391 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4394 SMESH::ElementType type)
4395 throw (SALOME::SALOME_Exception)
4398 SMESH::long_array_var res = new SMESH::long_array;
4399 vector< const SMDS_MeshElement* > foundElems;
4401 theSearchersDeleter.Set( myMesh );
4402 if ( !theElementSearcher ) {
4403 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4405 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4406 SMDSAbs_ElementType( type ),
4408 res->length( foundElems.size() );
4409 for ( int i = 0; i < foundElems.size(); ++i )
4410 res[i] = foundElems[i]->GetID();
4414 SMESH_CATCH( SMESH::throwCorbaException );
4418 //=======================================================================
4419 //function : FindAmongElementsByPoint
4420 //purpose : Searching among the given elements, return elements of given type
4421 // where the given point is IN or ON.
4422 // 'ALL' type means elements of any type excluding nodes
4423 //=======================================================================
4426 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4430 SMESH::ElementType type)
4431 throw (SALOME::SALOME_Exception)
4434 SMESH::long_array_var res = new SMESH::long_array;
4436 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4437 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4438 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4439 type != types[0] ) // but search of elements of dim > 0
4442 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4443 return FindElementsByPoint( x,y,z, type );
4445 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4447 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4448 if ( !theElementSearcher )
4450 // create a searcher from elementIDs
4451 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4452 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4454 if ( !idSourceToSet( elementIDs, meshDS, elements,
4455 SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4458 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4459 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4461 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4464 vector< const SMDS_MeshElement* > foundElems;
4466 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4467 SMDSAbs_ElementType( type ),
4469 res->length( foundElems.size() );
4470 for ( int i = 0; i < foundElems.size(); ++i )
4471 res[i] = foundElems[i]->GetID();
4475 SMESH_CATCH( SMESH::throwCorbaException );
4479 //=======================================================================
4480 //function : GetPointState
4481 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4482 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4483 //=======================================================================
4485 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4488 throw (SALOME::SALOME_Exception)
4491 theSearchersDeleter.Set( myMesh );
4492 if ( !theElementSearcher ) {
4493 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4495 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4497 SMESH_CATCH( SMESH::throwCorbaException );
4501 //=======================================================================
4502 //function : convError
4504 //=======================================================================
4506 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4508 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4512 RETCASE( SEW_BORDER1_NOT_FOUND );
4513 RETCASE( SEW_BORDER2_NOT_FOUND );
4514 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4515 RETCASE( SEW_BAD_SIDE_NODES );
4516 RETCASE( SEW_VOLUMES_TO_SPLIT );
4517 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4518 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4519 RETCASE( SEW_BAD_SIDE1_NODES );
4520 RETCASE( SEW_BAD_SIDE2_NODES );
4522 return SMESH::SMESH_MeshEditor::SEW_OK;
4525 //=======================================================================
4526 //function : SewFreeBorders
4528 //=======================================================================
4530 SMESH::SMESH_MeshEditor::Sew_Error
4531 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4532 CORBA::Long SecondNodeID1,
4533 CORBA::Long LastNodeID1,
4534 CORBA::Long FirstNodeID2,
4535 CORBA::Long SecondNodeID2,
4536 CORBA::Long LastNodeID2,
4537 CORBA::Boolean CreatePolygons,
4538 CORBA::Boolean CreatePolyedrs)
4539 throw (SALOME::SALOME_Exception)
4544 SMESHDS_Mesh* aMesh = getMeshDS();
4546 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4547 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4548 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4549 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4550 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4551 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4553 if (!aBorderFirstNode ||
4554 !aBorderSecondNode||
4556 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4557 if (!aSide2FirstNode ||
4558 !aSide2SecondNode ||
4560 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4562 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4563 << FirstNodeID1 << ", "
4564 << SecondNodeID1 << ", "
4565 << LastNodeID1 << ", "
4566 << FirstNodeID2 << ", "
4567 << SecondNodeID2 << ", "
4568 << LastNodeID2 << ", "
4569 << CreatePolygons<< ", "
4570 << CreatePolyedrs<< " )";
4572 SMESH::SMESH_MeshEditor::Sew_Error error =
4573 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4584 declareMeshModified( /*isReComputeSafe=*/false );
4587 SMESH_CATCH( SMESH::throwCorbaException );
4588 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4592 //=======================================================================
4593 //function : SewConformFreeBorders
4595 //=======================================================================
4597 SMESH::SMESH_MeshEditor::Sew_Error
4598 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4599 CORBA::Long SecondNodeID1,
4600 CORBA::Long LastNodeID1,
4601 CORBA::Long FirstNodeID2,
4602 CORBA::Long SecondNodeID2)
4603 throw (SALOME::SALOME_Exception)
4608 SMESHDS_Mesh* aMesh = getMeshDS();
4610 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4611 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4612 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4613 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4614 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4615 const SMDS_MeshNode* aSide2ThirdNode = 0;
4617 if (!aBorderFirstNode ||
4618 !aBorderSecondNode||
4620 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4621 if (!aSide2FirstNode ||
4623 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4625 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4626 << FirstNodeID1 << ", "
4627 << SecondNodeID1 << ", "
4628 << LastNodeID1 << ", "
4629 << FirstNodeID2 << ", "
4630 << SecondNodeID2 << " )";
4632 SMESH::SMESH_MeshEditor::Sew_Error error =
4633 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4642 declareMeshModified( /*isReComputeSafe=*/false );
4645 SMESH_CATCH( SMESH::throwCorbaException );
4646 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4650 //=======================================================================
4651 //function : SewBorderToSide
4653 //=======================================================================
4655 SMESH::SMESH_MeshEditor::Sew_Error
4656 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4657 CORBA::Long SecondNodeIDOnFreeBorder,
4658 CORBA::Long LastNodeIDOnFreeBorder,
4659 CORBA::Long FirstNodeIDOnSide,
4660 CORBA::Long LastNodeIDOnSide,
4661 CORBA::Boolean CreatePolygons,
4662 CORBA::Boolean CreatePolyedrs)
4663 throw (SALOME::SALOME_Exception)
4668 SMESHDS_Mesh* aMesh = getMeshDS();
4670 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4671 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4672 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4673 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4674 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4675 const SMDS_MeshNode* aSide2ThirdNode = 0;
4677 if (!aBorderFirstNode ||
4678 !aBorderSecondNode||
4680 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4681 if (!aSide2FirstNode ||
4683 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4685 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4686 << FirstNodeIDOnFreeBorder << ", "
4687 << SecondNodeIDOnFreeBorder << ", "
4688 << LastNodeIDOnFreeBorder << ", "
4689 << FirstNodeIDOnSide << ", "
4690 << LastNodeIDOnSide << ", "
4691 << CreatePolygons << ", "
4692 << CreatePolyedrs << ") ";
4694 SMESH::SMESH_MeshEditor::Sew_Error error =
4695 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4705 declareMeshModified( /*isReComputeSafe=*/false );
4708 SMESH_CATCH( SMESH::throwCorbaException );
4709 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4713 //=======================================================================
4714 //function : SewSideElements
4716 //=======================================================================
4718 SMESH::SMESH_MeshEditor::Sew_Error
4719 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4720 const SMESH::long_array& IDsOfSide2Elements,
4721 CORBA::Long NodeID1OfSide1ToMerge,
4722 CORBA::Long NodeID1OfSide2ToMerge,
4723 CORBA::Long NodeID2OfSide1ToMerge,
4724 CORBA::Long NodeID2OfSide2ToMerge)
4725 throw (SALOME::SALOME_Exception)
4730 SMESHDS_Mesh* aMesh = getMeshDS();
4732 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
4733 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
4734 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4735 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4737 if (!aFirstNode1ToMerge ||
4738 !aFirstNode2ToMerge )
4739 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4740 if (!aSecondNode1ToMerge||
4741 !aSecondNode2ToMerge)
4742 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4744 TIDSortedElemSet aSide1Elems, aSide2Elems;
4745 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4746 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4748 TPythonDump() << "error = " << this << ".SewSideElements( "
4749 << IDsOfSide1Elements << ", "
4750 << IDsOfSide2Elements << ", "
4751 << NodeID1OfSide1ToMerge << ", "
4752 << NodeID1OfSide2ToMerge << ", "
4753 << NodeID2OfSide1ToMerge << ", "
4754 << NodeID2OfSide2ToMerge << ")";
4756 SMESH::SMESH_MeshEditor::Sew_Error error =
4757 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
4760 aSecondNode1ToMerge,
4761 aSecondNode2ToMerge));
4763 declareMeshModified( /*isReComputeSafe=*/false );
4766 SMESH_CATCH( SMESH::throwCorbaException );
4767 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4770 //================================================================================
4772 * \brief Set new nodes for given element
4773 * \param ide - element id
4774 * \param newIDs - new node ids
4775 * \retval CORBA::Boolean - true if result is OK
4777 //================================================================================
4779 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4780 const SMESH::long_array& newIDs)
4781 throw (SALOME::SALOME_Exception)
4786 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
4787 if(!elem) return false;
4789 int nbn = newIDs.length();
4791 vector<const SMDS_MeshNode*> aNodes(nbn);
4794 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
4797 aNodes[nbn1] = aNode;
4800 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4801 << ide << ", " << newIDs << " )";
4803 MESSAGE("ChangeElementNodes");
4804 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4806 declareMeshModified( /*isReComputeSafe=*/ !res );
4810 SMESH_CATCH( SMESH::throwCorbaException );
4814 //=======================================================================
4816 * \brief Makes a part of the mesh quadratic or bi-quadratic
4818 //=======================================================================
4820 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
4821 CORBA::Boolean theToBiQuad,
4822 SMESH::SMESH_IDSource_ptr theObject)
4823 throw (SALOME::SALOME_Exception)
4828 TIDSortedElemSet elems;
4830 if ( !( elemsOK = CORBA::is_nil( theObject )))
4832 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
4833 SMDSAbs_All, /*emptyIfIsMesh=*/true );
4837 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
4838 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4840 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
4841 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
4843 declareMeshModified( /*isReComputeSafe=*/false );
4846 SMESH_CATCH( SMESH::throwCorbaException );
4849 //=======================================================================
4850 //function : ConvertFromQuadratic
4852 //=======================================================================
4854 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4855 throw (SALOME::SALOME_Exception)
4860 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
4861 TPythonDump() << this << ".ConvertFromQuadratic()";
4862 declareMeshModified( /*isReComputeSafe=*/!isDone );
4865 SMESH_CATCH( SMESH::throwCorbaException );
4869 //=======================================================================
4870 //function : ConvertToQuadratic
4872 //=======================================================================
4874 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4875 throw (SALOME::SALOME_Exception)
4877 convertToQuadratic( theForce3d, false );
4878 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
4881 //================================================================================
4883 * \brief Makes a part of the mesh quadratic
4885 //================================================================================
4887 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
4888 SMESH::SMESH_IDSource_ptr theObject)
4889 throw (SALOME::SALOME_Exception)
4891 convertToQuadratic( theForce3d, false, theObject );
4892 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
4895 //================================================================================
4897 * \brief Makes a part of the mesh bi-quadratic
4899 //================================================================================
4901 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
4902 SMESH::SMESH_IDSource_ptr theObject)
4903 throw (SALOME::SALOME_Exception)
4905 convertToQuadratic( theForce3d, true, theObject );
4906 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
4909 //================================================================================
4911 * \brief Makes a part of the mesh linear
4913 //================================================================================
4915 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
4916 throw (SALOME::SALOME_Exception)
4923 TIDSortedElemSet elems;
4924 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
4926 if ( elems.empty() )
4928 ConvertFromQuadratic();
4930 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
4932 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4936 getEditor().ConvertFromQuadratic(elems);
4939 declareMeshModified( /*isReComputeSafe=*/false );
4941 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
4943 SMESH_CATCH( SMESH::throwCorbaException );
4946 //=======================================================================
4947 //function : makeMesh
4948 //purpose : create a named imported mesh
4949 //=======================================================================
4951 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4953 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4954 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4955 SALOMEDS::Study_var study = gen->GetCurrentStudy();
4956 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
4957 gen->SetName( meshSO, theMeshName, "Mesh" );
4958 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4960 return mesh._retn();
4963 //=======================================================================
4964 //function : dumpGroupsList
4966 //=======================================================================
4968 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
4969 const SMESH::ListOfGroups * theGroupList)
4971 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
4972 if ( isDumpGroupList )
4973 theDumpPython << theGroupList << " = ";
4976 //================================================================================
4978 \brief Generates the unique group name.
4979 \param thePrefix name prefix
4982 //================================================================================
4984 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
4986 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4987 set<string> groupNames;
4989 // Get existing group names
4990 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
4991 SMESH::SMESH_GroupBase_var aGroup = groups[i];
4992 if (CORBA::is_nil(aGroup))
4995 CORBA::String_var name = aGroup->GetName();
4996 groupNames.insert( name.in() );
5000 string name = thePrefix;
5003 while (!groupNames.insert(name).second)
5004 name = SMESH_Comment( thePrefix ) << "_" << index++;
5009 //================================================================================
5011 * \brief Prepare SMESH_IDSource for work
5013 //================================================================================
5015 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5017 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5019 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5020 filter->SetMesh( mesh );
5023 //================================================================================
5025 * \brief Retrieve elements of given type from SMESH_IDSource
5027 //================================================================================
5029 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5030 const SMESHDS_Mesh* theMeshDS,
5031 TIDSortedElemSet& theElemSet,
5032 const SMDSAbs_ElementType theType,
5033 const bool emptyIfIsMesh,
5034 IDSource_Error* error)
5037 if ( error ) *error = IDSource_OK;
5039 if ( CORBA::is_nil( theIDSource ) )
5041 if ( error ) *error = IDSource_INVALID;
5044 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5046 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5047 *error = IDSource_EMPTY;
5050 prepareIdSource( theIDSource );
5051 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5052 if ( anIDs->length() == 0 )
5054 if ( error ) *error = IDSource_EMPTY;
5057 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5058 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5060 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5062 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5066 if ( error ) *error = IDSource_INVALID;
5072 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5073 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5075 if ( error ) *error = IDSource_INVALID;
5082 //================================================================================
5084 * \brief Duplicates given elements, i.e. creates new elements based on the
5085 * same nodes as the given ones.
5086 * \param theElements - container of elements to duplicate.
5087 * \param theGroupName - a name of group to contain the generated elements.
5088 * If a group with such a name already exists, the new elements
5089 * are added to the existng group, else a new group is created.
5090 * If \a theGroupName is empty, new elements are not added
5092 * \return a group where the new elements are added. NULL if theGroupName == "".
5095 //================================================================================
5097 SMESH::SMESH_Group_ptr
5098 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5099 const char* theGroupName)
5100 throw (SALOME::SALOME_Exception)
5102 SMESH::SMESH_Group_var newGroup;
5109 TIDSortedElemSet elems;
5110 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5112 getEditor().DoubleElements( elems );
5114 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5117 SMESH::ElementType type =
5118 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5119 // find existing group
5120 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5121 for ( size_t i = 0; i < groups->length(); ++i )
5122 if ( groups[i]->GetType() == type )
5124 CORBA::String_var name = groups[i]->GetName();
5125 if ( strcmp( name, theGroupName ) == 0 ) {
5126 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5130 // create a new group
5131 if ( newGroup->_is_nil() )
5132 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5134 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5136 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5137 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5138 for ( int i = 1; i <= aSeq.Length(); i++ )
5139 groupDS->SMDSGroup().Add( aSeq(i) );
5144 if ( !newGroup->_is_nil() )
5145 pyDump << newGroup << " = ";
5146 pyDump << this << ".DoubleElements( "
5147 << theElements << ", " << "'" << theGroupName <<"')";
5149 SMESH_CATCH( SMESH::throwCorbaException );
5151 return newGroup._retn();
5154 //================================================================================
5156 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5157 \param theNodes - identifiers of nodes to be doubled
5158 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5159 nodes. If list of element identifiers is empty then nodes are doubled but
5160 they not assigned to elements
5161 \return TRUE if operation has been completed successfully, FALSE otherwise
5162 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5164 //================================================================================
5166 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5167 const SMESH::long_array& theModifiedElems )
5168 throw (SALOME::SALOME_Exception)
5173 list< int > aListOfNodes;
5175 for ( i = 0, n = theNodes.length(); i < n; i++ )
5176 aListOfNodes.push_back( theNodes[ i ] );
5178 list< int > aListOfElems;
5179 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5180 aListOfElems.push_back( theModifiedElems[ i ] );
5182 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5184 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5186 // Update Python script
5187 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5191 SMESH_CATCH( SMESH::throwCorbaException );
5195 //================================================================================
5197 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5198 This method provided for convenience works as DoubleNodes() described above.
5199 \param theNodeId - identifier of node to be doubled.
5200 \param theModifiedElems - identifiers of elements to be updated.
5201 \return TRUE if operation has been completed successfully, FALSE otherwise
5202 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5204 //================================================================================
5206 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5207 const SMESH::long_array& theModifiedElems )
5208 throw (SALOME::SALOME_Exception)
5211 SMESH::long_array_var aNodes = new SMESH::long_array;
5212 aNodes->length( 1 );
5213 aNodes[ 0 ] = theNodeId;
5215 TPythonDump pyDump; // suppress dump by the next line
5217 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5219 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5223 SMESH_CATCH( SMESH::throwCorbaException );
5227 //================================================================================
5229 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5230 This method provided for convenience works as DoubleNodes() described above.
5231 \param theNodes - group of nodes to be doubled.
5232 \param theModifiedElems - group of elements to be updated.
5233 \return TRUE if operation has been completed successfully, FALSE otherwise
5234 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5236 //================================================================================
5238 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5239 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5240 throw (SALOME::SALOME_Exception)
5243 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5246 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5247 SMESH::long_array_var aModifiedElems;
5248 if ( !CORBA::is_nil( theModifiedElems ) )
5249 aModifiedElems = theModifiedElems->GetListOfID();
5252 aModifiedElems = new SMESH::long_array;
5253 aModifiedElems->length( 0 );
5256 TPythonDump pyDump; // suppress dump by the next line
5258 bool done = DoubleNodes( aNodes, aModifiedElems );
5260 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5264 SMESH_CATCH( SMESH::throwCorbaException );
5268 //================================================================================
5270 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5271 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5272 * \param theNodes - group of nodes to be doubled.
5273 * \param theModifiedElems - group of elements to be updated.
5274 * \return a new group with newly created nodes
5275 * \sa DoubleNodeGroup()
5277 //================================================================================
5279 SMESH::SMESH_Group_ptr
5280 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5281 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5282 throw (SALOME::SALOME_Exception)
5285 SMESH::SMESH_Group_var aNewGroup;
5287 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5288 return aNewGroup._retn();
5291 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5292 SMESH::long_array_var aModifiedElems;
5293 if ( !CORBA::is_nil( theModifiedElems ) )
5294 aModifiedElems = theModifiedElems->GetListOfID();
5296 aModifiedElems = new SMESH::long_array;
5297 aModifiedElems->length( 0 );
5300 TPythonDump pyDump; // suppress dump by the next line
5302 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5305 // Create group with newly created nodes
5306 SMESH::long_array_var anIds = GetLastCreatedNodes();
5307 if (anIds->length() > 0) {
5308 string anUnindexedName (theNodes->GetName());
5309 string aNewName = generateGroupName(anUnindexedName + "_double");
5310 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5311 aNewGroup->Add(anIds);
5312 pyDump << aNewGroup << " = ";
5316 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5317 << theModifiedElems << " )";
5319 return aNewGroup._retn();
5321 SMESH_CATCH( SMESH::throwCorbaException );
5325 //================================================================================
5327 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5328 This method provided for convenience works as DoubleNodes() described above.
5329 \param theNodes - list of groups of nodes to be doubled
5330 \param theModifiedElems - list of groups of elements to be updated.
5331 \return TRUE if operation has been completed successfully, FALSE otherwise
5332 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5334 //================================================================================
5336 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5337 const SMESH::ListOfGroups& theModifiedElems )
5338 throw (SALOME::SALOME_Exception)
5343 std::list< int > aNodes;
5345 for ( i = 0, n = theNodes.length(); i < n; i++ )
5347 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5348 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5350 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5351 for ( j = 0, m = aCurr->length(); j < m; j++ )
5352 aNodes.push_back( aCurr[ j ] );
5356 std::list< int > anElems;
5357 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5359 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5360 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5362 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5363 for ( j = 0, m = aCurr->length(); j < m; j++ )
5364 anElems.push_back( aCurr[ j ] );
5368 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5370 declareMeshModified( /*isReComputeSafe=*/false );
5372 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5376 SMESH_CATCH( SMESH::throwCorbaException );
5380 //================================================================================
5382 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5383 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5384 * \param theNodes - group of nodes to be doubled.
5385 * \param theModifiedElems - group of elements to be updated.
5386 * \return a new group with newly created nodes
5387 * \sa DoubleNodeGroups()
5389 //================================================================================
5391 SMESH::SMESH_Group_ptr
5392 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5393 const SMESH::ListOfGroups& theModifiedElems )
5394 throw (SALOME::SALOME_Exception)
5396 SMESH::SMESH_Group_var aNewGroup;
5398 TPythonDump pyDump; // suppress dump by the next line
5400 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5404 // Create group with newly created nodes
5405 SMESH::long_array_var anIds = GetLastCreatedNodes();
5406 if (anIds->length() > 0) {
5407 string anUnindexedName (theNodes[0]->GetName());
5408 string aNewName = generateGroupName(anUnindexedName + "_double");
5409 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5410 aNewGroup->Add(anIds);
5411 pyDump << aNewGroup << " = ";
5415 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5416 << theModifiedElems << " )";
5418 return aNewGroup._retn();
5422 //================================================================================
5424 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5425 \param theElems - the list of elements (edges or faces) to be replicated
5426 The nodes for duplication could be found from these elements
5427 \param theNodesNot - list of nodes to NOT replicate
5428 \param theAffectedElems - the list of elements (cells and edges) to which the
5429 replicated nodes should be associated to.
5430 \return TRUE if operation has been completed successfully, FALSE otherwise
5431 \sa DoubleNodeGroup(), DoubleNodeGroups()
5433 //================================================================================
5435 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5436 const SMESH::long_array& theNodesNot,
5437 const SMESH::long_array& theAffectedElems )
5438 throw (SALOME::SALOME_Exception)
5443 SMESHDS_Mesh* aMeshDS = getMeshDS();
5444 TIDSortedElemSet anElems, aNodes, anAffected;
5445 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5446 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5447 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5449 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5451 // Update Python script
5452 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5453 << theNodesNot << ", " << theAffectedElems << " )";
5455 declareMeshModified( /*isReComputeSafe=*/false );
5458 SMESH_CATCH( SMESH::throwCorbaException );
5462 //================================================================================
5464 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5465 \param theElems - the list of elements (edges or faces) to be replicated
5466 The nodes for duplication could be found from these elements
5467 \param theNodesNot - list of nodes to NOT replicate
5468 \param theShape - shape to detect affected elements (element which geometric center
5469 located on or inside shape).
5470 The replicated nodes should be associated to affected elements.
5471 \return TRUE if operation has been completed successfully, FALSE otherwise
5472 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5474 //================================================================================
5476 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5477 const SMESH::long_array& theNodesNot,
5478 GEOM::GEOM_Object_ptr theShape )
5479 throw (SALOME::SALOME_Exception)
5485 SMESHDS_Mesh* aMeshDS = getMeshDS();
5486 TIDSortedElemSet anElems, aNodes;
5487 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5488 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5490 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5491 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5493 // Update Python script
5494 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5495 << theNodesNot << ", " << theShape << " )";
5497 declareMeshModified( /*isReComputeSafe=*/false );
5500 SMESH_CATCH( SMESH::throwCorbaException );
5504 //================================================================================
5506 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5507 \param theElems - group of of elements (edges or faces) to be replicated
5508 \param theNodesNot - group of nodes not to replicated
5509 \param theAffectedElems - group of elements to which the replicated nodes
5510 should be associated to.
5511 \return TRUE if operation has been completed successfully, FALSE otherwise
5512 \sa DoubleNodes(), DoubleNodeGroups()
5514 //================================================================================
5517 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5518 SMESH::SMESH_GroupBase_ptr theNodesNot,
5519 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5520 throw (SALOME::SALOME_Exception)
5523 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5529 SMESHDS_Mesh* aMeshDS = getMeshDS();
5530 TIDSortedElemSet anElems, aNodes, anAffected;
5531 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5532 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5533 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5535 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5537 // Update Python script
5538 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5539 << theNodesNot << ", " << theAffectedElems << " )";
5541 declareMeshModified( /*isReComputeSafe=*/false );
5544 SMESH_CATCH( SMESH::throwCorbaException );
5548 //================================================================================
5550 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5551 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5552 * \param theElems - group of of elements (edges or faces) to be replicated
5553 * \param theNodesNot - group of nodes not to replicated
5554 * \param theAffectedElems - group of elements to which the replicated nodes
5555 * should be associated to.
5556 * \return a new group with newly created elements
5557 * \sa DoubleNodeElemGroup()
5559 //================================================================================
5561 SMESH::SMESH_Group_ptr
5562 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5563 SMESH::SMESH_GroupBase_ptr theNodesNot,
5564 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5565 throw (SALOME::SALOME_Exception)
5568 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5572 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5573 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5575 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5577 << theNodesNot << ", "
5578 << theAffectedElems << " )";
5580 return elemGroup._retn();
5583 //================================================================================
5585 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5586 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5587 * \param theElems - group of of elements (edges or faces) to be replicated
5588 * \param theNodesNot - group of nodes not to replicated
5589 * \param theAffectedElems - group of elements to which the replicated nodes
5590 * should be associated to.
5591 * \return a new group with newly created elements
5592 * \sa DoubleNodeElemGroup()
5594 //================================================================================
5596 SMESH::ListOfGroups*
5597 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5598 SMESH::SMESH_GroupBase_ptr theNodesNot,
5599 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5600 CORBA::Boolean theElemGroupNeeded,
5601 CORBA::Boolean theNodeGroupNeeded)
5602 throw (SALOME::SALOME_Exception)
5605 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5606 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5607 aTwoGroups->length( 2 );
5609 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5610 return aTwoGroups._retn();
5615 SMESHDS_Mesh* aMeshDS = getMeshDS();
5616 TIDSortedElemSet anElems, aNodes, anAffected;
5617 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5618 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5619 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5622 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5624 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5630 // Create group with newly created elements
5631 CORBA::String_var elemGroupName = theElems->GetName();
5632 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5633 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5635 SMESH::long_array_var anIds = GetLastCreatedElems();
5636 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5637 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5638 aNewElemGroup->Add(anIds);
5640 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5642 SMESH::long_array_var anIds = GetLastCreatedNodes();
5643 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5644 aNewNodeGroup->Add(anIds);
5648 // Update Python script
5651 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5652 else pyDump << aNewElemGroup << ", ";
5653 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5654 else pyDump << aNewNodeGroup << " ] = ";
5656 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5657 << theNodesNot << ", "
5658 << theAffectedElems << ", "
5659 << theElemGroupNeeded << ", "
5660 << theNodeGroupNeeded <<" )";
5662 aTwoGroups[0] = aNewElemGroup._retn();
5663 aTwoGroups[1] = aNewNodeGroup._retn();
5664 return aTwoGroups._retn();
5666 SMESH_CATCH( SMESH::throwCorbaException );
5670 //================================================================================
5672 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5673 \param theElems - group of of elements (edges or faces) to be replicated
5674 \param theNodesNot - group of nodes not to replicated
5675 \param theShape - shape to detect affected elements (element which geometric center
5676 located on or inside shape).
5677 The replicated nodes should be associated to affected elements.
5678 \return TRUE if operation has been completed successfully, FALSE otherwise
5679 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5681 //================================================================================
5684 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5685 SMESH::SMESH_GroupBase_ptr theNodesNot,
5686 GEOM::GEOM_Object_ptr theShape )
5687 throw (SALOME::SALOME_Exception)
5690 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5696 SMESHDS_Mesh* aMeshDS = getMeshDS();
5697 TIDSortedElemSet anElems, aNodes, anAffected;
5698 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5699 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5701 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5702 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5705 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5707 // Update Python script
5708 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5709 << theNodesNot << ", " << theShape << " )";
5712 SMESH_CATCH( SMESH::throwCorbaException );
5716 //================================================================================
5718 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5719 * \param [in] theGrpList - groups
5720 * \param [in] theMeshDS - mesh
5721 * \param [out] theElemSet - set of elements
5722 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5724 //================================================================================
5726 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5727 SMESHDS_Mesh* theMeshDS,
5728 TIDSortedElemSet& theElemSet,
5729 const bool theIsNodeGrp)
5731 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5733 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5734 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5735 : aGrp->GetType() != SMESH::NODE ) )
5737 SMESH::long_array_var anIDs = aGrp->GetIDs();
5738 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5743 //================================================================================
5745 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5746 This method provided for convenience works as DoubleNodes() described above.
5747 \param theElems - list of groups of elements (edges or faces) to be replicated
5748 \param theNodesNot - list of groups of nodes not to replicated
5749 \param theAffectedElems - group of elements to which the replicated nodes
5750 should be associated to.
5751 \return TRUE if operation has been completed successfully, FALSE otherwise
5752 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5754 //================================================================================
5757 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5758 const SMESH::ListOfGroups& theNodesNot,
5759 const SMESH::ListOfGroups& theAffectedElems)
5760 throw (SALOME::SALOME_Exception)
5766 SMESHDS_Mesh* aMeshDS = getMeshDS();
5767 TIDSortedElemSet anElems, aNodes, anAffected;
5768 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5769 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5770 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5772 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5774 // Update Python script
5775 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5776 << &theNodesNot << ", " << &theAffectedElems << " )";
5778 declareMeshModified( /*isReComputeSafe=*/false );
5781 SMESH_CATCH( SMESH::throwCorbaException );
5785 //================================================================================
5787 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5788 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5789 \param theElems - list of groups of elements (edges or faces) to be replicated
5790 \param theNodesNot - list of groups of nodes not to replicated
5791 \param theAffectedElems - group of elements to which the replicated nodes
5792 should be associated to.
5793 * \return a new group with newly created elements
5794 * \sa DoubleNodeElemGroups()
5796 //================================================================================
5798 SMESH::SMESH_Group_ptr
5799 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5800 const SMESH::ListOfGroups& theNodesNot,
5801 const SMESH::ListOfGroups& theAffectedElems)
5802 throw (SALOME::SALOME_Exception)
5805 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
5809 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5810 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5812 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
5814 << theNodesNot << ", "
5815 << theAffectedElems << " )";
5817 return elemGroup._retn();
5820 //================================================================================
5822 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5823 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5824 \param theElems - list of groups of elements (edges or faces) to be replicated
5825 \param theNodesNot - list of groups of nodes not to replicated
5826 \param theAffectedElems - group of elements to which the replicated nodes
5827 should be associated to.
5828 * \return a new group with newly created elements
5829 * \sa DoubleNodeElemGroups()
5831 //================================================================================
5833 SMESH::ListOfGroups*
5834 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
5835 const SMESH::ListOfGroups& theNodesNot,
5836 const SMESH::ListOfGroups& theAffectedElems,
5837 CORBA::Boolean theElemGroupNeeded,
5838 CORBA::Boolean theNodeGroupNeeded)
5839 throw (SALOME::SALOME_Exception)
5842 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5843 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5844 aTwoGroups->length( 2 );
5849 SMESHDS_Mesh* aMeshDS = getMeshDS();
5850 TIDSortedElemSet anElems, aNodes, anAffected;
5851 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5852 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5853 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5855 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5857 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5862 // Create group with newly created elements
5863 CORBA::String_var elemGroupName = theElems[0]->GetName();
5864 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5865 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5867 SMESH::long_array_var anIds = GetLastCreatedElems();
5868 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5869 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5870 aNewElemGroup->Add(anIds);
5872 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5874 SMESH::long_array_var anIds = GetLastCreatedNodes();
5875 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5876 aNewNodeGroup->Add(anIds);
5880 // Update Python script
5883 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5884 else pyDump << aNewElemGroup << ", ";
5885 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5886 else pyDump << aNewNodeGroup << " ] = ";
5888 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
5889 << &theNodesNot << ", "
5890 << &theAffectedElems << ", "
5891 << theElemGroupNeeded << ", "
5892 << theNodeGroupNeeded << " )";
5894 aTwoGroups[0] = aNewElemGroup._retn();
5895 aTwoGroups[1] = aNewNodeGroup._retn();
5896 return aTwoGroups._retn();
5898 SMESH_CATCH( SMESH::throwCorbaException );
5902 //================================================================================
5904 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5905 This method provided for convenience works as DoubleNodes() described above.
5906 \param theElems - list of groups of elements (edges or faces) to be replicated
5907 \param theNodesNot - list of groups of nodes not to replicated
5908 \param theShape - shape to detect affected elements (element which geometric center
5909 located on or inside shape).
5910 The replicated nodes should be associated to affected elements.
5911 \return TRUE if operation has been completed successfully, FALSE otherwise
5912 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5914 //================================================================================
5917 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5918 const SMESH::ListOfGroups& theNodesNot,
5919 GEOM::GEOM_Object_ptr theShape )
5920 throw (SALOME::SALOME_Exception)
5926 SMESHDS_Mesh* aMeshDS = getMeshDS();
5927 TIDSortedElemSet anElems, aNodes;
5928 listOfGroupToSet(theElems, aMeshDS, anElems,false );
5929 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5931 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5932 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5934 // Update Python script
5935 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5936 << &theNodesNot << ", " << theShape << " )";
5938 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5941 SMESH_CATCH( SMESH::throwCorbaException );
5945 //================================================================================
5947 \brief Identify the elements that will be affected by node duplication (actual
5948 duplication is not performed.
5949 This method is the first step of DoubleNodeElemGroupsInRegion.
5950 \param theElems - list of groups of elements (edges or faces) to be replicated
5951 \param theNodesNot - list of groups of nodes not to replicated
5952 \param theShape - shape to detect affected elements (element which geometric center
5953 located on or inside shape).
5954 The replicated nodes should be associated to affected elements.
5955 \return groups of affected elements
5956 \sa DoubleNodeElemGroupsInRegion()
5958 //================================================================================
5959 SMESH::ListOfGroups*
5960 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
5961 const SMESH::ListOfGroups& theNodesNot,
5962 GEOM::GEOM_Object_ptr theShape )
5963 throw (SALOME::SALOME_Exception)
5966 MESSAGE("AffectedElemGroupsInRegion");
5967 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
5968 bool isEdgeGroup = false;
5969 bool isFaceGroup = false;
5970 bool isVolumeGroup = false;
5971 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
5972 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
5973 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
5977 ::SMESH_MeshEditor aMeshEditor(myMesh);
5979 SMESHDS_Mesh* aMeshDS = getMeshDS();
5980 TIDSortedElemSet anElems, aNodes;
5981 listOfGroupToSet(theElems, aMeshDS, anElems, false);
5982 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
5984 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
5985 TIDSortedElemSet anAffected;
5986 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
5989 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5994 int lg = anAffected.size();
5995 MESSAGE("lg="<< lg);
5996 SMESH::long_array_var volumeIds = new SMESH::long_array;
5997 volumeIds->length(lg);
5998 SMESH::long_array_var faceIds = new SMESH::long_array;
5999 faceIds->length(lg);
6000 SMESH::long_array_var edgeIds = new SMESH::long_array;
6001 edgeIds->length(lg);
6006 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6007 for (; eIt != anAffected.end(); ++eIt)
6009 const SMDS_MeshElement* anElem = *eIt;
6012 int elemId = anElem->GetID();
6013 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6014 volumeIds[ivol++] = elemId;
6015 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6016 faceIds[iface++] = elemId;
6017 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6018 edgeIds[iedge++] = elemId;
6020 volumeIds->length(ivol);
6021 faceIds->length(iface);
6022 edgeIds->length(iedge);
6024 aNewVolumeGroup->Add(volumeIds);
6025 aNewFaceGroup->Add(faceIds);
6026 aNewEdgeGroup->Add(edgeIds);
6027 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6028 isFaceGroup = (aNewFaceGroup->Size() > 0);
6029 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6033 if (isEdgeGroup) nbGroups++;
6034 if (isFaceGroup) nbGroups++;
6035 if (isVolumeGroup) nbGroups++;
6036 aListOfGroups->length(nbGroups);
6039 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6040 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6041 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6043 // Update Python script
6046 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6047 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6048 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6050 pyDump << this << ".AffectedElemGroupsInRegion( "
6051 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6053 return aListOfGroups._retn();
6055 SMESH_CATCH( SMESH::throwCorbaException );
6059 //================================================================================
6061 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6062 The created 2D mesh elements based on nodes of free faces of boundary volumes
6063 \return TRUE if operation has been completed successfully, FALSE otherwise
6065 //================================================================================
6067 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6068 throw (SALOME::SALOME_Exception)
6073 bool aResult = getEditor().Make2DMeshFrom3D();
6075 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6077 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6080 SMESH_CATCH( SMESH::throwCorbaException );
6084 //================================================================================
6086 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6087 * The list of groups must contain at least two groups. The groups have to be disjoint:
6088 * no common element into two different groups.
6089 * The nodes of the internal faces at the boundaries of the groups are doubled.
6090 * Optionally, the internal faces are replaced by flat elements.
6091 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6092 * The flat elements are stored in groups of volumes.
6093 * These groups are named according to the position of the group in the list:
6094 * 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.
6095 * 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.
6096 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6097 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6098 * \param theDomains - list of groups of volumes
6099 * \param createJointElems - if TRUE, create the elements
6100 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6101 * the boundary between \a theDomains and the rest mesh
6102 * \return TRUE if operation has been completed successfully, FALSE otherwise
6104 //================================================================================
6107 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6108 CORBA::Boolean createJointElems,
6109 CORBA::Boolean onAllBoundaries )
6110 throw (SALOME::SALOME_Exception)
6117 SMESHDS_Mesh* aMeshDS = getMeshDS();
6119 // MESSAGE("theDomains.length = "<<theDomains.length());
6120 if ( theDomains.length() <= 1 && !onAllBoundaries )
6121 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6123 vector<TIDSortedElemSet> domains;
6124 domains.resize( theDomains.length() );
6126 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6128 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6129 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6131 // if ( aGrp->GetType() != SMESH::VOLUME )
6132 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6133 SMESH::long_array_var anIDs = aGrp->GetIDs();
6134 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6138 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6139 // TODO publish the groups of flat elements in study
6141 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6143 // Update Python script
6144 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6145 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6147 SMESH_CATCH( SMESH::throwCorbaException );
6149 myMesh_i->CreateGroupServants(); // publish created groups if any
6154 //================================================================================
6156 * \brief Double nodes on some external faces and create flat elements.
6157 * Flat elements are mainly used by some types of mechanic calculations.
6159 * Each group of the list must be constituted of faces.
6160 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6161 * @param theGroupsOfFaces - list of groups of faces
6162 * @return TRUE if operation has been completed successfully, FALSE otherwise
6164 //================================================================================
6167 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6168 throw (SALOME::SALOME_Exception)
6173 SMESHDS_Mesh* aMeshDS = getMeshDS();
6175 vector<TIDSortedElemSet> faceGroups;
6178 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6180 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6181 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6183 TIDSortedElemSet faceGroup;
6185 faceGroups.push_back(faceGroup);
6186 SMESH::long_array_var anIDs = aGrp->GetIDs();
6187 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6191 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6192 // TODO publish the groups of flat elements in study
6194 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6196 // Update Python script
6197 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6200 SMESH_CATCH( SMESH::throwCorbaException );
6204 //================================================================================
6206 * \brief Identify all the elements around a geom shape, get the faces delimiting
6209 * Build groups of volume to remove, groups of faces to replace on the skin of the
6210 * object, groups of faces to remove inside the object, (idem edges).
6211 * Build ordered list of nodes at the border of each group of faces to replace
6212 * (to be used to build a geom subshape).
6214 //================================================================================
6216 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6217 GEOM::GEOM_Object_ptr theShape,
6218 const char* groupName,
6219 const SMESH::double_array& theNodesCoords,
6220 SMESH::array_of_long_array_out GroupsOfNodes)
6221 throw (SALOME::SALOME_Exception)
6226 std::vector<std::vector<int> > aListOfListOfNodes;
6227 ::SMESH_MeshEditor aMeshEditor( myMesh );
6229 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6230 if ( !theNodeSearcher )
6231 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6233 vector<double> nodesCoords;
6234 for (int i = 0; i < theNodesCoords.length(); i++)
6236 nodesCoords.push_back( theNodesCoords[i] );
6239 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6240 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6241 nodesCoords, aListOfListOfNodes);
6243 GroupsOfNodes = new SMESH::array_of_long_array;
6244 GroupsOfNodes->length( aListOfListOfNodes.size() );
6245 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6246 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6248 vector<int>& aListOfNodes = *llIt;
6249 vector<int>::iterator lIt = aListOfNodes.begin();;
6250 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6251 aGroup.length( aListOfNodes.size() );
6252 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6253 aGroup[ j ] = (*lIt);
6255 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6258 << ", '" << groupName << "', "
6259 << theNodesCoords << " )";
6261 SMESH_CATCH( SMESH::throwCorbaException );
6264 // issue 20749 ===================================================================
6266 * \brief Creates missing boundary elements
6267 * \param elements - elements whose boundary is to be checked
6268 * \param dimension - defines type of boundary elements to create
6269 * \param groupName - a name of group to store created boundary elements in,
6270 * "" means not to create the group
6271 * \param meshName - a name of new mesh to store created boundary elements in,
6272 * "" means not to create the new mesh
6273 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6274 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6275 * boundary elements will be copied into the new mesh
6276 * \param group - returns the create group, if any
6277 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6279 // ================================================================================
6281 SMESH::SMESH_Mesh_ptr
6282 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6283 SMESH::Bnd_Dimension dim,
6284 const char* groupName,
6285 const char* meshName,
6286 CORBA::Boolean toCopyElements,
6287 CORBA::Boolean toCopyExistingBondary,
6288 SMESH::SMESH_Group_out group)
6289 throw (SALOME::SALOME_Exception)
6294 if ( dim > SMESH::BND_1DFROM2D )
6295 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6297 SMESHDS_Mesh* aMeshDS = getMeshDS();
6299 SMESH::SMESH_Mesh_var mesh_var;
6300 SMESH::SMESH_Group_var group_var;
6304 TIDSortedElemSet elements;
6305 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6306 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6310 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6311 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6313 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6315 // group of new boundary elements
6316 SMESH_Group* smesh_group = 0;
6317 if ( strlen(groupName) )
6319 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6320 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6321 smesh_group = group_i->GetSmeshGroup();
6325 getEditor().MakeBoundaryMesh( elements,
6326 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6330 toCopyExistingBondary);
6333 smesh_mesh->GetMeshDS()->Modified();
6336 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6338 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6339 if ( mesh_var->_is_nil() )
6340 pyDump << myMesh_i->_this() << ", ";
6342 pyDump << mesh_var << ", ";
6343 if ( group_var->_is_nil() )
6344 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6346 pyDump << group_var << " = ";
6347 pyDump << this << ".MakeBoundaryMesh( "
6349 << "SMESH." << dimName[int(dim)] << ", "
6350 << "'" << groupName << "', "
6351 << "'" << meshName<< "', "
6352 << toCopyElements << ", "
6353 << toCopyExistingBondary << ")";
6355 group = group_var._retn();
6356 return mesh_var._retn();
6358 SMESH_CATCH( SMESH::throwCorbaException );
6359 return SMESH::SMESH_Mesh::_nil();
6362 //================================================================================
6364 * \brief Creates missing boundary elements
6365 * \param dimension - defines type of boundary elements to create
6366 * \param groupName - a name of group to store all boundary elements in,
6367 * "" means not to create the group
6368 * \param meshName - a name of a new mesh, which is a copy of the initial
6369 * mesh + created boundary elements; "" means not to create the new mesh
6370 * \param toCopyAll - if true, the whole initial mesh will be copied into
6371 * the new mesh else only boundary elements will be copied into the new mesh
6372 * \param groups - optional groups of elements to make boundary around
6373 * \param mesh - returns the mesh where elements were added to
6374 * \param group - returns the created group, if any
6375 * \retval long - number of added boundary elements
6377 //================================================================================
6379 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6380 const char* groupName,
6381 const char* meshName,
6382 CORBA::Boolean toCopyAll,
6383 const SMESH::ListOfIDSources& groups,
6384 SMESH::SMESH_Mesh_out mesh,
6385 SMESH::SMESH_Group_out group)
6386 throw (SALOME::SALOME_Exception)
6391 if ( dim > SMESH::BND_1DFROM2D )
6392 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6394 // separate groups belonging to this and other mesh
6395 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6396 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6397 groupsOfThisMesh->length( groups.length() );
6398 groupsOfOtherMesh->length( groups.length() );
6399 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6400 for ( int i = 0; i < groups.length(); ++i )
6402 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6403 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6404 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6406 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6407 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6408 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6410 groupsOfThisMesh->length( nbGroups );
6411 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6416 if ( nbGroupsOfOtherMesh > 0 )
6418 // process groups belonging to another mesh
6419 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6420 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6421 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6422 groupsOfOtherMesh, mesh, group );
6425 SMESH::SMESH_Mesh_var mesh_var;
6426 SMESH::SMESH_Group_var group_var;
6429 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6430 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6434 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6436 /*toCopyGroups=*/false,
6437 /*toKeepIDs=*/true);
6439 mesh_var = makeMesh(meshName);
6441 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6442 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6445 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6446 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6448 // group of boundary elements
6449 SMESH_Group* smesh_group = 0;
6450 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6451 if ( strlen(groupName) )
6453 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6454 group_var = mesh_i->CreateGroup( groupType, groupName );
6455 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6456 smesh_group = group_i->GetSmeshGroup();
6459 TIDSortedElemSet elements;
6461 if ( groups.length() > 0 )
6463 for ( int i = 0; i < nbGroups; ++i )
6466 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6468 SMESH::Bnd_Dimension bdim =
6469 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6470 nbAdded += getEditor().MakeBoundaryMesh( elements,
6471 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6474 /*toCopyElements=*/false,
6475 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6476 /*toAddExistingBondary=*/true,
6477 /*aroundElements=*/true);
6483 nbAdded += getEditor().MakeBoundaryMesh( elements,
6484 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6487 /*toCopyElements=*/false,
6488 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6489 /*toAddExistingBondary=*/true);
6491 tgtMesh->GetMeshDS()->Modified();
6493 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6495 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6496 pyDump << "nbAdded, ";
6497 if ( mesh_var->_is_nil() )
6498 pyDump << myMesh_i->_this() << ", ";
6500 pyDump << mesh_var << ", ";
6501 if ( group_var->_is_nil() )
6502 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6504 pyDump << group_var << " = ";
6505 pyDump << this << ".MakeBoundaryElements( "
6506 << "SMESH." << dimName[int(dim)] << ", "
6507 << "'" << groupName << "', "
6508 << "'" << meshName<< "', "
6509 << toCopyAll << ", "
6512 mesh = mesh_var._retn();
6513 group = group_var._retn();
6516 SMESH_CATCH( SMESH::throwCorbaException );