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 //================================================================================
2143 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2144 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2145 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2146 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2147 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2148 * will be split in order to keep the mesh conformal.
2149 * \param elems - elements to split
2151 //================================================================================
2153 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2154 throw (SALOME::SALOME_Exception)
2159 TIDSortedElemSet elemSet;
2160 for ( size_t i = 0; i < theElems.length(); ++i )
2162 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2163 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2164 if ( mesh->GetId() != myMesh_i->GetId() )
2165 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2167 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2169 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2171 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2173 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2174 << theElems << " )";
2176 SMESH_CATCH( SMESH::throwCorbaException );
2179 //=======================================================================
2182 //=======================================================================
2185 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2186 const SMESH::long_array & IDsOfFixedNodes,
2187 CORBA::Long MaxNbOfIterations,
2188 CORBA::Double MaxAspectRatio,
2189 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2190 throw (SALOME::SALOME_Exception)
2192 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2193 MaxAspectRatio, Method, false );
2197 //=======================================================================
2198 //function : SmoothParametric
2200 //=======================================================================
2203 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2204 const SMESH::long_array & IDsOfFixedNodes,
2205 CORBA::Long MaxNbOfIterations,
2206 CORBA::Double MaxAspectRatio,
2207 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2208 throw (SALOME::SALOME_Exception)
2210 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2211 MaxAspectRatio, Method, true );
2215 //=======================================================================
2216 //function : SmoothObject
2218 //=======================================================================
2221 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2222 const SMESH::long_array & IDsOfFixedNodes,
2223 CORBA::Long MaxNbOfIterations,
2224 CORBA::Double MaxAspectRatio,
2225 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2226 throw (SALOME::SALOME_Exception)
2228 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2229 MaxAspectRatio, Method, false);
2233 //=======================================================================
2234 //function : SmoothParametricObject
2236 //=======================================================================
2239 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2240 const SMESH::long_array & IDsOfFixedNodes,
2241 CORBA::Long MaxNbOfIterations,
2242 CORBA::Double MaxAspectRatio,
2243 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2244 throw (SALOME::SALOME_Exception)
2246 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2247 MaxAspectRatio, Method, true);
2251 //=============================================================================
2255 //=============================================================================
2258 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2259 const SMESH::long_array & IDsOfFixedNodes,
2260 CORBA::Long MaxNbOfIterations,
2261 CORBA::Double MaxAspectRatio,
2262 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2264 throw (SALOME::SALOME_Exception)
2269 SMESHDS_Mesh* aMesh = getMeshDS();
2271 TIDSortedElemSet elements;
2272 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2274 set<const SMDS_MeshNode*> fixedNodes;
2275 for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
2276 CORBA::Long index = IDsOfFixedNodes[i];
2277 const SMDS_MeshNode * node = aMesh->FindNode(index);
2279 fixedNodes.insert( node );
2281 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2282 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2283 method = ::SMESH_MeshEditor::CENTROIDAL;
2285 getEditor().Smooth(elements, fixedNodes, method,
2286 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2288 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2290 // Update Python script
2291 TPythonDump() << "isDone = " << this << "."
2292 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2293 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2294 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2295 << "SMESH.SMESH_MeshEditor."
2296 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2297 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2301 SMESH_CATCH( SMESH::throwCorbaException );
2305 //=============================================================================
2309 //=============================================================================
2312 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2313 const SMESH::long_array & IDsOfFixedNodes,
2314 CORBA::Long MaxNbOfIterations,
2315 CORBA::Double MaxAspectRatio,
2316 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2318 throw (SALOME::SALOME_Exception)
2323 TPythonDump aTPythonDump; // suppress dump in smooth()
2325 prepareIdSource( theObject );
2326 SMESH::long_array_var anElementsId = theObject->GetIDs();
2327 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2328 MaxAspectRatio, Method, IsParametric);
2330 // Update Python script
2331 aTPythonDump << "isDone = " << this << "."
2332 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2333 << theObject << ", " << IDsOfFixedNodes << ", "
2334 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2335 << "SMESH.SMESH_MeshEditor."
2336 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2337 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2341 SMESH_CATCH( SMESH::throwCorbaException );
2345 //=============================================================================
2349 //=============================================================================
2351 void SMESH_MeshEditor_i::RenumberNodes()
2352 throw (SALOME::SALOME_Exception)
2355 // Update Python script
2356 TPythonDump() << this << ".RenumberNodes()";
2358 getMeshDS()->Renumber( true );
2360 SMESH_CATCH( SMESH::throwCorbaException );
2363 //=============================================================================
2367 //=============================================================================
2369 void SMESH_MeshEditor_i::RenumberElements()
2370 throw (SALOME::SALOME_Exception)
2373 // Update Python script
2374 TPythonDump() << this << ".RenumberElements()";
2376 getMeshDS()->Renumber( false );
2378 SMESH_CATCH( SMESH::throwCorbaException );
2381 //=======================================================================
2383 * \brief Return groups by their IDs
2385 //=======================================================================
2387 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2388 throw (SALOME::SALOME_Exception)
2393 myMesh_i->CreateGroupServants();
2394 return myMesh_i->GetGroups( *groupIDs );
2396 SMESH_CATCH( SMESH::throwCorbaException );
2400 //=======================================================================
2401 //function : RotationSweepObjects
2403 //=======================================================================
2405 SMESH::ListOfGroups*
2406 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2407 const SMESH::ListOfIDSources & theEdges,
2408 const SMESH::ListOfIDSources & theFaces,
2409 const SMESH::AxisStruct & theAxis,
2410 CORBA::Double theAngleInRadians,
2411 CORBA::Long theNbOfSteps,
2412 CORBA::Double theTolerance,
2413 const bool theMakeGroups)
2414 throw (SALOME::SALOME_Exception)
2419 TIDSortedElemSet elemsNodes[2];
2420 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2421 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2422 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2424 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2425 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2426 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2427 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2429 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2430 bool makeWalls=true;
2431 if ( myIsPreviewMode )
2433 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2434 TPreviewMesh * tmpMesh = getPreviewMesh();
2435 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2436 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2437 workElements = & copyElements[0];
2438 //makeWalls = false; -- faces are needed for preview
2441 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2443 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2444 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2446 ::SMESH_MeshEditor::PGroupIDs groupIds =
2447 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2448 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2450 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2452 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2454 if ( !myIsPreviewMode )
2456 dumpGroupsList( aPythonDump, aGroups );
2457 aPythonDump << this<< ".RotationSweepObjects( "
2462 << TVar( theAngleInRadians ) << ", "
2463 << TVar( theNbOfSteps ) << ", "
2464 << TVar( theTolerance ) << ", "
2465 << theMakeGroups << " )";
2469 getPreviewMesh()->Remove( SMDSAbs_Volume );
2472 return aGroups ? aGroups : new SMESH::ListOfGroups;
2474 SMESH_CATCH( SMESH::throwCorbaException );
2478 namespace MeshEditor_I
2481 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2483 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2485 bool myIsExtrusionByNormal;
2487 static int makeFlags( CORBA::Boolean MakeGroups,
2488 CORBA::Boolean ByAverageNormal = false,
2489 CORBA::Boolean UseInputElemsOnly = false,
2490 CORBA::Long Flags = 0,
2491 CORBA::Boolean MakeBoundary = true )
2493 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2494 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2495 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2496 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2500 ExtrusionParams(const SMESH::DirStruct & theDir,
2501 CORBA::Long theNbOfSteps,
2502 CORBA::Boolean theMakeGroups):
2503 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2507 makeFlags( theMakeGroups )),
2508 myIsExtrusionByNormal( false )
2512 ExtrusionParams(const SMESH::DirStruct & theDir,
2513 CORBA::Long theNbOfSteps,
2514 CORBA::Boolean theMakeGroups,
2515 CORBA::Long theExtrFlags,
2516 CORBA::Double theSewTolerance):
2517 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2521 makeFlags( theMakeGroups, false, false,
2522 theExtrFlags, false ),
2524 myIsExtrusionByNormal( false )
2527 // params for extrusion by normal
2528 ExtrusionParams(CORBA::Double theStepSize,
2529 CORBA::Long theNbOfSteps,
2530 CORBA::Short theDim,
2531 CORBA::Boolean theByAverageNormal,
2532 CORBA::Boolean theUseInputElemsOnly,
2533 CORBA::Boolean theMakeGroups ):
2534 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2536 makeFlags( theMakeGroups,
2537 theByAverageNormal, theUseInputElemsOnly ),
2539 myIsExtrusionByNormal( true )
2545 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2550 //=======================================================================
2552 * \brief Generate dim+1 elements by extrusion of elements along vector
2553 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2554 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2555 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2556 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2557 * \param [in] nbOfSteps - number of elements to generate from one element
2558 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2559 * corresponding to groups the input elements included in.
2560 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2562 //=======================================================================
2564 SMESH::ListOfGroups*
2565 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2566 const SMESH::ListOfIDSources & theEdges,
2567 const SMESH::ListOfIDSources & theFaces,
2568 const SMESH::DirStruct & theStepVector,
2569 CORBA::Long theNbOfSteps,
2570 CORBA::Boolean theToMakeGroups)
2571 throw (SALOME::SALOME_Exception)
2576 ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
2578 TIDSortedElemSet elemsNodes[2];
2579 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2580 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2581 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2583 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2584 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2585 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2586 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2588 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2589 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2590 if ( myIsPreviewMode )
2592 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2593 // previewType = SMDSAbs_Edge;
2595 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2596 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2597 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2598 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2599 workElements = & copyElements[0];
2601 params.SetNoGroups();
2603 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2605 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2606 ::SMESH_MeshEditor::PGroupIDs groupIds =
2607 getEditor().ExtrusionSweep( workElements, params, aHistory );
2609 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2611 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2613 if ( !myIsPreviewMode )
2615 dumpGroupsList( aPythonDump, aGroups );
2616 aPythonDump << this<< ".ExtrusionSweepObjects( "
2620 << theStepVector << ", "
2621 << TVar( theNbOfSteps ) << ", "
2622 << theToMakeGroups << " )";
2626 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2629 return aGroups ? aGroups : new SMESH::ListOfGroups;
2631 SMESH_CATCH( SMESH::throwCorbaException );
2635 //=======================================================================
2636 //function : ExtrusionByNormal
2638 //=======================================================================
2640 SMESH::ListOfGroups*
2641 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2642 CORBA::Double stepSize,
2643 CORBA::Long nbOfSteps,
2644 CORBA::Boolean byAverageNormal,
2645 CORBA::Boolean useInputElemsOnly,
2646 CORBA::Boolean makeGroups,
2648 throw (SALOME::SALOME_Exception)
2653 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2655 ExtrusionParams params( stepSize, nbOfSteps, dim,
2656 byAverageNormal, useInputElemsOnly, makeGroups );
2658 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2659 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2661 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2662 if (( elemTypes->length() == 1 ) &&
2663 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2664 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2667 TIDSortedElemSet elemsNodes[2];
2668 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2669 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2671 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2672 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2673 if ( myIsPreviewMode )
2675 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2676 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2677 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2678 workElements = & copyElements[0];
2680 params.SetNoGroups();
2683 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2684 ::SMESH_MeshEditor::PGroupIDs groupIds =
2685 getEditor().ExtrusionSweep( workElements, params, aHistory );
2687 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2689 if (!myIsPreviewMode) {
2690 dumpGroupsList(aPythonDump, aGroups);
2691 aPythonDump << this << ".ExtrusionByNormal( " << objects
2692 << ", " << TVar( stepSize )
2693 << ", " << TVar( nbOfSteps )
2694 << ", " << byAverageNormal
2695 << ", " << useInputElemsOnly
2696 << ", " << makeGroups
2702 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2705 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2707 return aGroups ? aGroups : new SMESH::ListOfGroups;
2709 SMESH_CATCH( SMESH::throwCorbaException );
2713 //=======================================================================
2714 //function : AdvancedExtrusion
2716 //=======================================================================
2718 SMESH::ListOfGroups*
2719 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2720 const SMESH::DirStruct & theStepVector,
2721 CORBA::Long theNbOfSteps,
2722 CORBA::Long theExtrFlags,
2723 CORBA::Double theSewTolerance,
2724 CORBA::Boolean theMakeGroups)
2725 throw (SALOME::SALOME_Exception)
2730 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2732 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2733 theExtrFlags, theSewTolerance );
2735 TIDSortedElemSet elemsNodes[2];
2736 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2738 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2739 ::SMESH_MeshEditor::PGroupIDs groupIds =
2740 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2742 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2744 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2746 if ( !myIsPreviewMode ) {
2747 dumpGroupsList(aPythonDump, aGroups);
2748 aPythonDump << this << ".AdvancedExtrusion( "
2749 << theIDsOfElements << ", "
2750 << theStepVector << ", "
2751 << theNbOfSteps << ", "
2752 << theExtrFlags << ", "
2753 << theSewTolerance << ", "
2754 << theMakeGroups << " )";
2758 getPreviewMesh()->Remove( SMDSAbs_Volume );
2761 return aGroups ? aGroups : new SMESH::ListOfGroups;
2763 SMESH_CATCH( SMESH::throwCorbaException );
2767 //================================================================================
2769 * \brief Convert extrusion error to IDL enum
2771 //================================================================================
2775 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2777 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2781 RETCASE( EXTR_NO_ELEMENTS );
2782 RETCASE( EXTR_PATH_NOT_EDGE );
2783 RETCASE( EXTR_BAD_PATH_SHAPE );
2784 RETCASE( EXTR_BAD_STARTING_NODE );
2785 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2786 RETCASE( EXTR_CANT_GET_TANGENT );
2788 return SMESH::SMESH_MeshEditor::EXTR_OK;
2792 //=======================================================================
2793 //function : extrusionAlongPath
2795 //=======================================================================
2796 SMESH::ListOfGroups*
2797 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2798 const SMESH::ListOfIDSources & theEdges,
2799 const SMESH::ListOfIDSources & theFaces,
2800 SMESH::SMESH_IDSource_ptr thePathMesh,
2801 GEOM::GEOM_Object_ptr thePathShape,
2802 CORBA::Long theNodeStart,
2803 CORBA::Boolean theHasAngles,
2804 const SMESH::double_array & theAngles,
2805 CORBA::Boolean theLinearVariation,
2806 CORBA::Boolean theHasRefPoint,
2807 const SMESH::PointStruct & theRefPoint,
2809 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2810 throw (SALOME::SALOME_Exception)
2815 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2817 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2818 if ( thePathMesh->_is_nil() )
2819 return aGroups._retn();
2822 SMESH_subMesh* aSubMesh = 0;
2823 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2824 if ( thePathShape->_is_nil() )
2826 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2827 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2829 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2830 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2831 if ( !aMeshImp ) return aGroups._retn();
2832 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2833 if ( !aSubMesh ) return aGroups._retn();
2835 else if ( !aMeshImp ||
2836 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2838 return aGroups._retn();
2843 if ( !aMeshImp ) return aGroups._retn();
2844 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2845 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2846 if ( !aSubMesh || !aSubMesh->GetSubMeshDS() )
2847 return aGroups._retn();
2850 SMDS_MeshNode* nodeStart =
2851 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2853 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2854 return aGroups._retn();
2857 TIDSortedElemSet elemsNodes[2];
2858 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2859 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2860 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2862 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2863 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2864 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2865 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2867 list<double> angles;
2868 for (int i = 0; i < theAngles.length(); i++) {
2869 angles.push_back( theAngles[i] );
2872 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2874 int nbOldGroups = myMesh->NbGroup();
2876 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2877 if ( myIsPreviewMode )
2879 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2880 TPreviewMesh * tmpMesh = getPreviewMesh();
2881 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2882 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2883 workElements = & copyElements[0];
2884 theMakeGroups = false;
2887 ::SMESH_MeshEditor::Extrusion_Error error;
2889 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2890 theHasAngles, angles, theLinearVariation,
2891 theHasRefPoint, refPnt, theMakeGroups );
2893 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2894 theHasAngles, angles, theLinearVariation,
2895 theHasRefPoint, refPnt, theMakeGroups );
2897 declareMeshModified( /*isReComputeSafe=*/true );
2898 theError = convExtrError( error );
2900 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2901 if ( theMakeGroups ) {
2902 list<int> groupIDs = myMesh->GetGroupIds();
2903 list<int>::iterator newBegin = groupIDs.begin();
2904 std::advance( newBegin, nbOldGroups ); // skip old groups
2905 groupIDs.erase( groupIDs.begin(), newBegin );
2906 aGroups = getGroups( & groupIDs );
2907 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2910 if ( !myIsPreviewMode ) {
2911 aPythonDump << "(" << aGroups << ", error) = "
2912 << this << ".ExtrusionAlongPathObjects( "
2916 << thePathMesh << ", "
2917 << thePathShape << ", "
2918 << theNodeStart << ", "
2919 << theHasAngles << ", "
2920 << theAngles << ", "
2921 << theLinearVariation << ", "
2922 << theHasRefPoint << ", "
2923 << "SMESH.PointStruct( "
2924 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2925 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2926 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2927 << theMakeGroups << " )";
2931 getPreviewMesh()->Remove( SMDSAbs_Volume );
2934 return aGroups._retn();
2936 SMESH_CATCH( SMESH::throwCorbaException );
2940 //================================================================================
2942 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2943 * of given angles along path steps
2944 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2945 * which proceeds the extrusion
2946 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2947 * is used to define the sub-mesh for the path
2949 //================================================================================
2951 SMESH::double_array*
2952 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2953 GEOM::GEOM_Object_ptr thePathShape,
2954 const SMESH::double_array & theAngles)
2956 SMESH::double_array_var aResult = new SMESH::double_array();
2957 int nbAngles = theAngles.length();
2958 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2960 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2961 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2962 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2963 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2964 return aResult._retn();
2965 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2966 if ( nbSteps == nbAngles )
2968 aResult.inout() = theAngles;
2972 aResult->length( nbSteps );
2973 double rAn2St = double( nbAngles ) / double( nbSteps );
2974 double angPrev = 0, angle;
2975 for ( int iSt = 0; iSt < nbSteps; ++iSt )
2977 double angCur = rAn2St * ( iSt+1 );
2978 double angCurFloor = floor( angCur );
2979 double angPrevFloor = floor( angPrev );
2980 if ( angPrevFloor == angCurFloor )
2981 angle = rAn2St * theAngles[ int( angCurFloor ) ];
2984 int iP = int( angPrevFloor );
2985 double angPrevCeil = ceil(angPrev);
2986 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2988 int iC = int( angCurFloor );
2989 if ( iC < nbAngles )
2990 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2992 iP = int( angPrevCeil );
2994 angle += theAngles[ iC ];
2996 aResult[ iSt ] = angle;
3001 // Update Python script
3002 TPythonDump() << "rotAngles = " << theAngles;
3003 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3004 << thePathMesh << ", "
3005 << thePathShape << ", "
3008 return aResult._retn();
3011 //=======================================================================
3014 //=======================================================================
3016 SMESH::ListOfGroups*
3017 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3018 const SMESH::AxisStruct & theAxis,
3019 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3020 CORBA::Boolean theCopy,
3022 ::SMESH_Mesh* theTargetMesh)
3023 throw (SALOME::SALOME_Exception)
3028 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3029 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3031 if ( theTargetMesh )
3035 switch ( theMirrorType ) {
3036 case SMESH::SMESH_MeshEditor::POINT:
3037 aTrsf.SetMirror( P );
3039 case SMESH::SMESH_MeshEditor::AXIS:
3040 aTrsf.SetMirror( gp_Ax1( P, V ));
3043 aTrsf.SetMirror( gp_Ax2( P, V ));
3046 TIDSortedElemSet copyElements;
3047 TIDSortedElemSet* workElements = & theElements;
3049 if ( myIsPreviewMode )
3051 TPreviewMesh * tmpMesh = getPreviewMesh();
3052 tmpMesh->Copy( theElements, copyElements);
3053 if ( !theCopy && !theTargetMesh )
3055 TIDSortedElemSet elemsAround, elemsAroundCopy;
3056 getElementsAround( theElements, getMeshDS(), elemsAround );
3057 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3059 workElements = & copyElements;
3060 theMakeGroups = false;
3063 ::SMESH_MeshEditor::PGroupIDs groupIds =
3064 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3066 if ( theCopy && !myIsPreviewMode)
3068 if ( theTargetMesh )
3070 theTargetMesh->GetMeshDS()->Modified();
3074 declareMeshModified( /*isReComputeSafe=*/false );
3077 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3079 SMESH_CATCH( SMESH::throwCorbaException );
3083 //=======================================================================
3086 //=======================================================================
3088 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3089 const SMESH::AxisStruct & theAxis,
3090 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3091 CORBA::Boolean theCopy)
3092 throw (SALOME::SALOME_Exception)
3094 if ( !myIsPreviewMode ) {
3095 TPythonDump() << this << ".Mirror( "
3096 << theIDsOfElements << ", "
3098 << mirrorTypeName(theMirrorType) << ", "
3101 if ( theIDsOfElements.length() > 0 )
3103 TIDSortedElemSet elements;
3104 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3105 mirror(elements, theAxis, theMirrorType, theCopy, false);
3110 //=======================================================================
3111 //function : MirrorObject
3113 //=======================================================================
3115 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3116 const SMESH::AxisStruct & theAxis,
3117 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3118 CORBA::Boolean theCopy)
3119 throw (SALOME::SALOME_Exception)
3121 if ( !myIsPreviewMode ) {
3122 TPythonDump() << this << ".MirrorObject( "
3123 << theObject << ", "
3125 << mirrorTypeName(theMirrorType) << ", "
3128 TIDSortedElemSet elements;
3130 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3132 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3133 mirror(elements, theAxis, theMirrorType, theCopy, false);
3136 //=======================================================================
3137 //function : MirrorMakeGroups
3139 //=======================================================================
3141 SMESH::ListOfGroups*
3142 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3143 const SMESH::AxisStruct& theMirror,
3144 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3145 throw (SALOME::SALOME_Exception)
3147 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3149 SMESH::ListOfGroups * aGroups = 0;
3150 if ( theIDsOfElements.length() > 0 )
3152 TIDSortedElemSet elements;
3153 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3154 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3156 if (!myIsPreviewMode) {
3157 dumpGroupsList(aPythonDump, aGroups);
3158 aPythonDump << this << ".MirrorMakeGroups( "
3159 << theIDsOfElements << ", "
3160 << theMirror << ", "
3161 << mirrorTypeName(theMirrorType) << " )";
3166 //=======================================================================
3167 //function : MirrorObjectMakeGroups
3169 //=======================================================================
3171 SMESH::ListOfGroups*
3172 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3173 const SMESH::AxisStruct& theMirror,
3174 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3175 throw (SALOME::SALOME_Exception)
3177 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3179 SMESH::ListOfGroups * aGroups = 0;
3180 TIDSortedElemSet elements;
3181 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3182 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3184 if (!myIsPreviewMode)
3186 dumpGroupsList(aPythonDump,aGroups);
3187 aPythonDump << this << ".MirrorObjectMakeGroups( "
3188 << theObject << ", "
3189 << theMirror << ", "
3190 << mirrorTypeName(theMirrorType) << " )";
3195 //=======================================================================
3196 //function : MirrorMakeMesh
3198 //=======================================================================
3200 SMESH::SMESH_Mesh_ptr
3201 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3202 const SMESH::AxisStruct& theMirror,
3203 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3204 CORBA::Boolean theCopyGroups,
3205 const char* theMeshName)
3206 throw (SALOME::SALOME_Exception)
3208 SMESH_Mesh_i* mesh_i;
3209 SMESH::SMESH_Mesh_var mesh;
3210 { // open new scope to dump "MakeMesh" command
3211 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3213 TPythonDump pydump; // to prevent dump at mesh creation
3215 mesh = makeMesh( theMeshName );
3216 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3217 if (mesh_i && theIDsOfElements.length() > 0 )
3219 TIDSortedElemSet elements;
3220 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3221 mirror(elements, theMirror, theMirrorType,
3222 false, theCopyGroups, & mesh_i->GetImpl());
3223 mesh_i->CreateGroupServants();
3226 if (!myIsPreviewMode) {
3227 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3228 << theIDsOfElements << ", "
3229 << theMirror << ", "
3230 << mirrorTypeName(theMirrorType) << ", "
3231 << theCopyGroups << ", '"
3232 << theMeshName << "' )";
3237 if (!myIsPreviewMode && mesh_i)
3238 mesh_i->GetGroups();
3240 return mesh._retn();
3243 //=======================================================================
3244 //function : MirrorObjectMakeMesh
3246 //=======================================================================
3248 SMESH::SMESH_Mesh_ptr
3249 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3250 const SMESH::AxisStruct& theMirror,
3251 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3252 CORBA::Boolean theCopyGroups,
3253 const char* theMeshName)
3254 throw (SALOME::SALOME_Exception)
3256 SMESH_Mesh_i* mesh_i;
3257 SMESH::SMESH_Mesh_var mesh;
3258 { // open new scope to dump "MakeMesh" command
3259 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3261 TPythonDump pydump; // to prevent dump at mesh creation
3263 mesh = makeMesh( theMeshName );
3264 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3265 TIDSortedElemSet elements;
3267 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3269 mirror(elements, theMirror, theMirrorType,
3270 false, theCopyGroups, & mesh_i->GetImpl());
3271 mesh_i->CreateGroupServants();
3273 if (!myIsPreviewMode) {
3274 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3275 << theObject << ", "
3276 << theMirror << ", "
3277 << mirrorTypeName(theMirrorType) << ", "
3278 << theCopyGroups << ", '"
3279 << theMeshName << "' )";
3284 if (!myIsPreviewMode && mesh_i)
3285 mesh_i->GetGroups();
3287 return mesh._retn();
3290 //=======================================================================
3291 //function : translate
3293 //=======================================================================
3295 SMESH::ListOfGroups*
3296 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3297 const SMESH::DirStruct & theVector,
3298 CORBA::Boolean theCopy,
3300 ::SMESH_Mesh* theTargetMesh)
3301 throw (SALOME::SALOME_Exception)
3306 if ( theTargetMesh )
3310 const SMESH::PointStruct * P = &theVector.PS;
3311 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3313 TIDSortedElemSet copyElements;
3314 TIDSortedElemSet* workElements = &theElements;
3316 if ( myIsPreviewMode )
3318 TPreviewMesh * tmpMesh = getPreviewMesh();
3319 tmpMesh->Copy( theElements, copyElements);
3320 if ( !theCopy && !theTargetMesh )
3322 TIDSortedElemSet elemsAround, elemsAroundCopy;
3323 getElementsAround( theElements, getMeshDS(), elemsAround );
3324 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3326 workElements = & copyElements;
3327 theMakeGroups = false;
3330 ::SMESH_MeshEditor::PGroupIDs groupIds =
3331 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3333 if ( theCopy && !myIsPreviewMode )
3335 if ( theTargetMesh )
3337 theTargetMesh->GetMeshDS()->Modified();
3341 declareMeshModified( /*isReComputeSafe=*/false );
3345 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3347 SMESH_CATCH( SMESH::throwCorbaException );
3351 //=======================================================================
3352 //function : Translate
3354 //=======================================================================
3356 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3357 const SMESH::DirStruct & theVector,
3358 CORBA::Boolean theCopy)
3359 throw (SALOME::SALOME_Exception)
3361 if (!myIsPreviewMode) {
3362 TPythonDump() << this << ".Translate( "
3363 << theIDsOfElements << ", "
3364 << theVector << ", "
3367 if (theIDsOfElements.length()) {
3368 TIDSortedElemSet elements;
3369 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3370 translate(elements, theVector, theCopy, false);
3374 //=======================================================================
3375 //function : TranslateObject
3377 //=======================================================================
3379 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3380 const SMESH::DirStruct & theVector,
3381 CORBA::Boolean theCopy)
3382 throw (SALOME::SALOME_Exception)
3384 if (!myIsPreviewMode) {
3385 TPythonDump() << this << ".TranslateObject( "
3386 << theObject << ", "
3387 << theVector << ", "
3390 TIDSortedElemSet elements;
3392 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3394 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3395 translate(elements, theVector, theCopy, false);
3398 //=======================================================================
3399 //function : TranslateMakeGroups
3401 //=======================================================================
3403 SMESH::ListOfGroups*
3404 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3405 const SMESH::DirStruct& theVector)
3406 throw (SALOME::SALOME_Exception)
3408 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3410 SMESH::ListOfGroups * aGroups = 0;
3411 if (theIDsOfElements.length()) {
3412 TIDSortedElemSet elements;
3413 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3414 aGroups = translate(elements,theVector,true,true);
3416 if (!myIsPreviewMode) {
3417 dumpGroupsList(aPythonDump, aGroups);
3418 aPythonDump << this << ".TranslateMakeGroups( "
3419 << theIDsOfElements << ", "
3420 << theVector << " )";
3425 //=======================================================================
3426 //function : TranslateObjectMakeGroups
3428 //=======================================================================
3430 SMESH::ListOfGroups*
3431 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3432 const SMESH::DirStruct& theVector)
3433 throw (SALOME::SALOME_Exception)
3435 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3437 SMESH::ListOfGroups * aGroups = 0;
3438 TIDSortedElemSet elements;
3439 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3440 aGroups = translate(elements, theVector, true, true);
3442 if (!myIsPreviewMode) {
3443 dumpGroupsList(aPythonDump, aGroups);
3444 aPythonDump << this << ".TranslateObjectMakeGroups( "
3445 << theObject << ", "
3446 << theVector << " )";
3451 //=======================================================================
3452 //function : TranslateMakeMesh
3454 //=======================================================================
3456 SMESH::SMESH_Mesh_ptr
3457 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3458 const SMESH::DirStruct& theVector,
3459 CORBA::Boolean theCopyGroups,
3460 const char* theMeshName)
3461 throw (SALOME::SALOME_Exception)
3463 SMESH_Mesh_i* mesh_i;
3464 SMESH::SMESH_Mesh_var mesh;
3466 { // open new scope to dump "MakeMesh" command
3467 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3469 TPythonDump pydump; // to prevent dump at mesh creation
3471 mesh = makeMesh( theMeshName );
3472 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3474 if ( mesh_i && theIDsOfElements.length() )
3476 TIDSortedElemSet elements;
3477 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3478 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3479 mesh_i->CreateGroupServants();
3482 if ( !myIsPreviewMode ) {
3483 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3484 << theIDsOfElements << ", "
3485 << theVector << ", "
3486 << theCopyGroups << ", '"
3487 << theMeshName << "' )";
3492 if (!myIsPreviewMode && mesh_i)
3493 mesh_i->GetGroups();
3495 return mesh._retn();
3498 //=======================================================================
3499 //function : TranslateObjectMakeMesh
3501 //=======================================================================
3503 SMESH::SMESH_Mesh_ptr
3504 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3505 const SMESH::DirStruct& theVector,
3506 CORBA::Boolean theCopyGroups,
3507 const char* theMeshName)
3508 throw (SALOME::SALOME_Exception)
3511 SMESH_Mesh_i* mesh_i;
3512 SMESH::SMESH_Mesh_var mesh;
3513 { // open new scope to dump "MakeMesh" command
3514 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3516 TPythonDump pydump; // to prevent dump at mesh creation
3517 mesh = makeMesh( theMeshName );
3518 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3520 TIDSortedElemSet elements;
3522 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3524 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3525 mesh_i->CreateGroupServants();
3527 if ( !myIsPreviewMode ) {
3528 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3529 << theObject << ", "
3530 << theVector << ", "
3531 << theCopyGroups << ", '"
3532 << theMeshName << "' )";
3537 if (!myIsPreviewMode && mesh_i)
3538 mesh_i->GetGroups();
3540 return mesh._retn();
3542 SMESH_CATCH( SMESH::throwCorbaException );
3546 //=======================================================================
3549 //=======================================================================
3551 SMESH::ListOfGroups*
3552 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3553 const SMESH::AxisStruct & theAxis,
3554 CORBA::Double theAngle,
3555 CORBA::Boolean theCopy,
3557 ::SMESH_Mesh* theTargetMesh)
3558 throw (SALOME::SALOME_Exception)
3563 if ( theTargetMesh )
3566 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3567 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3570 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3572 TIDSortedElemSet copyElements;
3573 TIDSortedElemSet* workElements = &theElements;
3574 if ( myIsPreviewMode ) {
3575 TPreviewMesh * tmpMesh = getPreviewMesh();
3576 tmpMesh->Copy( theElements, copyElements );
3577 if ( !theCopy && !theTargetMesh )
3579 TIDSortedElemSet elemsAround, elemsAroundCopy;
3580 getElementsAround( theElements, getMeshDS(), elemsAround );
3581 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3583 workElements = ©Elements;
3584 theMakeGroups = false;
3587 ::SMESH_MeshEditor::PGroupIDs groupIds =
3588 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3590 if ( theCopy && !myIsPreviewMode)
3592 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3593 else declareMeshModified( /*isReComputeSafe=*/false );
3596 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3598 SMESH_CATCH( SMESH::throwCorbaException );
3602 //=======================================================================
3605 //=======================================================================
3607 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3608 const SMESH::AxisStruct & theAxis,
3609 CORBA::Double theAngle,
3610 CORBA::Boolean theCopy)
3611 throw (SALOME::SALOME_Exception)
3613 if (!myIsPreviewMode) {
3614 TPythonDump() << this << ".Rotate( "
3615 << theIDsOfElements << ", "
3617 << TVar( theAngle ) << ", "
3620 if (theIDsOfElements.length() > 0)
3622 TIDSortedElemSet elements;
3623 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3624 rotate(elements,theAxis,theAngle,theCopy,false);
3628 //=======================================================================
3629 //function : RotateObject
3631 //=======================================================================
3633 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3634 const SMESH::AxisStruct & theAxis,
3635 CORBA::Double theAngle,
3636 CORBA::Boolean theCopy)
3637 throw (SALOME::SALOME_Exception)
3639 if ( !myIsPreviewMode ) {
3640 TPythonDump() << this << ".RotateObject( "
3641 << theObject << ", "
3643 << TVar( theAngle ) << ", "
3646 TIDSortedElemSet elements;
3647 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3648 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3649 rotate(elements,theAxis,theAngle,theCopy,false);
3652 //=======================================================================
3653 //function : RotateMakeGroups
3655 //=======================================================================
3657 SMESH::ListOfGroups*
3658 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3659 const SMESH::AxisStruct& theAxis,
3660 CORBA::Double theAngle)
3661 throw (SALOME::SALOME_Exception)
3663 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3665 SMESH::ListOfGroups * aGroups = 0;
3666 if (theIDsOfElements.length() > 0)
3668 TIDSortedElemSet elements;
3669 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3670 aGroups = rotate(elements,theAxis,theAngle,true,true);
3672 if (!myIsPreviewMode) {
3673 dumpGroupsList(aPythonDump, aGroups);
3674 aPythonDump << this << ".RotateMakeGroups( "
3675 << theIDsOfElements << ", "
3677 << TVar( theAngle ) << " )";
3682 //=======================================================================
3683 //function : RotateObjectMakeGroups
3685 //=======================================================================
3687 SMESH::ListOfGroups*
3688 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3689 const SMESH::AxisStruct& theAxis,
3690 CORBA::Double theAngle)
3691 throw (SALOME::SALOME_Exception)
3693 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3695 SMESH::ListOfGroups * aGroups = 0;
3696 TIDSortedElemSet elements;
3697 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3698 aGroups = rotate(elements, theAxis, theAngle, true, true);
3700 if (!myIsPreviewMode) {
3701 dumpGroupsList(aPythonDump, aGroups);
3702 aPythonDump << this << ".RotateObjectMakeGroups( "
3703 << theObject << ", "
3705 << TVar( theAngle ) << " )";
3710 //=======================================================================
3711 //function : RotateMakeMesh
3713 //=======================================================================
3715 SMESH::SMESH_Mesh_ptr
3716 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3717 const SMESH::AxisStruct& theAxis,
3718 CORBA::Double theAngleInRadians,
3719 CORBA::Boolean theCopyGroups,
3720 const char* theMeshName)
3721 throw (SALOME::SALOME_Exception)
3724 SMESH::SMESH_Mesh_var mesh;
3725 SMESH_Mesh_i* mesh_i;
3727 { // open new scope to dump "MakeMesh" command
3728 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3730 TPythonDump pydump; // to prevent dump at mesh creation
3732 mesh = makeMesh( theMeshName );
3733 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3735 if ( mesh_i && theIDsOfElements.length() > 0 )
3737 TIDSortedElemSet elements;
3738 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3739 rotate(elements, theAxis, theAngleInRadians,
3740 false, theCopyGroups, & mesh_i->GetImpl());
3741 mesh_i->CreateGroupServants();
3743 if ( !myIsPreviewMode ) {
3744 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3745 << theIDsOfElements << ", "
3747 << TVar( theAngleInRadians ) << ", "
3748 << theCopyGroups << ", '"
3749 << theMeshName << "' )";
3754 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3755 mesh_i->GetGroups();
3757 return mesh._retn();
3759 SMESH_CATCH( SMESH::throwCorbaException );
3763 //=======================================================================
3764 //function : RotateObjectMakeMesh
3766 //=======================================================================
3768 SMESH::SMESH_Mesh_ptr
3769 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3770 const SMESH::AxisStruct& theAxis,
3771 CORBA::Double theAngleInRadians,
3772 CORBA::Boolean theCopyGroups,
3773 const char* theMeshName)
3774 throw (SALOME::SALOME_Exception)
3777 SMESH::SMESH_Mesh_var mesh;
3778 SMESH_Mesh_i* mesh_i;
3780 {// open new scope to dump "MakeMesh" command
3781 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3783 TPythonDump pydump; // to prevent dump at mesh creation
3784 mesh = makeMesh( theMeshName );
3785 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3787 TIDSortedElemSet elements;
3789 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3791 rotate(elements, theAxis, theAngleInRadians,
3792 false, theCopyGroups, & mesh_i->GetImpl());
3793 mesh_i->CreateGroupServants();
3795 if ( !myIsPreviewMode ) {
3796 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3797 << theObject << ", "
3799 << TVar( theAngleInRadians ) << ", "
3800 << theCopyGroups << ", '"
3801 << theMeshName << "' )";
3806 if (!myIsPreviewMode && mesh_i)
3807 mesh_i->GetGroups();
3809 return mesh._retn();
3811 SMESH_CATCH( SMESH::throwCorbaException );
3815 //=======================================================================
3818 //=======================================================================
3820 SMESH::ListOfGroups*
3821 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3822 const SMESH::PointStruct& thePoint,
3823 const SMESH::double_array& theScaleFact,
3824 CORBA::Boolean theCopy,
3826 ::SMESH_Mesh* theTargetMesh)
3827 throw (SALOME::SALOME_Exception)
3831 if ( theScaleFact.length() < 1 )
3832 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3833 if ( theScaleFact.length() == 2 )
3834 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3836 if ( theTargetMesh )
3839 TIDSortedElemSet elements;
3840 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3841 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3846 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3847 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3851 #if OCC_VERSION_LARGE > 0x06070100
3852 // fight against orthogonalization
3853 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3854 // 0, S[1], 0, thePoint.y * (1-S[1]),
3855 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3856 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3857 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3858 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3859 loc.SetCoord( thePoint.x * (1-S[0]),
3860 thePoint.y * (1-S[1]),
3861 thePoint.z * (1-S[2]));
3862 M.SetDiagonal( S[0], S[1], S[2] );
3865 double tol = std::numeric_limits<double>::max();
3866 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3867 0, S[1], 0, thePoint.y * (1-S[1]),
3868 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3871 TIDSortedElemSet copyElements;
3872 TIDSortedElemSet* workElements = &elements;
3873 if ( myIsPreviewMode )
3875 TPreviewMesh * tmpMesh = getPreviewMesh();
3876 tmpMesh->Copy( elements, copyElements);
3877 if ( !theCopy && !theTargetMesh )
3879 TIDSortedElemSet elemsAround, elemsAroundCopy;
3880 getElementsAround( elements, getMeshDS(), elemsAround );
3881 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3883 workElements = & copyElements;
3884 theMakeGroups = false;
3887 ::SMESH_MeshEditor::PGroupIDs groupIds =
3888 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3890 if ( theCopy && !myIsPreviewMode )
3892 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3893 else declareMeshModified( /*isReComputeSafe=*/false );
3895 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3897 SMESH_CATCH( SMESH::throwCorbaException );
3901 //=======================================================================
3904 //=======================================================================
3906 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3907 const SMESH::PointStruct& thePoint,
3908 const SMESH::double_array& theScaleFact,
3909 CORBA::Boolean theCopy)
3910 throw (SALOME::SALOME_Exception)
3912 if ( !myIsPreviewMode ) {
3913 TPythonDump() << this << ".Scale( "
3914 << theObject << ", "
3916 << TVar( theScaleFact ) << ", "
3919 scale(theObject, thePoint, theScaleFact, theCopy, false);
3923 //=======================================================================
3924 //function : ScaleMakeGroups
3926 //=======================================================================
3928 SMESH::ListOfGroups*
3929 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3930 const SMESH::PointStruct& thePoint,
3931 const SMESH::double_array& theScaleFact)
3932 throw (SALOME::SALOME_Exception)
3934 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3936 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3937 if (!myIsPreviewMode) {
3938 dumpGroupsList(aPythonDump, aGroups);
3939 aPythonDump << this << ".Scale("
3942 << TVar( theScaleFact ) << ",True,True)";
3948 //=======================================================================
3949 //function : ScaleMakeMesh
3951 //=======================================================================
3953 SMESH::SMESH_Mesh_ptr
3954 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3955 const SMESH::PointStruct& thePoint,
3956 const SMESH::double_array& theScaleFact,
3957 CORBA::Boolean theCopyGroups,
3958 const char* theMeshName)
3959 throw (SALOME::SALOME_Exception)
3961 SMESH_Mesh_i* mesh_i;
3962 SMESH::SMESH_Mesh_var mesh;
3963 { // open new scope to dump "MakeMesh" command
3964 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3966 TPythonDump pydump; // to prevent dump at mesh creation
3967 mesh = makeMesh( theMeshName );
3968 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3972 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3973 mesh_i->CreateGroupServants();
3975 if ( !myIsPreviewMode )
3976 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3977 << theObject << ", "
3979 << TVar( theScaleFact ) << ", "
3980 << theCopyGroups << ", '"
3981 << theMeshName << "' )";
3985 if (!myIsPreviewMode && mesh_i)
3986 mesh_i->GetGroups();
3988 return mesh._retn();
3992 //=======================================================================
3993 //function : findCoincidentNodes
3995 //=======================================================================
3997 void SMESH_MeshEditor_i::
3998 findCoincidentNodes (TIDSortedNodeSet & Nodes,
3999 CORBA::Double Tolerance,
4000 SMESH::array_of_long_array_out GroupsOfNodes,
4001 CORBA::Boolean SeparateCornersAndMedium)
4003 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4004 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4006 GroupsOfNodes = new SMESH::array_of_long_array;
4007 GroupsOfNodes->length( aListOfListOfNodes.size() );
4008 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4009 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4011 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4012 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4013 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4014 aGroup.length( aListOfNodes.size() );
4015 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4016 aGroup[ j ] = (*lIt)->GetID();
4020 //=======================================================================
4021 //function : FindCoincidentNodes
4023 //=======================================================================
4025 void SMESH_MeshEditor_i::
4026 FindCoincidentNodes (CORBA::Double Tolerance,
4027 SMESH::array_of_long_array_out GroupsOfNodes,
4028 CORBA::Boolean SeparateCornersAndMedium)
4029 throw (SALOME::SALOME_Exception)
4034 TIDSortedNodeSet nodes; // no input nodes
4035 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4037 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4038 << Tolerance << ", "
4039 << SeparateCornersAndMedium << " )";
4041 SMESH_CATCH( SMESH::throwCorbaException );
4044 //=======================================================================
4045 //function : FindCoincidentNodesOnPart
4047 //=======================================================================
4049 void SMESH_MeshEditor_i::
4050 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4051 CORBA::Double Tolerance,
4052 SMESH::array_of_long_array_out GroupsOfNodes,
4053 CORBA::Boolean SeparateCornersAndMedium)
4054 throw (SALOME::SALOME_Exception)
4059 TIDSortedNodeSet nodes;
4060 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4062 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4064 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4066 << Tolerance << ", "
4067 << SeparateCornersAndMedium << " )";
4069 SMESH_CATCH( SMESH::throwCorbaException );
4072 //================================================================================
4074 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4075 * ExceptSubMeshOrGroups
4077 //================================================================================
4079 void SMESH_MeshEditor_i::
4080 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4081 CORBA::Double theTolerance,
4082 SMESH::array_of_long_array_out theGroupsOfNodes,
4083 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4084 CORBA::Boolean theSeparateCornersAndMedium)
4085 throw (SALOME::SALOME_Exception)
4090 TIDSortedNodeSet nodes;
4091 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4093 for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4095 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4097 while ( nodeIt->more() )
4098 nodes.erase( cast2Node( nodeIt->next() ));
4100 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4102 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4104 << theTolerance << ", "
4105 << theExceptSubMeshOrGroups << ", "
4106 << theSeparateCornersAndMedium << " )";
4108 SMESH_CATCH( SMESH::throwCorbaException );
4111 //=======================================================================
4112 //function : MergeNodes
4114 //=======================================================================
4116 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
4117 throw (SALOME::SALOME_Exception)
4122 SMESHDS_Mesh* aMesh = getMeshDS();
4124 TPythonDump aTPythonDump;
4125 aTPythonDump << this << ".MergeNodes([";
4126 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4127 for (int i = 0; i < GroupsOfNodes.length(); i++)
4129 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4130 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4131 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4132 for ( int j = 0; j < aNodeGroup.length(); j++ )
4134 CORBA::Long index = aNodeGroup[ j ];
4135 const SMDS_MeshNode * node = aMesh->FindNode(index);
4137 aListOfNodes.push_back( node );
4139 if ( aListOfNodes.size() < 2 )
4140 aListOfListOfNodes.pop_back();
4142 if ( i > 0 ) aTPythonDump << ", ";
4143 aTPythonDump << aNodeGroup;
4145 getEditor().MergeNodes( aListOfListOfNodes );
4147 aTPythonDump << "])";
4149 declareMeshModified( /*isReComputeSafe=*/false );
4151 SMESH_CATCH( SMESH::throwCorbaException );
4154 //=======================================================================
4155 //function : FindEqualElements
4157 //=======================================================================
4159 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4160 SMESH::array_of_long_array_out GroupsOfElementsID)
4161 throw (SALOME::SALOME_Exception)
4166 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4167 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4169 TIDSortedElemSet elems;
4170 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4172 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4173 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4175 GroupsOfElementsID = new SMESH::array_of_long_array;
4176 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4178 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4179 aListOfListOfElementsID.begin();
4180 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4182 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4183 list<int>& listOfIDs = *arraysIt;
4184 aGroup.length( listOfIDs.size() );
4185 list<int>::iterator idIt = listOfIDs.begin();
4186 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4187 aGroup[ k ] = *idIt;
4190 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4194 SMESH_CATCH( SMESH::throwCorbaException );
4197 //=======================================================================
4198 //function : MergeElements
4200 //=======================================================================
4202 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4203 throw (SALOME::SALOME_Exception)
4208 TPythonDump aTPythonDump;
4209 aTPythonDump << this << ".MergeElements( [";
4211 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4213 for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4214 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4215 aListOfListOfElementsID.push_back( list< int >() );
4216 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4217 for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4218 CORBA::Long id = anElemsIDGroup[ j ];
4219 aListOfElemsID.push_back( id );
4221 if ( aListOfElemsID.size() < 2 )
4222 aListOfListOfElementsID.pop_back();
4223 if ( i > 0 ) aTPythonDump << ", ";
4224 aTPythonDump << anElemsIDGroup;
4227 getEditor().MergeElements(aListOfListOfElementsID);
4229 declareMeshModified( /*isReComputeSafe=*/true );
4231 aTPythonDump << "] )";
4233 SMESH_CATCH( SMESH::throwCorbaException );
4236 //=======================================================================
4237 //function : MergeEqualElements
4239 //=======================================================================
4241 void SMESH_MeshEditor_i::MergeEqualElements()
4242 throw (SALOME::SALOME_Exception)
4247 getEditor().MergeEqualElements();
4249 declareMeshModified( /*isReComputeSafe=*/true );
4251 TPythonDump() << this << ".MergeEqualElements()";
4253 SMESH_CATCH( SMESH::throwCorbaException );
4256 //=============================================================================
4258 * Move the node to a given point
4260 //=============================================================================
4262 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4266 throw (SALOME::SALOME_Exception)
4269 initData(/*deleteSearchers=*/false);
4271 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4275 if ( theNodeSearcher )
4276 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4278 if ( myIsPreviewMode ) // make preview data
4280 // in a preview mesh, make edges linked to a node
4281 TPreviewMesh& tmpMesh = *getPreviewMesh();
4282 TIDSortedElemSet linkedNodes;
4283 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4284 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4285 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4286 for ( ; nIt != linkedNodes.end(); ++nIt )
4288 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4289 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4293 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4294 // fill preview data
4296 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4297 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4299 getMeshDS()->MoveNode(node, x, y, z);
4301 if ( !myIsPreviewMode )
4303 // Update Python script
4304 TPythonDump() << "isDone = " << this << ".MoveNode( "
4305 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4306 declareMeshModified( /*isReComputeSafe=*/false );
4309 SMESH_CATCH( SMESH::throwCorbaException );
4314 //================================================================================
4316 * \brief Return ID of node closest to a given point
4318 //================================================================================
4320 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4323 throw (SALOME::SALOME_Exception)
4326 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4328 if ( !theNodeSearcher ) {
4329 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4332 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4333 return node->GetID();
4335 SMESH_CATCH( SMESH::throwCorbaException );
4339 //================================================================================
4341 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4342 * move the node closest to the point to point's location and return ID of the node
4344 //================================================================================
4346 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4349 CORBA::Long theNodeID)
4350 throw (SALOME::SALOME_Exception)
4353 // We keep theNodeSearcher until any mesh modification:
4354 // 1) initData() deletes theNodeSearcher at any edition,
4355 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4357 initData(/*deleteSearchers=*/false);
4359 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4361 int nodeID = theNodeID;
4362 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4363 if ( !node ) // preview moving node
4365 if ( !theNodeSearcher ) {
4366 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4369 node = theNodeSearcher->FindClosestTo( p );
4372 nodeID = node->GetID();
4373 if ( myIsPreviewMode ) // make preview data
4375 // in a preview mesh, make edges linked to a node
4376 TPreviewMesh tmpMesh = *getPreviewMesh();
4377 TIDSortedElemSet linkedNodes;
4378 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4379 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4380 for ( ; nIt != linkedNodes.end(); ++nIt )
4382 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4383 tmpMesh.Copy( &edge );
4386 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4388 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4389 // fill preview data
4391 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4393 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4397 getMeshDS()->MoveNode(node, x, y, z);
4401 if ( !myIsPreviewMode )
4403 TPythonDump() << "nodeID = " << this
4404 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4405 << ", " << nodeID << " )";
4407 declareMeshModified( /*isReComputeSafe=*/false );
4412 SMESH_CATCH( SMESH::throwCorbaException );
4416 //=======================================================================
4418 * Return elements of given type where the given point is IN or ON.
4420 * 'ALL' type means elements of any type excluding nodes
4422 //=======================================================================
4424 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4427 SMESH::ElementType type)
4428 throw (SALOME::SALOME_Exception)
4431 SMESH::long_array_var res = new SMESH::long_array;
4432 vector< const SMDS_MeshElement* > foundElems;
4434 theSearchersDeleter.Set( myMesh );
4435 if ( !theElementSearcher ) {
4436 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4438 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4439 SMDSAbs_ElementType( type ),
4441 res->length( foundElems.size() );
4442 for ( int i = 0; i < foundElems.size(); ++i )
4443 res[i] = foundElems[i]->GetID();
4447 SMESH_CATCH( SMESH::throwCorbaException );
4451 //=======================================================================
4452 //function : FindAmongElementsByPoint
4453 //purpose : Searching among the given elements, return elements of given type
4454 // where the given point is IN or ON.
4455 // 'ALL' type means elements of any type excluding nodes
4456 //=======================================================================
4459 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4463 SMESH::ElementType type)
4464 throw (SALOME::SALOME_Exception)
4467 SMESH::long_array_var res = new SMESH::long_array;
4469 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4470 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4471 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4472 type != types[0] ) // but search of elements of dim > 0
4475 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4476 return FindElementsByPoint( x,y,z, type );
4478 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4480 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4481 if ( !theElementSearcher )
4483 // create a searcher from elementIDs
4484 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4485 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4487 if ( !idSourceToSet( elementIDs, meshDS, elements,
4488 SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4491 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4492 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4494 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4497 vector< const SMDS_MeshElement* > foundElems;
4499 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4500 SMDSAbs_ElementType( type ),
4502 res->length( foundElems.size() );
4503 for ( int i = 0; i < foundElems.size(); ++i )
4504 res[i] = foundElems[i]->GetID();
4508 SMESH_CATCH( SMESH::throwCorbaException );
4512 //=======================================================================
4513 //function : GetPointState
4514 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4515 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4516 //=======================================================================
4518 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4521 throw (SALOME::SALOME_Exception)
4524 theSearchersDeleter.Set( myMesh );
4525 if ( !theElementSearcher ) {
4526 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4528 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4530 SMESH_CATCH( SMESH::throwCorbaException );
4534 //=======================================================================
4535 //function : convError
4537 //=======================================================================
4539 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4541 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4545 RETCASE( SEW_BORDER1_NOT_FOUND );
4546 RETCASE( SEW_BORDER2_NOT_FOUND );
4547 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4548 RETCASE( SEW_BAD_SIDE_NODES );
4549 RETCASE( SEW_VOLUMES_TO_SPLIT );
4550 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4551 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4552 RETCASE( SEW_BAD_SIDE1_NODES );
4553 RETCASE( SEW_BAD_SIDE2_NODES );
4555 return SMESH::SMESH_MeshEditor::SEW_OK;
4558 //=======================================================================
4559 //function : SewFreeBorders
4561 //=======================================================================
4563 SMESH::SMESH_MeshEditor::Sew_Error
4564 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4565 CORBA::Long SecondNodeID1,
4566 CORBA::Long LastNodeID1,
4567 CORBA::Long FirstNodeID2,
4568 CORBA::Long SecondNodeID2,
4569 CORBA::Long LastNodeID2,
4570 CORBA::Boolean CreatePolygons,
4571 CORBA::Boolean CreatePolyedrs)
4572 throw (SALOME::SALOME_Exception)
4577 SMESHDS_Mesh* aMesh = getMeshDS();
4579 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4580 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4581 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4582 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4583 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4584 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4586 if (!aBorderFirstNode ||
4587 !aBorderSecondNode||
4589 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4590 if (!aSide2FirstNode ||
4591 !aSide2SecondNode ||
4593 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4595 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4596 << FirstNodeID1 << ", "
4597 << SecondNodeID1 << ", "
4598 << LastNodeID1 << ", "
4599 << FirstNodeID2 << ", "
4600 << SecondNodeID2 << ", "
4601 << LastNodeID2 << ", "
4602 << CreatePolygons<< ", "
4603 << CreatePolyedrs<< " )";
4605 SMESH::SMESH_MeshEditor::Sew_Error error =
4606 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4617 declareMeshModified( /*isReComputeSafe=*/false );
4620 SMESH_CATCH( SMESH::throwCorbaException );
4621 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4625 //=======================================================================
4626 //function : SewConformFreeBorders
4628 //=======================================================================
4630 SMESH::SMESH_MeshEditor::Sew_Error
4631 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4632 CORBA::Long SecondNodeID1,
4633 CORBA::Long LastNodeID1,
4634 CORBA::Long FirstNodeID2,
4635 CORBA::Long SecondNodeID2)
4636 throw (SALOME::SALOME_Exception)
4641 SMESHDS_Mesh* aMesh = getMeshDS();
4643 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4644 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4645 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4646 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4647 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4648 const SMDS_MeshNode* aSide2ThirdNode = 0;
4650 if (!aBorderFirstNode ||
4651 !aBorderSecondNode||
4653 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4654 if (!aSide2FirstNode ||
4656 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4658 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4659 << FirstNodeID1 << ", "
4660 << SecondNodeID1 << ", "
4661 << LastNodeID1 << ", "
4662 << FirstNodeID2 << ", "
4663 << SecondNodeID2 << " )";
4665 SMESH::SMESH_MeshEditor::Sew_Error error =
4666 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4675 declareMeshModified( /*isReComputeSafe=*/false );
4678 SMESH_CATCH( SMESH::throwCorbaException );
4679 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4683 //=======================================================================
4684 //function : SewBorderToSide
4686 //=======================================================================
4688 SMESH::SMESH_MeshEditor::Sew_Error
4689 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4690 CORBA::Long SecondNodeIDOnFreeBorder,
4691 CORBA::Long LastNodeIDOnFreeBorder,
4692 CORBA::Long FirstNodeIDOnSide,
4693 CORBA::Long LastNodeIDOnSide,
4694 CORBA::Boolean CreatePolygons,
4695 CORBA::Boolean CreatePolyedrs)
4696 throw (SALOME::SALOME_Exception)
4701 SMESHDS_Mesh* aMesh = getMeshDS();
4703 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4704 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4705 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4706 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4707 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4708 const SMDS_MeshNode* aSide2ThirdNode = 0;
4710 if (!aBorderFirstNode ||
4711 !aBorderSecondNode||
4713 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4714 if (!aSide2FirstNode ||
4716 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4718 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4719 << FirstNodeIDOnFreeBorder << ", "
4720 << SecondNodeIDOnFreeBorder << ", "
4721 << LastNodeIDOnFreeBorder << ", "
4722 << FirstNodeIDOnSide << ", "
4723 << LastNodeIDOnSide << ", "
4724 << CreatePolygons << ", "
4725 << CreatePolyedrs << ") ";
4727 SMESH::SMESH_MeshEditor::Sew_Error error =
4728 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4738 declareMeshModified( /*isReComputeSafe=*/false );
4741 SMESH_CATCH( SMESH::throwCorbaException );
4742 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4746 //=======================================================================
4747 //function : SewSideElements
4749 //=======================================================================
4751 SMESH::SMESH_MeshEditor::Sew_Error
4752 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4753 const SMESH::long_array& IDsOfSide2Elements,
4754 CORBA::Long NodeID1OfSide1ToMerge,
4755 CORBA::Long NodeID1OfSide2ToMerge,
4756 CORBA::Long NodeID2OfSide1ToMerge,
4757 CORBA::Long NodeID2OfSide2ToMerge)
4758 throw (SALOME::SALOME_Exception)
4763 SMESHDS_Mesh* aMesh = getMeshDS();
4765 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
4766 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
4767 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4768 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4770 if (!aFirstNode1ToMerge ||
4771 !aFirstNode2ToMerge )
4772 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4773 if (!aSecondNode1ToMerge||
4774 !aSecondNode2ToMerge)
4775 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4777 TIDSortedElemSet aSide1Elems, aSide2Elems;
4778 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4779 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4781 TPythonDump() << "error = " << this << ".SewSideElements( "
4782 << IDsOfSide1Elements << ", "
4783 << IDsOfSide2Elements << ", "
4784 << NodeID1OfSide1ToMerge << ", "
4785 << NodeID1OfSide2ToMerge << ", "
4786 << NodeID2OfSide1ToMerge << ", "
4787 << NodeID2OfSide2ToMerge << ")";
4789 SMESH::SMESH_MeshEditor::Sew_Error error =
4790 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
4793 aSecondNode1ToMerge,
4794 aSecondNode2ToMerge));
4796 declareMeshModified( /*isReComputeSafe=*/false );
4799 SMESH_CATCH( SMESH::throwCorbaException );
4800 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4803 //================================================================================
4805 * \brief Set new nodes for given element
4806 * \param ide - element id
4807 * \param newIDs - new node ids
4808 * \retval CORBA::Boolean - true if result is OK
4810 //================================================================================
4812 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4813 const SMESH::long_array& newIDs)
4814 throw (SALOME::SALOME_Exception)
4819 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
4820 if(!elem) return false;
4822 int nbn = newIDs.length();
4824 vector<const SMDS_MeshNode*> aNodes(nbn);
4827 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
4830 aNodes[nbn1] = aNode;
4833 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4834 << ide << ", " << newIDs << " )";
4836 MESSAGE("ChangeElementNodes");
4837 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4839 declareMeshModified( /*isReComputeSafe=*/ !res );
4843 SMESH_CATCH( SMESH::throwCorbaException );
4847 //=======================================================================
4849 * \brief Makes a part of the mesh quadratic or bi-quadratic
4851 //=======================================================================
4853 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
4854 CORBA::Boolean theToBiQuad,
4855 SMESH::SMESH_IDSource_ptr theObject)
4856 throw (SALOME::SALOME_Exception)
4861 TIDSortedElemSet elems;
4863 if ( !( elemsOK = CORBA::is_nil( theObject )))
4865 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
4866 SMDSAbs_All, /*emptyIfIsMesh=*/true );
4870 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
4871 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4873 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
4874 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
4876 declareMeshModified( /*isReComputeSafe=*/false );
4879 SMESH_CATCH( SMESH::throwCorbaException );
4882 //=======================================================================
4883 //function : ConvertFromQuadratic
4885 //=======================================================================
4887 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4888 throw (SALOME::SALOME_Exception)
4893 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
4894 TPythonDump() << this << ".ConvertFromQuadratic()";
4895 declareMeshModified( /*isReComputeSafe=*/!isDone );
4898 SMESH_CATCH( SMESH::throwCorbaException );
4902 //=======================================================================
4903 //function : ConvertToQuadratic
4905 //=======================================================================
4907 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4908 throw (SALOME::SALOME_Exception)
4910 convertToQuadratic( theForce3d, false );
4911 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
4914 //================================================================================
4916 * \brief Makes a part of the mesh quadratic
4918 //================================================================================
4920 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
4921 SMESH::SMESH_IDSource_ptr theObject)
4922 throw (SALOME::SALOME_Exception)
4924 convertToQuadratic( theForce3d, false, theObject );
4925 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
4928 //================================================================================
4930 * \brief Makes a part of the mesh bi-quadratic
4932 //================================================================================
4934 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
4935 SMESH::SMESH_IDSource_ptr theObject)
4936 throw (SALOME::SALOME_Exception)
4938 convertToQuadratic( theForce3d, true, theObject );
4939 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
4942 //================================================================================
4944 * \brief Makes a part of the mesh linear
4946 //================================================================================
4948 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
4949 throw (SALOME::SALOME_Exception)
4956 TIDSortedElemSet elems;
4957 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
4959 if ( elems.empty() )
4961 ConvertFromQuadratic();
4963 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
4965 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4969 getEditor().ConvertFromQuadratic(elems);
4972 declareMeshModified( /*isReComputeSafe=*/false );
4974 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
4976 SMESH_CATCH( SMESH::throwCorbaException );
4979 //=======================================================================
4980 //function : makeMesh
4981 //purpose : create a named imported mesh
4982 //=======================================================================
4984 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4986 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4987 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4988 SALOMEDS::Study_var study = gen->GetCurrentStudy();
4989 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
4990 gen->SetName( meshSO, theMeshName, "Mesh" );
4991 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4993 return mesh._retn();
4996 //=======================================================================
4997 //function : dumpGroupsList
4999 //=======================================================================
5001 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5002 const SMESH::ListOfGroups * theGroupList)
5004 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5005 if ( isDumpGroupList )
5006 theDumpPython << theGroupList << " = ";
5009 //================================================================================
5011 \brief Generates the unique group name.
5012 \param thePrefix name prefix
5015 //================================================================================
5017 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
5019 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5020 set<string> groupNames;
5022 // Get existing group names
5023 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5024 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5025 if (CORBA::is_nil(aGroup))
5028 CORBA::String_var name = aGroup->GetName();
5029 groupNames.insert( name.in() );
5033 string name = thePrefix;
5036 while (!groupNames.insert(name).second)
5037 name = SMESH_Comment( thePrefix ) << "_" << index++;
5042 //================================================================================
5044 * \brief Prepare SMESH_IDSource for work
5046 //================================================================================
5048 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5050 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5052 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5053 filter->SetMesh( mesh );
5056 //================================================================================
5058 * \brief Retrieve elements of given type from SMESH_IDSource
5060 //================================================================================
5062 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5063 const SMESHDS_Mesh* theMeshDS,
5064 TIDSortedElemSet& theElemSet,
5065 const SMDSAbs_ElementType theType,
5066 const bool emptyIfIsMesh,
5067 IDSource_Error* error)
5070 if ( error ) *error = IDSource_OK;
5072 if ( CORBA::is_nil( theIDSource ) )
5074 if ( error ) *error = IDSource_INVALID;
5077 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5079 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5080 *error = IDSource_EMPTY;
5083 prepareIdSource( theIDSource );
5084 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5085 if ( anIDs->length() == 0 )
5087 if ( error ) *error = IDSource_EMPTY;
5090 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5091 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5093 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5095 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5099 if ( error ) *error = IDSource_INVALID;
5105 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5106 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5108 if ( error ) *error = IDSource_INVALID;
5115 //================================================================================
5117 * \brief Duplicates given elements, i.e. creates new elements based on the
5118 * same nodes as the given ones.
5119 * \param theElements - container of elements to duplicate.
5120 * \param theGroupName - a name of group to contain the generated elements.
5121 * If a group with such a name already exists, the new elements
5122 * are added to the existng group, else a new group is created.
5123 * If \a theGroupName is empty, new elements are not added
5125 * \return a group where the new elements are added. NULL if theGroupName == "".
5128 //================================================================================
5130 SMESH::SMESH_Group_ptr
5131 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5132 const char* theGroupName)
5133 throw (SALOME::SALOME_Exception)
5135 SMESH::SMESH_Group_var newGroup;
5142 TIDSortedElemSet elems;
5143 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5145 getEditor().DoubleElements( elems );
5147 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5150 SMESH::ElementType type =
5151 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5152 // find existing group
5153 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5154 for ( size_t i = 0; i < groups->length(); ++i )
5155 if ( groups[i]->GetType() == type )
5157 CORBA::String_var name = groups[i]->GetName();
5158 if ( strcmp( name, theGroupName ) == 0 ) {
5159 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5163 // create a new group
5164 if ( newGroup->_is_nil() )
5165 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5167 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5169 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5170 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5171 for ( int i = 1; i <= aSeq.Length(); i++ )
5172 groupDS->SMDSGroup().Add( aSeq(i) );
5177 if ( !newGroup->_is_nil() )
5178 pyDump << newGroup << " = ";
5179 pyDump << this << ".DoubleElements( "
5180 << theElements << ", " << "'" << theGroupName <<"')";
5182 SMESH_CATCH( SMESH::throwCorbaException );
5184 return newGroup._retn();
5187 //================================================================================
5189 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5190 \param theNodes - identifiers of nodes to be doubled
5191 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5192 nodes. If list of element identifiers is empty then nodes are doubled but
5193 they not assigned to elements
5194 \return TRUE if operation has been completed successfully, FALSE otherwise
5195 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5197 //================================================================================
5199 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5200 const SMESH::long_array& theModifiedElems )
5201 throw (SALOME::SALOME_Exception)
5206 list< int > aListOfNodes;
5208 for ( i = 0, n = theNodes.length(); i < n; i++ )
5209 aListOfNodes.push_back( theNodes[ i ] );
5211 list< int > aListOfElems;
5212 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5213 aListOfElems.push_back( theModifiedElems[ i ] );
5215 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5217 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5219 // Update Python script
5220 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5224 SMESH_CATCH( SMESH::throwCorbaException );
5228 //================================================================================
5230 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5231 This method provided for convenience works as DoubleNodes() described above.
5232 \param theNodeId - identifier of node to be doubled.
5233 \param theModifiedElems - identifiers of elements to be updated.
5234 \return TRUE if operation has been completed successfully, FALSE otherwise
5235 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5237 //================================================================================
5239 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5240 const SMESH::long_array& theModifiedElems )
5241 throw (SALOME::SALOME_Exception)
5244 SMESH::long_array_var aNodes = new SMESH::long_array;
5245 aNodes->length( 1 );
5246 aNodes[ 0 ] = theNodeId;
5248 TPythonDump pyDump; // suppress dump by the next line
5250 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5252 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5256 SMESH_CATCH( SMESH::throwCorbaException );
5260 //================================================================================
5262 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5263 This method provided for convenience works as DoubleNodes() described above.
5264 \param theNodes - group of nodes to be doubled.
5265 \param theModifiedElems - group of elements to be updated.
5266 \return TRUE if operation has been completed successfully, FALSE otherwise
5267 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5269 //================================================================================
5271 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5272 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5273 throw (SALOME::SALOME_Exception)
5276 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5279 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5280 SMESH::long_array_var aModifiedElems;
5281 if ( !CORBA::is_nil( theModifiedElems ) )
5282 aModifiedElems = theModifiedElems->GetListOfID();
5285 aModifiedElems = new SMESH::long_array;
5286 aModifiedElems->length( 0 );
5289 TPythonDump pyDump; // suppress dump by the next line
5291 bool done = DoubleNodes( aNodes, aModifiedElems );
5293 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5297 SMESH_CATCH( SMESH::throwCorbaException );
5301 //================================================================================
5303 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5304 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5305 * \param theNodes - group of nodes to be doubled.
5306 * \param theModifiedElems - group of elements to be updated.
5307 * \return a new group with newly created nodes
5308 * \sa DoubleNodeGroup()
5310 //================================================================================
5312 SMESH::SMESH_Group_ptr
5313 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5314 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5315 throw (SALOME::SALOME_Exception)
5318 SMESH::SMESH_Group_var aNewGroup;
5320 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5321 return aNewGroup._retn();
5324 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5325 SMESH::long_array_var aModifiedElems;
5326 if ( !CORBA::is_nil( theModifiedElems ) )
5327 aModifiedElems = theModifiedElems->GetListOfID();
5329 aModifiedElems = new SMESH::long_array;
5330 aModifiedElems->length( 0 );
5333 TPythonDump pyDump; // suppress dump by the next line
5335 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5338 // Create group with newly created nodes
5339 SMESH::long_array_var anIds = GetLastCreatedNodes();
5340 if (anIds->length() > 0) {
5341 string anUnindexedName (theNodes->GetName());
5342 string aNewName = generateGroupName(anUnindexedName + "_double");
5343 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5344 aNewGroup->Add(anIds);
5345 pyDump << aNewGroup << " = ";
5349 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5350 << theModifiedElems << " )";
5352 return aNewGroup._retn();
5354 SMESH_CATCH( SMESH::throwCorbaException );
5358 //================================================================================
5360 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5361 This method provided for convenience works as DoubleNodes() described above.
5362 \param theNodes - list of groups of nodes to be doubled
5363 \param theModifiedElems - list of groups of elements to be updated.
5364 \return TRUE if operation has been completed successfully, FALSE otherwise
5365 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5367 //================================================================================
5369 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5370 const SMESH::ListOfGroups& theModifiedElems )
5371 throw (SALOME::SALOME_Exception)
5376 std::list< int > aNodes;
5378 for ( i = 0, n = theNodes.length(); i < n; i++ )
5380 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5381 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5383 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5384 for ( j = 0, m = aCurr->length(); j < m; j++ )
5385 aNodes.push_back( aCurr[ j ] );
5389 std::list< int > anElems;
5390 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5392 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5393 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5395 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5396 for ( j = 0, m = aCurr->length(); j < m; j++ )
5397 anElems.push_back( aCurr[ j ] );
5401 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5403 declareMeshModified( /*isReComputeSafe=*/false );
5405 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5409 SMESH_CATCH( SMESH::throwCorbaException );
5413 //================================================================================
5415 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5416 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5417 * \param theNodes - group of nodes to be doubled.
5418 * \param theModifiedElems - group of elements to be updated.
5419 * \return a new group with newly created nodes
5420 * \sa DoubleNodeGroups()
5422 //================================================================================
5424 SMESH::SMESH_Group_ptr
5425 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5426 const SMESH::ListOfGroups& theModifiedElems )
5427 throw (SALOME::SALOME_Exception)
5429 SMESH::SMESH_Group_var aNewGroup;
5431 TPythonDump pyDump; // suppress dump by the next line
5433 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5437 // Create group with newly created nodes
5438 SMESH::long_array_var anIds = GetLastCreatedNodes();
5439 if (anIds->length() > 0) {
5440 string anUnindexedName (theNodes[0]->GetName());
5441 string aNewName = generateGroupName(anUnindexedName + "_double");
5442 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5443 aNewGroup->Add(anIds);
5444 pyDump << aNewGroup << " = ";
5448 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5449 << theModifiedElems << " )";
5451 return aNewGroup._retn();
5455 //================================================================================
5457 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5458 \param theElems - the list of elements (edges or faces) to be replicated
5459 The nodes for duplication could be found from these elements
5460 \param theNodesNot - list of nodes to NOT replicate
5461 \param theAffectedElems - the list of elements (cells and edges) to which the
5462 replicated nodes should be associated to.
5463 \return TRUE if operation has been completed successfully, FALSE otherwise
5464 \sa DoubleNodeGroup(), DoubleNodeGroups()
5466 //================================================================================
5468 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5469 const SMESH::long_array& theNodesNot,
5470 const SMESH::long_array& theAffectedElems )
5471 throw (SALOME::SALOME_Exception)
5476 SMESHDS_Mesh* aMeshDS = getMeshDS();
5477 TIDSortedElemSet anElems, aNodes, anAffected;
5478 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5479 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5480 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5482 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5484 // Update Python script
5485 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5486 << theNodesNot << ", " << theAffectedElems << " )";
5488 declareMeshModified( /*isReComputeSafe=*/false );
5491 SMESH_CATCH( SMESH::throwCorbaException );
5495 //================================================================================
5497 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5498 \param theElems - the list of elements (edges or faces) to be replicated
5499 The nodes for duplication could be found from these elements
5500 \param theNodesNot - list of nodes to NOT replicate
5501 \param theShape - shape to detect affected elements (element which geometric center
5502 located on or inside shape).
5503 The replicated nodes should be associated to affected elements.
5504 \return TRUE if operation has been completed successfully, FALSE otherwise
5505 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5507 //================================================================================
5509 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5510 const SMESH::long_array& theNodesNot,
5511 GEOM::GEOM_Object_ptr theShape )
5512 throw (SALOME::SALOME_Exception)
5518 SMESHDS_Mesh* aMeshDS = getMeshDS();
5519 TIDSortedElemSet anElems, aNodes;
5520 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5521 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5523 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5524 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5526 // Update Python script
5527 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5528 << theNodesNot << ", " << theShape << " )";
5530 declareMeshModified( /*isReComputeSafe=*/false );
5533 SMESH_CATCH( SMESH::throwCorbaException );
5537 //================================================================================
5539 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5540 \param theElems - group of of elements (edges or faces) to be replicated
5541 \param theNodesNot - group of nodes not to replicated
5542 \param theAffectedElems - group of elements to which the replicated nodes
5543 should be associated to.
5544 \return TRUE if operation has been completed successfully, FALSE otherwise
5545 \sa DoubleNodes(), DoubleNodeGroups()
5547 //================================================================================
5550 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5551 SMESH::SMESH_GroupBase_ptr theNodesNot,
5552 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5553 throw (SALOME::SALOME_Exception)
5556 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5562 SMESHDS_Mesh* aMeshDS = getMeshDS();
5563 TIDSortedElemSet anElems, aNodes, anAffected;
5564 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5565 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5566 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5568 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5570 // Update Python script
5571 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5572 << theNodesNot << ", " << theAffectedElems << " )";
5574 declareMeshModified( /*isReComputeSafe=*/false );
5577 SMESH_CATCH( SMESH::throwCorbaException );
5581 //================================================================================
5583 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5584 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5585 * \param theElems - group of of elements (edges or faces) to be replicated
5586 * \param theNodesNot - group of nodes not to replicated
5587 * \param theAffectedElems - group of elements to which the replicated nodes
5588 * should be associated to.
5589 * \return a new group with newly created elements
5590 * \sa DoubleNodeElemGroup()
5592 //================================================================================
5594 SMESH::SMESH_Group_ptr
5595 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5596 SMESH::SMESH_GroupBase_ptr theNodesNot,
5597 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5598 throw (SALOME::SALOME_Exception)
5601 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5605 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5606 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5608 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5610 << theNodesNot << ", "
5611 << theAffectedElems << " )";
5613 return elemGroup._retn();
5616 //================================================================================
5618 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5619 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5620 * \param theElems - group of of elements (edges or faces) to be replicated
5621 * \param theNodesNot - group of nodes not to replicated
5622 * \param theAffectedElems - group of elements to which the replicated nodes
5623 * should be associated to.
5624 * \return a new group with newly created elements
5625 * \sa DoubleNodeElemGroup()
5627 //================================================================================
5629 SMESH::ListOfGroups*
5630 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5631 SMESH::SMESH_GroupBase_ptr theNodesNot,
5632 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5633 CORBA::Boolean theElemGroupNeeded,
5634 CORBA::Boolean theNodeGroupNeeded)
5635 throw (SALOME::SALOME_Exception)
5638 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5639 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5640 aTwoGroups->length( 2 );
5642 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5643 return aTwoGroups._retn();
5648 SMESHDS_Mesh* aMeshDS = getMeshDS();
5649 TIDSortedElemSet anElems, aNodes, anAffected;
5650 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5651 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5652 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5655 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5657 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5663 // Create group with newly created elements
5664 CORBA::String_var elemGroupName = theElems->GetName();
5665 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5666 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5668 SMESH::long_array_var anIds = GetLastCreatedElems();
5669 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5670 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5671 aNewElemGroup->Add(anIds);
5673 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5675 SMESH::long_array_var anIds = GetLastCreatedNodes();
5676 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5677 aNewNodeGroup->Add(anIds);
5681 // Update Python script
5684 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5685 else pyDump << aNewElemGroup << ", ";
5686 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5687 else pyDump << aNewNodeGroup << " ] = ";
5689 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5690 << theNodesNot << ", "
5691 << theAffectedElems << ", "
5692 << theElemGroupNeeded << ", "
5693 << theNodeGroupNeeded <<" )";
5695 aTwoGroups[0] = aNewElemGroup._retn();
5696 aTwoGroups[1] = aNewNodeGroup._retn();
5697 return aTwoGroups._retn();
5699 SMESH_CATCH( SMESH::throwCorbaException );
5703 //================================================================================
5705 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5706 \param theElems - group of of elements (edges or faces) to be replicated
5707 \param theNodesNot - group of nodes not to replicated
5708 \param theShape - shape to detect affected elements (element which geometric center
5709 located on or inside shape).
5710 The replicated nodes should be associated to affected elements.
5711 \return TRUE if operation has been completed successfully, FALSE otherwise
5712 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5714 //================================================================================
5717 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5718 SMESH::SMESH_GroupBase_ptr theNodesNot,
5719 GEOM::GEOM_Object_ptr theShape )
5720 throw (SALOME::SALOME_Exception)
5723 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5729 SMESHDS_Mesh* aMeshDS = getMeshDS();
5730 TIDSortedElemSet anElems, aNodes, anAffected;
5731 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5732 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5734 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5735 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5738 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5740 // Update Python script
5741 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5742 << theNodesNot << ", " << theShape << " )";
5745 SMESH_CATCH( SMESH::throwCorbaException );
5749 //================================================================================
5751 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5752 * \param [in] theGrpList - groups
5753 * \param [in] theMeshDS - mesh
5754 * \param [out] theElemSet - set of elements
5755 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5757 //================================================================================
5759 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5760 SMESHDS_Mesh* theMeshDS,
5761 TIDSortedElemSet& theElemSet,
5762 const bool theIsNodeGrp)
5764 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5766 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5767 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5768 : aGrp->GetType() != SMESH::NODE ) )
5770 SMESH::long_array_var anIDs = aGrp->GetIDs();
5771 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5776 //================================================================================
5778 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5779 This method provided for convenience works as DoubleNodes() described above.
5780 \param theElems - list of groups of elements (edges or faces) to be replicated
5781 \param theNodesNot - list of groups of nodes not to replicated
5782 \param theAffectedElems - group of elements to which the replicated nodes
5783 should be associated to.
5784 \return TRUE if operation has been completed successfully, FALSE otherwise
5785 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5787 //================================================================================
5790 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5791 const SMESH::ListOfGroups& theNodesNot,
5792 const SMESH::ListOfGroups& theAffectedElems)
5793 throw (SALOME::SALOME_Exception)
5799 SMESHDS_Mesh* aMeshDS = getMeshDS();
5800 TIDSortedElemSet anElems, aNodes, anAffected;
5801 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5802 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5803 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5805 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5807 // Update Python script
5808 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5809 << &theNodesNot << ", " << &theAffectedElems << " )";
5811 declareMeshModified( /*isReComputeSafe=*/false );
5814 SMESH_CATCH( SMESH::throwCorbaException );
5818 //================================================================================
5820 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5821 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5822 \param theElems - list of groups of elements (edges or faces) to be replicated
5823 \param theNodesNot - list of groups of nodes not to replicated
5824 \param theAffectedElems - group of elements to which the replicated nodes
5825 should be associated to.
5826 * \return a new group with newly created elements
5827 * \sa DoubleNodeElemGroups()
5829 //================================================================================
5831 SMESH::SMESH_Group_ptr
5832 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5833 const SMESH::ListOfGroups& theNodesNot,
5834 const SMESH::ListOfGroups& theAffectedElems)
5835 throw (SALOME::SALOME_Exception)
5838 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
5842 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5843 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5845 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
5847 << theNodesNot << ", "
5848 << theAffectedElems << " )";
5850 return elemGroup._retn();
5853 //================================================================================
5855 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5856 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5857 \param theElems - list of groups of elements (edges or faces) to be replicated
5858 \param theNodesNot - list of groups of nodes not to replicated
5859 \param theAffectedElems - group of elements to which the replicated nodes
5860 should be associated to.
5861 * \return a new group with newly created elements
5862 * \sa DoubleNodeElemGroups()
5864 //================================================================================
5866 SMESH::ListOfGroups*
5867 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
5868 const SMESH::ListOfGroups& theNodesNot,
5869 const SMESH::ListOfGroups& theAffectedElems,
5870 CORBA::Boolean theElemGroupNeeded,
5871 CORBA::Boolean theNodeGroupNeeded)
5872 throw (SALOME::SALOME_Exception)
5875 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5876 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5877 aTwoGroups->length( 2 );
5882 SMESHDS_Mesh* aMeshDS = getMeshDS();
5883 TIDSortedElemSet anElems, aNodes, anAffected;
5884 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5885 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5886 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5888 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5890 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5895 // Create group with newly created elements
5896 CORBA::String_var elemGroupName = theElems[0]->GetName();
5897 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5898 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5900 SMESH::long_array_var anIds = GetLastCreatedElems();
5901 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5902 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5903 aNewElemGroup->Add(anIds);
5905 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5907 SMESH::long_array_var anIds = GetLastCreatedNodes();
5908 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5909 aNewNodeGroup->Add(anIds);
5913 // Update Python script
5916 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5917 else pyDump << aNewElemGroup << ", ";
5918 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5919 else pyDump << aNewNodeGroup << " ] = ";
5921 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
5922 << &theNodesNot << ", "
5923 << &theAffectedElems << ", "
5924 << theElemGroupNeeded << ", "
5925 << theNodeGroupNeeded << " )";
5927 aTwoGroups[0] = aNewElemGroup._retn();
5928 aTwoGroups[1] = aNewNodeGroup._retn();
5929 return aTwoGroups._retn();
5931 SMESH_CATCH( SMESH::throwCorbaException );
5935 //================================================================================
5937 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5938 This method provided for convenience works as DoubleNodes() described above.
5939 \param theElems - list of groups of elements (edges or faces) to be replicated
5940 \param theNodesNot - list of groups of nodes not to replicated
5941 \param theShape - shape to detect affected elements (element which geometric center
5942 located on or inside shape).
5943 The replicated nodes should be associated to affected elements.
5944 \return TRUE if operation has been completed successfully, FALSE otherwise
5945 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5947 //================================================================================
5950 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5951 const SMESH::ListOfGroups& theNodesNot,
5952 GEOM::GEOM_Object_ptr theShape )
5953 throw (SALOME::SALOME_Exception)
5959 SMESHDS_Mesh* aMeshDS = getMeshDS();
5960 TIDSortedElemSet anElems, aNodes;
5961 listOfGroupToSet(theElems, aMeshDS, anElems,false );
5962 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5964 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5965 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5967 // Update Python script
5968 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5969 << &theNodesNot << ", " << theShape << " )";
5971 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5974 SMESH_CATCH( SMESH::throwCorbaException );
5978 //================================================================================
5980 \brief Identify the elements that will be affected by node duplication (actual
5981 duplication is not performed.
5982 This method is the first step of DoubleNodeElemGroupsInRegion.
5983 \param theElems - list of groups of elements (edges or faces) to be replicated
5984 \param theNodesNot - list of groups of nodes not to replicated
5985 \param theShape - shape to detect affected elements (element which geometric center
5986 located on or inside shape).
5987 The replicated nodes should be associated to affected elements.
5988 \return groups of affected elements
5989 \sa DoubleNodeElemGroupsInRegion()
5991 //================================================================================
5992 SMESH::ListOfGroups*
5993 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
5994 const SMESH::ListOfGroups& theNodesNot,
5995 GEOM::GEOM_Object_ptr theShape )
5996 throw (SALOME::SALOME_Exception)
5999 MESSAGE("AffectedElemGroupsInRegion");
6000 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6001 bool isEdgeGroup = false;
6002 bool isFaceGroup = false;
6003 bool isVolumeGroup = false;
6004 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6005 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6006 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6010 ::SMESH_MeshEditor aMeshEditor(myMesh);
6012 SMESHDS_Mesh* aMeshDS = getMeshDS();
6013 TIDSortedElemSet anElems, aNodes;
6014 listOfGroupToSet(theElems, aMeshDS, anElems, false);
6015 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6017 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6018 TIDSortedElemSet anAffected;
6019 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6022 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6027 int lg = anAffected.size();
6028 MESSAGE("lg="<< lg);
6029 SMESH::long_array_var volumeIds = new SMESH::long_array;
6030 volumeIds->length(lg);
6031 SMESH::long_array_var faceIds = new SMESH::long_array;
6032 faceIds->length(lg);
6033 SMESH::long_array_var edgeIds = new SMESH::long_array;
6034 edgeIds->length(lg);
6039 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6040 for (; eIt != anAffected.end(); ++eIt)
6042 const SMDS_MeshElement* anElem = *eIt;
6045 int elemId = anElem->GetID();
6046 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6047 volumeIds[ivol++] = elemId;
6048 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6049 faceIds[iface++] = elemId;
6050 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6051 edgeIds[iedge++] = elemId;
6053 volumeIds->length(ivol);
6054 faceIds->length(iface);
6055 edgeIds->length(iedge);
6057 aNewVolumeGroup->Add(volumeIds);
6058 aNewFaceGroup->Add(faceIds);
6059 aNewEdgeGroup->Add(edgeIds);
6060 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6061 isFaceGroup = (aNewFaceGroup->Size() > 0);
6062 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6066 if (isEdgeGroup) nbGroups++;
6067 if (isFaceGroup) nbGroups++;
6068 if (isVolumeGroup) nbGroups++;
6069 aListOfGroups->length(nbGroups);
6072 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6073 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6074 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6076 // Update Python script
6079 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6080 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6081 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6083 pyDump << this << ".AffectedElemGroupsInRegion( "
6084 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6086 return aListOfGroups._retn();
6088 SMESH_CATCH( SMESH::throwCorbaException );
6092 //================================================================================
6094 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6095 The created 2D mesh elements based on nodes of free faces of boundary volumes
6096 \return TRUE if operation has been completed successfully, FALSE otherwise
6098 //================================================================================
6100 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6101 throw (SALOME::SALOME_Exception)
6106 bool aResult = getEditor().Make2DMeshFrom3D();
6108 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6110 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6113 SMESH_CATCH( SMESH::throwCorbaException );
6117 //================================================================================
6119 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6120 * The list of groups must contain at least two groups. The groups have to be disjoint:
6121 * no common element into two different groups.
6122 * The nodes of the internal faces at the boundaries of the groups are doubled.
6123 * Optionally, the internal faces are replaced by flat elements.
6124 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6125 * The flat elements are stored in groups of volumes.
6126 * These groups are named according to the position of the group in the list:
6127 * 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.
6128 * 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.
6129 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6130 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6131 * \param theDomains - list of groups of volumes
6132 * \param createJointElems - if TRUE, create the elements
6133 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6134 * the boundary between \a theDomains and the rest mesh
6135 * \return TRUE if operation has been completed successfully, FALSE otherwise
6137 //================================================================================
6140 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6141 CORBA::Boolean createJointElems,
6142 CORBA::Boolean onAllBoundaries )
6143 throw (SALOME::SALOME_Exception)
6150 SMESHDS_Mesh* aMeshDS = getMeshDS();
6152 // MESSAGE("theDomains.length = "<<theDomains.length());
6153 if ( theDomains.length() <= 1 && !onAllBoundaries )
6154 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6156 vector<TIDSortedElemSet> domains;
6157 domains.resize( theDomains.length() );
6159 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6161 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6162 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6164 // if ( aGrp->GetType() != SMESH::VOLUME )
6165 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6166 SMESH::long_array_var anIDs = aGrp->GetIDs();
6167 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6171 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6172 // TODO publish the groups of flat elements in study
6174 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6176 // Update Python script
6177 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6178 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6180 SMESH_CATCH( SMESH::throwCorbaException );
6182 myMesh_i->CreateGroupServants(); // publish created groups if any
6187 //================================================================================
6189 * \brief Double nodes on some external faces and create flat elements.
6190 * Flat elements are mainly used by some types of mechanic calculations.
6192 * Each group of the list must be constituted of faces.
6193 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6194 * @param theGroupsOfFaces - list of groups of faces
6195 * @return TRUE if operation has been completed successfully, FALSE otherwise
6197 //================================================================================
6200 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6201 throw (SALOME::SALOME_Exception)
6206 SMESHDS_Mesh* aMeshDS = getMeshDS();
6208 vector<TIDSortedElemSet> faceGroups;
6211 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6213 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6214 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6216 TIDSortedElemSet faceGroup;
6218 faceGroups.push_back(faceGroup);
6219 SMESH::long_array_var anIDs = aGrp->GetIDs();
6220 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6224 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6225 // TODO publish the groups of flat elements in study
6227 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6229 // Update Python script
6230 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6233 SMESH_CATCH( SMESH::throwCorbaException );
6237 //================================================================================
6239 * \brief Identify all the elements around a geom shape, get the faces delimiting
6242 * Build groups of volume to remove, groups of faces to replace on the skin of the
6243 * object, groups of faces to remove inside the object, (idem edges).
6244 * Build ordered list of nodes at the border of each group of faces to replace
6245 * (to be used to build a geom subshape).
6247 //================================================================================
6249 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6250 GEOM::GEOM_Object_ptr theShape,
6251 const char* groupName,
6252 const SMESH::double_array& theNodesCoords,
6253 SMESH::array_of_long_array_out GroupsOfNodes)
6254 throw (SALOME::SALOME_Exception)
6259 std::vector<std::vector<int> > aListOfListOfNodes;
6260 ::SMESH_MeshEditor aMeshEditor( myMesh );
6262 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6263 if ( !theNodeSearcher )
6264 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6266 vector<double> nodesCoords;
6267 for (int i = 0; i < theNodesCoords.length(); i++)
6269 nodesCoords.push_back( theNodesCoords[i] );
6272 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6273 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6274 nodesCoords, aListOfListOfNodes);
6276 GroupsOfNodes = new SMESH::array_of_long_array;
6277 GroupsOfNodes->length( aListOfListOfNodes.size() );
6278 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6279 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6281 vector<int>& aListOfNodes = *llIt;
6282 vector<int>::iterator lIt = aListOfNodes.begin();;
6283 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6284 aGroup.length( aListOfNodes.size() );
6285 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6286 aGroup[ j ] = (*lIt);
6288 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6291 << ", '" << groupName << "', "
6292 << theNodesCoords << " )";
6294 SMESH_CATCH( SMESH::throwCorbaException );
6297 // issue 20749 ===================================================================
6299 * \brief Creates missing boundary elements
6300 * \param elements - elements whose boundary is to be checked
6301 * \param dimension - defines type of boundary elements to create
6302 * \param groupName - a name of group to store created boundary elements in,
6303 * "" means not to create the group
6304 * \param meshName - a name of new mesh to store created boundary elements in,
6305 * "" means not to create the new mesh
6306 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6307 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6308 * boundary elements will be copied into the new mesh
6309 * \param group - returns the create group, if any
6310 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6312 // ================================================================================
6314 SMESH::SMESH_Mesh_ptr
6315 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6316 SMESH::Bnd_Dimension dim,
6317 const char* groupName,
6318 const char* meshName,
6319 CORBA::Boolean toCopyElements,
6320 CORBA::Boolean toCopyExistingBondary,
6321 SMESH::SMESH_Group_out group)
6322 throw (SALOME::SALOME_Exception)
6327 if ( dim > SMESH::BND_1DFROM2D )
6328 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6330 SMESHDS_Mesh* aMeshDS = getMeshDS();
6332 SMESH::SMESH_Mesh_var mesh_var;
6333 SMESH::SMESH_Group_var group_var;
6337 TIDSortedElemSet elements;
6338 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6339 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6343 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6344 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6346 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6348 // group of new boundary elements
6349 SMESH_Group* smesh_group = 0;
6350 if ( strlen(groupName) )
6352 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6353 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6354 smesh_group = group_i->GetSmeshGroup();
6358 getEditor().MakeBoundaryMesh( elements,
6359 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6363 toCopyExistingBondary);
6366 smesh_mesh->GetMeshDS()->Modified();
6369 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6371 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6372 if ( mesh_var->_is_nil() )
6373 pyDump << myMesh_i->_this() << ", ";
6375 pyDump << mesh_var << ", ";
6376 if ( group_var->_is_nil() )
6377 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6379 pyDump << group_var << " = ";
6380 pyDump << this << ".MakeBoundaryMesh( "
6382 << "SMESH." << dimName[int(dim)] << ", "
6383 << "'" << groupName << "', "
6384 << "'" << meshName<< "', "
6385 << toCopyElements << ", "
6386 << toCopyExistingBondary << ")";
6388 group = group_var._retn();
6389 return mesh_var._retn();
6391 SMESH_CATCH( SMESH::throwCorbaException );
6392 return SMESH::SMESH_Mesh::_nil();
6395 //================================================================================
6397 * \brief Creates missing boundary elements
6398 * \param dimension - defines type of boundary elements to create
6399 * \param groupName - a name of group to store all boundary elements in,
6400 * "" means not to create the group
6401 * \param meshName - a name of a new mesh, which is a copy of the initial
6402 * mesh + created boundary elements; "" means not to create the new mesh
6403 * \param toCopyAll - if true, the whole initial mesh will be copied into
6404 * the new mesh else only boundary elements will be copied into the new mesh
6405 * \param groups - optional groups of elements to make boundary around
6406 * \param mesh - returns the mesh where elements were added to
6407 * \param group - returns the created group, if any
6408 * \retval long - number of added boundary elements
6410 //================================================================================
6412 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6413 const char* groupName,
6414 const char* meshName,
6415 CORBA::Boolean toCopyAll,
6416 const SMESH::ListOfIDSources& groups,
6417 SMESH::SMESH_Mesh_out mesh,
6418 SMESH::SMESH_Group_out group)
6419 throw (SALOME::SALOME_Exception)
6424 if ( dim > SMESH::BND_1DFROM2D )
6425 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6427 // separate groups belonging to this and other mesh
6428 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6429 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6430 groupsOfThisMesh->length( groups.length() );
6431 groupsOfOtherMesh->length( groups.length() );
6432 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6433 for ( int i = 0; i < groups.length(); ++i )
6435 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6436 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6437 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6439 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6440 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6441 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6443 groupsOfThisMesh->length( nbGroups );
6444 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6449 if ( nbGroupsOfOtherMesh > 0 )
6451 // process groups belonging to another mesh
6452 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6453 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6454 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6455 groupsOfOtherMesh, mesh, group );
6458 SMESH::SMESH_Mesh_var mesh_var;
6459 SMESH::SMESH_Group_var group_var;
6462 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6463 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6467 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6469 /*toCopyGroups=*/false,
6470 /*toKeepIDs=*/true);
6472 mesh_var = makeMesh(meshName);
6474 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6475 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6478 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6479 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6481 // group of boundary elements
6482 SMESH_Group* smesh_group = 0;
6483 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6484 if ( strlen(groupName) )
6486 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6487 group_var = mesh_i->CreateGroup( groupType, groupName );
6488 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6489 smesh_group = group_i->GetSmeshGroup();
6492 TIDSortedElemSet elements;
6494 if ( groups.length() > 0 )
6496 for ( int i = 0; i < nbGroups; ++i )
6499 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6501 SMESH::Bnd_Dimension bdim =
6502 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6503 nbAdded += getEditor().MakeBoundaryMesh( elements,
6504 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6507 /*toCopyElements=*/false,
6508 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6509 /*toAddExistingBondary=*/true,
6510 /*aroundElements=*/true);
6516 nbAdded += getEditor().MakeBoundaryMesh( elements,
6517 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6520 /*toCopyElements=*/false,
6521 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6522 /*toAddExistingBondary=*/true);
6524 tgtMesh->GetMeshDS()->Modified();
6526 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6528 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6529 pyDump << "nbAdded, ";
6530 if ( mesh_var->_is_nil() )
6531 pyDump << myMesh_i->_this() << ", ";
6533 pyDump << mesh_var << ", ";
6534 if ( group_var->_is_nil() )
6535 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6537 pyDump << group_var << " = ";
6538 pyDump << this << ".MakeBoundaryElements( "
6539 << "SMESH." << dimName[int(dim)] << ", "
6540 << "'" << groupName << "', "
6541 << "'" << meshName<< "', "
6542 << toCopyAll << ", "
6545 mesh = mesh_var._retn();
6546 group = group_var._retn();
6549 SMESH_CATCH( SMESH::throwCorbaException );