1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
46 #include "SMDS_SetIterator.hxx"
47 #include "SMDS_VolumeTool.hxx"
48 #include "SMESHDS_Group.hxx"
49 #include "SMESHDS_GroupOnGeom.hxx"
50 #include "SMESH_ControlsDef.hxx"
51 #include "SMESH_Filter_i.hxx"
52 #include "SMESH_Gen_i.hxx"
53 #include "SMESH_Group.hxx"
54 #include "SMESH_Group_i.hxx"
55 #include "SMESH_MeshAlgos.hxx"
56 #include "SMESH_MeshPartDS.hxx"
57 #include "SMESH_MesherHelper.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMeshEventListener.hxx"
60 #include "SMESH_subMesh_i.hxx"
62 #include <utilities.h>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <Utils_CorbaException.hxx>
65 #include <SALOMEDS_wrap.hxx>
66 #include <SALOME_GenericObj_i.hh>
67 #include <Basics_OCCTVersion.hxx>
69 #include <BRepAdaptor_Surface.hxx>
70 #include <BRep_Tool.hxx>
71 #include <TopExp_Explorer.hxx>
73 #include <TopoDS_Edge.hxx>
74 #include <TopoDS_Face.hxx>
79 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
83 #include <Standard_Failure.hxx>
86 #include <Standard_ErrorHandler.hxx>
92 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
94 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
97 using SMESH::TPythonDump;
100 namespace MeshEditor_I {
102 //=============================================================================
104 * \brief Mesh to apply modifications for preview purposes
106 //=============================================================================
108 struct TPreviewMesh: public SMESH_Mesh
110 SMDSAbs_ElementType myPreviewType; // type to show
112 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
113 _isShapeToMesh = (_id =_studyId = 0);
114 _myMeshDS = new SMESHDS_Mesh( _id, true );
115 myPreviewType = previewElements;
117 //!< Copy a set of elements
118 void Copy(const TIDSortedElemSet & theElements,
119 TIDSortedElemSet& theCopyElements,
120 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
121 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
123 // loop on theIDsOfElements
124 TIDSortedElemSet::const_iterator eIt = theElements.begin();
125 for ( ; eIt != theElements.end(); ++eIt )
127 const SMDS_MeshElement* anElem = *eIt;
128 if ( !anElem ) continue;
129 SMDSAbs_ElementType type = anElem->GetType();
130 if ( type == theAvoidType ||
131 ( theSelectType != SMDSAbs_All && type != theSelectType ))
133 const SMDS_MeshElement* anElemCopy;
134 if ( type == SMDSAbs_Node)
135 anElemCopy = Copy( cast2Node(anElem) );
137 anElemCopy = Copy( anElem );
139 theCopyElements.insert( theCopyElements.end(), anElemCopy );
143 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
145 // copy element nodes
146 int anElemNbNodes = anElem->NbNodes();
147 vector< int > anElemNodesID( anElemNbNodes ) ;
148 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
149 for ( int i = 0; itElemNodes->more(); i++)
151 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
153 anElemNodesID[i] = anElemNode->GetID();
156 // creates a corresponding element on copied nodes
157 ::SMESH_MeshEditor::ElemFeatures elemType;
158 elemType.Init( anElem, /*basicOnly=*/false );
159 elemType.SetID( anElem->GetID() );
160 SMDS_MeshElement* anElemCopy =
161 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
165 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
167 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
168 anElemNode->GetID());
172 GetMeshDS()->ClearMesh();
174 void Remove( SMDSAbs_ElementType type )
176 SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator( type );
177 while ( eIt->more() )
178 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
180 };// struct TPreviewMesh
182 static SMESH_NodeSearcher * theNodeSearcher = 0;
183 static SMESH_ElementSearcher * theElementSearcher = 0;
185 //=============================================================================
187 * \brief Deleter of theNodeSearcher at any compute event 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 ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
289 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
291 aMap.insert( aMap.end(), elem );
294 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
295 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
297 aMap.insert( aMap.end(), elem );
301 //================================================================================
303 * \brief Retrieve nodes from SMESH_IDSource
305 //================================================================================
307 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
308 const SMESHDS_Mesh* theMeshDS,
309 TIDSortedNodeSet& theNodeSet)
312 if ( CORBA::is_nil( theObject ) )
314 SMESH::array_of_ElementType_var types = theObject->GetTypes();
315 SMESH::long_array_var aElementsId = theObject->GetIDs();
316 if ( types->length() == 1 && types[0] == SMESH::NODE)
318 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
319 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
320 theNodeSet.insert( theNodeSet.end(), n);
322 else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
324 SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
325 while ( nIt->more( ))
326 if ( const SMDS_MeshElement * elem = nIt->next() )
327 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
331 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
332 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
333 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
337 //================================================================================
339 * \brief Returns elements connected to the given elements
341 //================================================================================
343 void getElementsAround(const TIDSortedElemSet& theElements,
344 const SMESHDS_Mesh* theMeshDS,
345 TIDSortedElemSet& theElementsAround)
347 if ( theElements.empty() ) return;
349 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
350 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
352 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
353 return; // all the elements are in theElements
356 elemType = SMDSAbs_All;
358 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
360 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
361 for ( ; elemIt != theElements.end(); ++elemIt )
363 const SMDS_MeshElement* e = *elemIt;
364 int i = e->NbCornerNodes();
367 const SMDS_MeshNode* n = e->GetNode( i );
368 if ( !isNodeChecked[ n->GetID() ])
370 isNodeChecked[ n->GetID() ] = true;
371 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
372 while ( invIt->more() )
374 const SMDS_MeshElement* elemAround = invIt->next();
375 if ( !theElements.count( elemAround ))
376 theElementsAround.insert( elemAround );
383 //================================================================================
385 * \brief Return a string used to detect change of mesh part on which theElementSearcher
386 * is going to be used
388 //================================================================================
390 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
392 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
393 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
394 // take into account passible group modification
395 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
396 partIOR += SMESH_Comment( type );
400 } // namespace MeshEditor_I
402 using namespace MeshEditor_I;
404 //=============================================================================
408 //=============================================================================
410 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
412 myMesh( &theMesh->GetImpl() ),
414 myIsPreviewMode ( isPreview ),
420 //================================================================================
424 //================================================================================
426 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
428 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
429 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
430 poa->deactivate_object(anObjectId.in());
432 //deleteAuxIDSources();
433 delete myPreviewMesh; myPreviewMesh = 0;
434 delete myPreviewEditor; myPreviewEditor = 0;
437 //================================================================================
439 * \brief Returns the mesh
441 //================================================================================
443 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
445 return myMesh_i->_this();
448 //================================================================================
450 * \brief Clear members
452 //================================================================================
454 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
456 if ( myIsPreviewMode ) {
457 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
460 if ( deleteSearchers )
461 TSearchersDeleter::Delete();
463 getEditor().GetError().reset();
464 getEditor().ClearLastCreated();
467 //================================================================================
469 * \brief Increment mesh modif time and optionally record that the performed
470 * modification may influence 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 ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
798 IdList.push_back( IDsOfElements[i] );
800 // Update Python script
801 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
804 bool ret = getEditor().Remove( IdList, false );
806 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
809 SMESH_CATCH( SMESH::throwCorbaException );
813 //=============================================================================
817 //=============================================================================
819 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
820 throw (SALOME::SALOME_Exception)
826 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
827 IdList.push_back( IDsOfNodes[i] );
829 // Update Python script
830 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
832 bool ret = getEditor().Remove( IdList, true );
834 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
837 SMESH_CATCH( SMESH::throwCorbaException );
841 //=============================================================================
845 //=============================================================================
847 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
848 throw (SALOME::SALOME_Exception)
853 // Update Python script
854 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
856 // Create filter to find all orphan nodes
857 SMESH::Controls::Filter::TIdSequence seq;
858 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
859 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
861 // remove orphan nodes (if there are any)
862 list< int > IdList( seq.begin(), seq.end() );
864 int nbNodesBefore = myMesh->NbNodes();
865 getEditor().Remove( IdList, true );
866 int nbNodesAfter = myMesh->NbNodes();
868 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
869 return nbNodesBefore - nbNodesAfter;
871 SMESH_CATCH( SMESH::throwCorbaException );
875 //=============================================================================
879 //=============================================================================
881 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
882 throw (SALOME::SALOME_Exception)
887 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
889 // Update Python script
890 TPythonDump() << "nodeID = " << this << ".AddNode( "
891 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
893 declareMeshModified( /*isReComputeSafe=*/false );
896 SMESH_CATCH( SMESH::throwCorbaException );
900 //=============================================================================
902 * Create 0D element on the given node.
904 //=============================================================================
906 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
907 throw (SALOME::SALOME_Exception)
912 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
913 SMDS_MeshElement* elem = getMeshDS()->Add0DElement(aNode);
915 // Update Python script
916 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
918 declareMeshModified( /*isReComputeSafe=*/false );
920 return elem ? elem->GetID() : 0;
922 SMESH_CATCH( SMESH::throwCorbaException );
926 //=============================================================================
928 * Create a ball element on the given node.
930 //=============================================================================
932 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
933 throw (SALOME::SALOME_Exception)
938 if ( diameter < std::numeric_limits<double>::min() )
939 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
941 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
942 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
944 // Update Python script
945 TPythonDump() << "ballElem = "
946 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
948 declareMeshModified( /*isReComputeSafe=*/false );
949 return elem ? elem->GetID() : 0;
951 SMESH_CATCH( SMESH::throwCorbaException );
955 //=============================================================================
957 * Create an edge, either linear and quadratic (this is determed
958 * by number of given nodes, two or three)
960 //=============================================================================
962 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
963 throw (SALOME::SALOME_Exception)
968 int NbNodes = IDsOfNodes.length();
969 SMDS_MeshElement* elem = 0;
972 CORBA::Long index1 = IDsOfNodes[0];
973 CORBA::Long index2 = IDsOfNodes[1];
974 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
975 getMeshDS()->FindNode(index2));
977 // Update Python script
978 TPythonDump() << "edge = " << this << ".AddEdge([ "
979 << index1 << ", " << index2 <<" ])";
982 CORBA::Long n1 = IDsOfNodes[0];
983 CORBA::Long n2 = IDsOfNodes[1];
984 CORBA::Long n12 = IDsOfNodes[2];
985 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
986 getMeshDS()->FindNode(n2),
987 getMeshDS()->FindNode(n12));
988 // Update Python script
989 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
990 <<n1<<", "<<n2<<", "<<n12<<" ])";
993 declareMeshModified( /*isReComputeSafe=*/false );
994 return elem ? elem->GetID() : 0;
996 SMESH_CATCH( SMESH::throwCorbaException );
1000 //=============================================================================
1004 //=============================================================================
1006 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1007 throw (SALOME::SALOME_Exception)
1012 int NbNodes = IDsOfNodes.length();
1018 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1019 for (int i = 0; i < NbNodes; i++)
1020 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1022 SMDS_MeshElement* elem = 0;
1024 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1025 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1026 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1027 nodes[4], nodes[5]); break;
1028 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1029 nodes[4], nodes[5], nodes[6]); break;
1030 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1031 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1032 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1033 nodes[4], nodes[5], nodes[6], nodes[7],
1035 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1038 // Update Python script
1039 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1041 declareMeshModified( /*isReComputeSafe=*/false );
1043 return elem ? elem->GetID() : 0;
1045 SMESH_CATCH( SMESH::throwCorbaException );
1049 //=============================================================================
1053 //=============================================================================
1055 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1056 throw (SALOME::SALOME_Exception)
1061 int NbNodes = IDsOfNodes.length();
1062 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1063 for (int i = 0; i < NbNodes; i++)
1064 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1067 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1069 // Update Python script
1070 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1072 declareMeshModified( /*isReComputeSafe=*/false );
1073 return elem ? elem->GetID() : 0;
1075 SMESH_CATCH( SMESH::throwCorbaException );
1079 //=============================================================================
1081 * AddQuadPolygonalFace
1083 //=============================================================================
1085 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1086 throw (SALOME::SALOME_Exception)
1091 int NbNodes = IDsOfNodes.length();
1092 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1093 for (int i = 0; i < NbNodes; i++)
1094 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1096 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1098 // Update Python script
1099 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1101 declareMeshModified( /*isReComputeSafe=*/false );
1102 return elem ? elem->GetID() : 0;
1104 SMESH_CATCH( SMESH::throwCorbaException );
1108 //=============================================================================
1110 * Create volume, either linear and quadratic (this is determed
1111 * by number of given nodes)
1113 //=============================================================================
1115 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1116 throw (SALOME::SALOME_Exception)
1121 int NbNodes = IDsOfNodes.length();
1122 vector< const SMDS_MeshNode*> n(NbNodes);
1123 for(int i=0;i<NbNodes;i++)
1124 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1126 SMDS_MeshElement* elem = 0;
1129 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1130 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1131 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1132 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1133 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1134 n[6],n[7],n[8],n[9]);
1136 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1137 n[6],n[7],n[8],n[9],n[10],n[11]);
1139 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1140 n[7],n[8],n[9],n[10],n[11],n[12]);
1142 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1143 n[9],n[10],n[11],n[12],n[13],n[14]);
1145 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1146 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1147 n[15],n[16],n[17],n[18],n[19]);
1149 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1150 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1151 n[15],n[16],n[17],n[18],n[19],
1152 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1156 // Update Python script
1157 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1159 declareMeshModified( /*isReComputeSafe=*/false );
1160 return elem ? elem->GetID() : 0;
1162 SMESH_CATCH( SMESH::throwCorbaException );
1166 //=============================================================================
1168 * AddPolyhedralVolume
1170 //=============================================================================
1171 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1172 const SMESH::long_array & Quantities)
1173 throw (SALOME::SALOME_Exception)
1178 int NbNodes = IDsOfNodes.length();
1179 std::vector<const SMDS_MeshNode*> n (NbNodes);
1180 for (int i = 0; i < NbNodes; i++)
1182 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1183 if (!aNode) return 0;
1187 int NbFaces = Quantities.length();
1188 std::vector<int> q (NbFaces);
1189 for (int j = 0; j < NbFaces; j++)
1190 q[j] = Quantities[j];
1192 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1194 // Update Python script
1195 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1196 << IDsOfNodes << ", " << Quantities << " )";
1198 declareMeshModified( /*isReComputeSafe=*/false );
1199 return elem ? elem->GetID() : 0;
1201 SMESH_CATCH( SMESH::throwCorbaException );
1205 //=============================================================================
1207 * AddPolyhedralVolumeByFaces
1209 //=============================================================================
1211 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1212 throw (SALOME::SALOME_Exception)
1217 int NbFaces = IdsOfFaces.length();
1218 std::vector<const SMDS_MeshNode*> poly_nodes;
1219 std::vector<int> quantities (NbFaces);
1221 for (int i = 0; i < NbFaces; i++) {
1222 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1223 quantities[i] = aFace->NbNodes();
1225 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1226 while (It->more()) {
1227 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1231 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1233 // Update Python script
1234 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1235 << IdsOfFaces << " )";
1237 declareMeshModified( /*isReComputeSafe=*/false );
1238 return elem ? elem->GetID() : 0;
1240 SMESH_CATCH( SMESH::throwCorbaException );
1244 //=============================================================================
1246 // \brief Create 0D elements on all nodes of the given object except those
1247 // nodes on which a 0D element already exists.
1248 // \param theObject object on whose nodes 0D elements will be created.
1249 // \param theGroupName optional name of a group to add 0D elements created
1250 // and/or found on nodes of \a theObject.
1251 // \return an object (a new group or a temporary SMESH_IDSource) holding
1252 // ids of new and/or found 0D elements.
1254 //=============================================================================
1256 SMESH::SMESH_IDSource_ptr
1257 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1258 const char* theGroupName)
1259 throw (SALOME::SALOME_Exception)
1264 SMESH::SMESH_IDSource_var result;
1267 TIDSortedElemSet elements, elems0D;
1268 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1269 getEditor().Create0DElementsOnAllNodes( elements, elems0D );
1271 SMESH::long_array_var newElems = new SMESH::long_array;
1272 newElems->length( elems0D.size() );
1273 TIDSortedElemSet::iterator eIt = elems0D.begin();
1274 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1275 newElems[ i ] = (*eIt)->GetID();
1277 SMESH::SMESH_GroupBase_var groupToFill;
1278 if ( theGroupName && strlen( theGroupName ))
1280 // Get existing group named theGroupName
1281 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1282 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1283 SMESH::SMESH_GroupBase_var group = groups[i];
1284 if ( !group->_is_nil() ) {
1285 CORBA::String_var name = group->GetName();
1286 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1287 groupToFill = group;
1292 if ( groupToFill->_is_nil() )
1293 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1294 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1295 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1298 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1300 group_i->Add( newElems );
1301 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1302 pyDump << groupToFill;
1306 result = MakeIDSource( newElems, SMESH::ELEM0D );
1307 pyDump << "elem0DIDs";
1310 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1311 << theObject << ", '" << theGroupName << "' )";
1313 return result._retn();
1315 SMESH_CATCH( SMESH::throwCorbaException );
1319 //=============================================================================
1321 * \brief Bind a node to a vertex
1322 * \param NodeID - node ID
1323 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1324 * \retval boolean - false if NodeID or VertexID is invalid
1326 //=============================================================================
1328 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1329 throw (SALOME::SALOME_Exception)
1333 SMESHDS_Mesh * mesh = getMeshDS();
1334 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1336 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1338 if ( mesh->MaxShapeIndex() < VertexID )
1339 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1341 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1342 if ( shape.ShapeType() != TopAbs_VERTEX )
1343 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1345 mesh->SetNodeOnVertex( node, VertexID );
1347 myMesh->SetIsModified( true );
1349 SMESH_CATCH( SMESH::throwCorbaException );
1352 //=============================================================================
1354 * \brief Store node position on an edge
1355 * \param NodeID - node ID
1356 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1357 * \param paramOnEdge - parameter on edge where the node is located
1358 * \retval boolean - false if any parameter is invalid
1360 //=============================================================================
1362 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1363 CORBA::Double paramOnEdge)
1364 throw (SALOME::SALOME_Exception)
1368 SMESHDS_Mesh * mesh = getMeshDS();
1369 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1371 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1373 if ( mesh->MaxShapeIndex() < EdgeID )
1374 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1376 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1377 if ( shape.ShapeType() != TopAbs_EDGE )
1378 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1381 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1382 if ( paramOnEdge < f || paramOnEdge > l )
1383 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1385 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1387 myMesh->SetIsModified( true );
1389 SMESH_CATCH( SMESH::throwCorbaException );
1392 //=============================================================================
1394 * \brief Store node position on a face
1395 * \param NodeID - node ID
1396 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1397 * \param u - U parameter on face where the node is located
1398 * \param v - V parameter on face where the node is located
1399 * \retval boolean - false if any parameter is invalid
1401 //=============================================================================
1403 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1404 CORBA::Double u, CORBA::Double v)
1405 throw (SALOME::SALOME_Exception)
1408 SMESHDS_Mesh * mesh = getMeshDS();
1409 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1411 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1413 if ( mesh->MaxShapeIndex() < FaceID )
1414 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1416 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1417 if ( shape.ShapeType() != TopAbs_FACE )
1418 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1420 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1421 bool isOut = ( u < surf.FirstUParameter() ||
1422 u > surf.LastUParameter() ||
1423 v < surf.FirstVParameter() ||
1424 v > surf.LastVParameter() );
1428 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1429 << " u( " << surf.FirstUParameter()
1430 << "," << surf.LastUParameter()
1431 << ") v( " << surf.FirstVParameter()
1432 << "," << surf.LastVParameter() << ")" );
1434 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1437 mesh->SetNodeOnFace( node, FaceID, u, v );
1438 myMesh->SetIsModified( true );
1440 SMESH_CATCH( SMESH::throwCorbaException );
1443 //=============================================================================
1445 * \brief Bind a node to a solid
1446 * \param NodeID - node ID
1447 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1448 * \retval boolean - false if NodeID or SolidID is invalid
1450 //=============================================================================
1452 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1453 throw (SALOME::SALOME_Exception)
1456 SMESHDS_Mesh * mesh = getMeshDS();
1457 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1459 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1461 if ( mesh->MaxShapeIndex() < SolidID )
1462 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1464 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1465 if ( shape.ShapeType() != TopAbs_SOLID &&
1466 shape.ShapeType() != TopAbs_SHELL)
1467 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1469 mesh->SetNodeInVolume( node, SolidID );
1471 SMESH_CATCH( SMESH::throwCorbaException );
1474 //=============================================================================
1476 * \brief Bind an element to a shape
1477 * \param ElementID - element ID
1478 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1480 //=============================================================================
1482 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1483 CORBA::Long ShapeID)
1484 throw (SALOME::SALOME_Exception)
1487 SMESHDS_Mesh * mesh = getMeshDS();
1488 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1490 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1492 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1493 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1495 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1496 if ( shape.ShapeType() != TopAbs_EDGE &&
1497 shape.ShapeType() != TopAbs_FACE &&
1498 shape.ShapeType() != TopAbs_SOLID &&
1499 shape.ShapeType() != TopAbs_SHELL )
1500 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1502 mesh->SetMeshElementOnShape( elem, ShapeID );
1504 myMesh->SetIsModified( true );
1506 SMESH_CATCH( SMESH::throwCorbaException );
1509 //=============================================================================
1513 //=============================================================================
1515 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1516 CORBA::Long NodeID2)
1517 throw (SALOME::SALOME_Exception)
1522 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1523 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1527 // Update Python script
1528 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1529 << NodeID1 << ", " << NodeID2 << " )";
1531 int ret = getEditor().InverseDiag ( n1, n2 );
1533 declareMeshModified( /*isReComputeSafe=*/false );
1536 SMESH_CATCH( SMESH::throwCorbaException );
1540 //=============================================================================
1544 //=============================================================================
1546 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1547 CORBA::Long NodeID2)
1548 throw (SALOME::SALOME_Exception)
1553 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1554 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1558 // Update Python script
1559 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1560 << NodeID1 << ", " << NodeID2 << " )";
1563 bool stat = getEditor().DeleteDiag ( n1, n2 );
1565 declareMeshModified( /*isReComputeSafe=*/!stat );
1569 SMESH_CATCH( SMESH::throwCorbaException );
1573 //=============================================================================
1577 //=============================================================================
1579 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1580 throw (SALOME::SALOME_Exception)
1585 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1587 CORBA::Long index = IDsOfElements[i];
1588 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1590 getEditor().Reorient( elem );
1592 // Update Python script
1593 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1595 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1598 SMESH_CATCH( SMESH::throwCorbaException );
1602 //=============================================================================
1606 //=============================================================================
1608 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1609 throw (SALOME::SALOME_Exception)
1614 TPythonDump aTPythonDump; // suppress dump in Reorient()
1616 prepareIdSource( theObject );
1618 SMESH::long_array_var anElementsId = theObject->GetIDs();
1619 CORBA::Boolean isDone = Reorient(anElementsId);
1621 // Update Python script
1622 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1624 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1627 SMESH_CATCH( SMESH::throwCorbaException );
1631 //=======================================================================
1632 //function : Reorient2D
1633 //purpose : Reorient faces contained in \a the2Dgroup.
1634 // the2Dgroup - the mesh or its part to reorient
1635 // theDirection - desired direction of normal of \a theFace
1636 // theFace - ID of face whose orientation is checked.
1637 // It can be < 1 then \a thePoint is used to find a face.
1638 // thePoint - is used to find a face if \a theFace < 1.
1639 // return number of reoriented elements.
1640 //=======================================================================
1642 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1643 const SMESH::DirStruct& theDirection,
1644 CORBA::Long theFace,
1645 const SMESH::PointStruct& thePoint)
1646 throw (SALOME::SALOME_Exception)
1649 initData(/*deleteSearchers=*/false);
1651 TIDSortedElemSet elements;
1652 IDSource_Error error;
1653 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1654 if ( error == IDSource_EMPTY )
1656 if ( error == IDSource_INVALID )
1657 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1660 const SMDS_MeshElement* face = 0;
1663 face = getMeshDS()->FindElement( theFace );
1665 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1666 if ( face->GetType() != SMDSAbs_Face )
1667 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1671 // create theElementSearcher if needed
1672 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1673 if ( !theElementSearcher )
1675 if ( elements.empty() ) // search in the whole mesh
1677 if ( myMesh->NbFaces() == 0 )
1678 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1680 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1684 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1685 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1687 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1691 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1692 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1695 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1696 if ( !elements.empty() && !elements.count( face ))
1697 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1700 const SMESH::PointStruct * P = &theDirection.PS;
1701 gp_Vec dirVec( P->x, P->y, P->z );
1702 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1703 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1705 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1708 declareMeshModified( /*isReComputeSafe=*/false );
1710 TPythonDump() << this << ".Reorient2D( "
1711 << the2Dgroup << ", "
1712 << theDirection << ", "
1714 << thePoint << " )";
1718 SMESH_CATCH( SMESH::throwCorbaException );
1722 //=======================================================================
1723 //function : Reorient2DBy3D
1724 //purpose : Reorient faces basing on orientation of adjacent volumes.
1725 //=======================================================================
1727 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1728 SMESH::SMESH_IDSource_ptr volumeGroup,
1729 CORBA::Boolean outsideNormal)
1730 throw (SALOME::SALOME_Exception)
1735 TIDSortedElemSet volumes;
1736 IDSource_Error volsError;
1737 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1740 for ( size_t i = 0; i < faceGroups.length(); ++i )
1742 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1744 TIDSortedElemSet faces;
1745 IDSource_Error error;
1746 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1747 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1748 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1749 if ( error == IDSource_OK && volsError != IDSource_OK )
1750 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1752 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1754 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1759 declareMeshModified( /*isReComputeSafe=*/false );
1761 TPythonDump() << this << ".Reorient2DBy3D( "
1762 << faceGroups << ", "
1763 << volumeGroup << ", "
1764 << outsideNormal << " )";
1768 SMESH_CATCH( SMESH::throwCorbaException );
1772 //=============================================================================
1774 * \brief Fuse neighbour triangles into quadrangles.
1776 //=============================================================================
1778 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1779 SMESH::NumericalFunctor_ptr Criterion,
1780 CORBA::Double MaxAngle)
1781 throw (SALOME::SALOME_Exception)
1786 SMESHDS_Mesh* aMesh = getMeshDS();
1787 TIDSortedElemSet faces,copyFaces;
1788 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1789 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1790 TIDSortedElemSet* workElements = & faces;
1792 if ( myIsPreviewMode ) {
1793 SMDSAbs_ElementType select = SMDSAbs_Face;
1794 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1795 workElements = & copyFaces;
1798 SMESH::NumericalFunctor_i* aNumericalFunctor =
1799 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1800 SMESH::Controls::NumericalFunctorPtr aCrit;
1801 if ( !aNumericalFunctor )
1802 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1804 aCrit = aNumericalFunctor->GetNumericalFunctor();
1806 if ( !myIsPreviewMode ) {
1807 // Update Python script
1808 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1809 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1812 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1814 declareMeshModified( /*isReComputeSafe=*/!stat );
1817 SMESH_CATCH( SMESH::throwCorbaException );
1821 //=============================================================================
1823 * \brief Fuse neighbour triangles into quadrangles.
1825 //=============================================================================
1827 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1828 SMESH::NumericalFunctor_ptr Criterion,
1829 CORBA::Double MaxAngle)
1830 throw (SALOME::SALOME_Exception)
1835 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1837 prepareIdSource( theObject );
1838 SMESH::long_array_var anElementsId = theObject->GetIDs();
1839 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1841 if ( !myIsPreviewMode ) {
1842 SMESH::NumericalFunctor_i* aNumericalFunctor =
1843 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1845 // Update Python script
1846 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1847 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1852 SMESH_CATCH( SMESH::throwCorbaException );
1856 //=============================================================================
1858 * \brief Split quadrangles into triangles.
1860 //=============================================================================
1862 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1863 SMESH::NumericalFunctor_ptr Criterion)
1864 throw (SALOME::SALOME_Exception)
1869 SMESHDS_Mesh* aMesh = getMeshDS();
1870 TIDSortedElemSet faces;
1871 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1873 SMESH::NumericalFunctor_i* aNumericalFunctor =
1874 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1875 SMESH::Controls::NumericalFunctorPtr aCrit;
1876 if ( !aNumericalFunctor )
1877 aCrit.reset( new SMESH::Controls::AspectRatio() );
1879 aCrit = aNumericalFunctor->GetNumericalFunctor();
1882 // Update Python script
1883 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1885 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1887 declareMeshModified( /*isReComputeSafe=*/false );
1890 SMESH_CATCH( SMESH::throwCorbaException );
1894 //=============================================================================
1896 * \brief Split quadrangles into triangles.
1898 //=============================================================================
1900 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1901 SMESH::NumericalFunctor_ptr Criterion)
1902 throw (SALOME::SALOME_Exception)
1907 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1909 prepareIdSource( theObject );
1910 SMESH::long_array_var anElementsId = theObject->GetIDs();
1911 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1913 SMESH::NumericalFunctor_i* aNumericalFunctor =
1914 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1916 // Update Python script
1917 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1919 declareMeshModified( /*isReComputeSafe=*/false );
1922 SMESH_CATCH( SMESH::throwCorbaException );
1926 //================================================================================
1928 * \brief Split each of quadrangles into 4 triangles.
1929 * \param [in] theObject - theQuads Container of quadrangles to split.
1931 //================================================================================
1933 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1934 throw (SALOME::SALOME_Exception)
1939 TIDSortedElemSet faces;
1940 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1942 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1944 getEditor().QuadTo4Tri( faces );
1945 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1947 SMESH_CATCH( SMESH::throwCorbaException );
1950 //=============================================================================
1952 * \brief Split quadrangles into triangles.
1954 //=============================================================================
1956 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1957 CORBA::Boolean Diag13)
1958 throw (SALOME::SALOME_Exception)
1963 SMESHDS_Mesh* aMesh = getMeshDS();
1964 TIDSortedElemSet faces;
1965 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1967 // Update Python script
1968 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1969 << IDsOfElements << ", " << Diag13 << " )";
1971 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1973 declareMeshModified( /*isReComputeSafe=*/ !stat );
1976 SMESH_CATCH( SMESH::throwCorbaException );
1980 //=============================================================================
1982 * \brief Split quadrangles into triangles.
1984 //=============================================================================
1986 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1987 CORBA::Boolean Diag13)
1988 throw (SALOME::SALOME_Exception)
1993 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
1995 prepareIdSource( theObject );
1996 SMESH::long_array_var anElementsId = theObject->GetIDs();
1997 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1999 // Update Python script
2000 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2001 << theObject << ", " << Diag13 << " )";
2003 declareMeshModified( /*isReComputeSafe=*/!isDone );
2006 SMESH_CATCH( SMESH::throwCorbaException );
2011 //=============================================================================
2013 * Find better splitting of the given quadrangle.
2014 * \param IDOfQuad ID of the quadrangle to be splitted.
2015 * \param Criterion A criterion to choose a diagonal for splitting.
2016 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2017 * diagonal is better, 0 if error occurs.
2019 //=============================================================================
2021 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2022 SMESH::NumericalFunctor_ptr Criterion)
2023 throw (SALOME::SALOME_Exception)
2028 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2029 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2031 SMESH::NumericalFunctor_i* aNumericalFunctor =
2032 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2033 SMESH::Controls::NumericalFunctorPtr aCrit;
2034 if (aNumericalFunctor)
2035 aCrit = aNumericalFunctor->GetNumericalFunctor();
2037 aCrit.reset(new SMESH::Controls::AspectRatio());
2039 int id = getEditor().BestSplit(quad, aCrit);
2040 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2044 SMESH_CATCH( SMESH::throwCorbaException );
2048 //================================================================================
2050 * \brief Split volumic elements into tetrahedrons
2052 //================================================================================
2054 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2055 CORBA::Short methodFlags)
2056 throw (SALOME::SALOME_Exception)
2061 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2062 const int noneFacet = -1;
2063 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2064 while( volIt->more() )
2065 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2067 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2068 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2070 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2071 << elems << ", " << methodFlags << " )";
2073 SMESH_CATCH( SMESH::throwCorbaException );
2076 //================================================================================
2078 * \brief Split hexahedra into triangular prisms
2079 * \param elems - elements to split
2080 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2081 * to split into triangles
2082 * \param methodFlags - flags passing splitting method:
2083 * 1 - split the hexahedron into 2 prisms
2084 * 2 - split the hexahedron into 4 prisms
2086 //================================================================================
2088 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2089 const SMESH::PointStruct & startHexPoint,
2090 const SMESH::DirStruct& facetToSplitNormal,
2091 CORBA::Short methodFlags,
2092 CORBA::Boolean allDomains)
2093 throw (SALOME::SALOME_Exception)
2097 prepareIdSource( elems );
2099 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2102 gp_Dir( facetToSplitNormal.PS.x,
2103 facetToSplitNormal.PS.y,
2104 facetToSplitNormal.PS.z ));
2105 TIDSortedElemSet elemSet;
2106 SMESH::long_array_var anElementsId = elems->GetIDs();
2107 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2108 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2110 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2111 while ( !elemSet.empty() )
2113 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2117 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2118 for ( ; ef != elemFacets.end(); ++ef )
2119 elemSet.erase( ef->first );
2122 if ( methodFlags == 2 )
2123 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2125 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2127 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2128 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2130 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2132 << startHexPoint << ", "
2133 << facetToSplitNormal<< ", "
2134 << methodFlags<< ", "
2135 << allDomains << " )";
2137 SMESH_CATCH( SMESH::throwCorbaException );
2140 //================================================================================
2142 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2143 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2144 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2145 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2146 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2147 * will be split in order to keep the mesh conformal.
2148 * \param elems - elements to split
2150 //================================================================================
2152 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2153 throw (SALOME::SALOME_Exception)
2158 TIDSortedElemSet elemSet;
2159 for ( size_t i = 0; i < theElems.length(); ++i )
2161 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2162 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2163 if ( mesh->GetId() != myMesh_i->GetId() )
2164 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2166 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2168 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2170 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2172 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2173 << theElems << " )";
2175 SMESH_CATCH( SMESH::throwCorbaException );
2178 //=======================================================================
2181 //=======================================================================
2184 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2185 const SMESH::long_array & IDsOfFixedNodes,
2186 CORBA::Long MaxNbOfIterations,
2187 CORBA::Double MaxAspectRatio,
2188 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2189 throw (SALOME::SALOME_Exception)
2191 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2192 MaxAspectRatio, Method, false );
2196 //=======================================================================
2197 //function : SmoothParametric
2199 //=======================================================================
2202 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2203 const SMESH::long_array & IDsOfFixedNodes,
2204 CORBA::Long MaxNbOfIterations,
2205 CORBA::Double MaxAspectRatio,
2206 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2207 throw (SALOME::SALOME_Exception)
2209 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2210 MaxAspectRatio, Method, true );
2214 //=======================================================================
2215 //function : SmoothObject
2217 //=======================================================================
2220 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2221 const SMESH::long_array & IDsOfFixedNodes,
2222 CORBA::Long MaxNbOfIterations,
2223 CORBA::Double MaxAspectRatio,
2224 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2225 throw (SALOME::SALOME_Exception)
2227 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2228 MaxAspectRatio, Method, false);
2232 //=======================================================================
2233 //function : SmoothParametricObject
2235 //=======================================================================
2238 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2239 const SMESH::long_array & IDsOfFixedNodes,
2240 CORBA::Long MaxNbOfIterations,
2241 CORBA::Double MaxAspectRatio,
2242 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2243 throw (SALOME::SALOME_Exception)
2245 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2246 MaxAspectRatio, Method, true);
2250 //=============================================================================
2254 //=============================================================================
2257 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2258 const SMESH::long_array & IDsOfFixedNodes,
2259 CORBA::Long MaxNbOfIterations,
2260 CORBA::Double MaxAspectRatio,
2261 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2263 throw (SALOME::SALOME_Exception)
2268 SMESHDS_Mesh* aMesh = getMeshDS();
2270 TIDSortedElemSet elements;
2271 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2273 set<const SMDS_MeshNode*> fixedNodes;
2274 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2275 CORBA::Long index = IDsOfFixedNodes[i];
2276 const SMDS_MeshNode * node = aMesh->FindNode(index);
2278 fixedNodes.insert( node );
2280 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2281 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2282 method = ::SMESH_MeshEditor::CENTROIDAL;
2284 getEditor().Smooth(elements, fixedNodes, method,
2285 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2287 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2289 // Update Python script
2290 TPythonDump() << "isDone = " << this << "."
2291 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2292 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2293 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2294 << "SMESH.SMESH_MeshEditor."
2295 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2296 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2300 SMESH_CATCH( SMESH::throwCorbaException );
2304 //=============================================================================
2308 //=============================================================================
2311 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2312 const SMESH::long_array & IDsOfFixedNodes,
2313 CORBA::Long MaxNbOfIterations,
2314 CORBA::Double MaxAspectRatio,
2315 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2317 throw (SALOME::SALOME_Exception)
2322 TPythonDump aTPythonDump; // suppress dump in smooth()
2324 prepareIdSource( theObject );
2325 SMESH::long_array_var anElementsId = theObject->GetIDs();
2326 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2327 MaxAspectRatio, Method, IsParametric);
2329 // Update Python script
2330 aTPythonDump << "isDone = " << this << "."
2331 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2332 << theObject << ", " << IDsOfFixedNodes << ", "
2333 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2334 << "SMESH.SMESH_MeshEditor."
2335 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2336 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2340 SMESH_CATCH( SMESH::throwCorbaException );
2344 //=============================================================================
2348 //=============================================================================
2350 void SMESH_MeshEditor_i::RenumberNodes()
2351 throw (SALOME::SALOME_Exception)
2354 // Update Python script
2355 TPythonDump() << this << ".RenumberNodes()";
2357 getMeshDS()->Renumber( true );
2359 SMESH_CATCH( SMESH::throwCorbaException );
2362 //=============================================================================
2366 //=============================================================================
2368 void SMESH_MeshEditor_i::RenumberElements()
2369 throw (SALOME::SALOME_Exception)
2372 // Update Python script
2373 TPythonDump() << this << ".RenumberElements()";
2375 getMeshDS()->Renumber( false );
2377 SMESH_CATCH( SMESH::throwCorbaException );
2380 //=======================================================================
2382 * \brief Return groups by their IDs
2384 //=======================================================================
2386 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2387 throw (SALOME::SALOME_Exception)
2392 myMesh_i->CreateGroupServants();
2393 return myMesh_i->GetGroups( *groupIDs );
2395 SMESH_CATCH( SMESH::throwCorbaException );
2399 //=======================================================================
2400 //function : RotationSweepObjects
2402 //=======================================================================
2404 SMESH::ListOfGroups*
2405 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2406 const SMESH::ListOfIDSources & theEdges,
2407 const SMESH::ListOfIDSources & theFaces,
2408 const SMESH::AxisStruct & theAxis,
2409 CORBA::Double theAngleInRadians,
2410 CORBA::Long theNbOfSteps,
2411 CORBA::Double theTolerance,
2412 const bool theMakeGroups)
2413 throw (SALOME::SALOME_Exception)
2418 TIDSortedElemSet elemsNodes[2];
2419 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2420 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2421 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2423 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2424 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2425 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2426 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2428 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2429 bool makeWalls=true;
2430 if ( myIsPreviewMode )
2432 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2433 TPreviewMesh * tmpMesh = getPreviewMesh();
2434 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2435 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2436 workElements = & copyElements[0];
2437 //makeWalls = false; -- faces are needed for preview
2440 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2442 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2443 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2445 ::SMESH_MeshEditor::PGroupIDs groupIds =
2446 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2447 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2449 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2451 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2453 if ( !myIsPreviewMode )
2455 dumpGroupsList( aPythonDump, aGroups );
2456 aPythonDump << this<< ".RotationSweepObjects( "
2461 << TVar( theAngleInRadians ) << ", "
2462 << TVar( theNbOfSteps ) << ", "
2463 << TVar( theTolerance ) << ", "
2464 << theMakeGroups << " )";
2468 getPreviewMesh()->Remove( SMDSAbs_Volume );
2471 return aGroups ? aGroups : new SMESH::ListOfGroups;
2473 SMESH_CATCH( SMESH::throwCorbaException );
2477 namespace MeshEditor_I
2480 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2482 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2484 bool myIsExtrusionByNormal;
2486 static int makeFlags( CORBA::Boolean MakeGroups,
2487 CORBA::Boolean ByAverageNormal = false,
2488 CORBA::Boolean UseInputElemsOnly = false,
2489 CORBA::Long Flags = 0,
2490 CORBA::Boolean MakeBoundary = true )
2492 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2493 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2494 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2495 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2499 ExtrusionParams(const SMESH::DirStruct & theDir,
2500 CORBA::Long theNbOfSteps,
2501 CORBA::Boolean theMakeGroups):
2502 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2506 makeFlags( theMakeGroups )),
2507 myIsExtrusionByNormal( false )
2511 ExtrusionParams(const SMESH::DirStruct & theDir,
2512 CORBA::Long theNbOfSteps,
2513 CORBA::Boolean theMakeGroups,
2514 CORBA::Long theExtrFlags,
2515 CORBA::Double theSewTolerance):
2516 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2520 makeFlags( theMakeGroups, false, false,
2521 theExtrFlags, false ),
2523 myIsExtrusionByNormal( false )
2526 // params for extrusion by normal
2527 ExtrusionParams(CORBA::Double theStepSize,
2528 CORBA::Long theNbOfSteps,
2529 CORBA::Short theDim,
2530 CORBA::Boolean theByAverageNormal,
2531 CORBA::Boolean theUseInputElemsOnly,
2532 CORBA::Boolean theMakeGroups ):
2533 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2535 makeFlags( theMakeGroups,
2536 theByAverageNormal, theUseInputElemsOnly ),
2538 myIsExtrusionByNormal( true )
2544 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2549 //=======================================================================
2551 * \brief Generate dim+1 elements by extrusion of elements along vector
2552 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2553 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2554 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2555 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2556 * \param [in] nbOfSteps - number of elements to generate from one element
2557 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2558 * corresponding to groups the input elements included in.
2559 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2561 //=======================================================================
2563 SMESH::ListOfGroups*
2564 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2565 const SMESH::ListOfIDSources & theEdges,
2566 const SMESH::ListOfIDSources & theFaces,
2567 const SMESH::DirStruct & theStepVector,
2568 CORBA::Long theNbOfSteps,
2569 CORBA::Boolean theToMakeGroups)
2570 throw (SALOME::SALOME_Exception)
2575 ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
2577 TIDSortedElemSet elemsNodes[2];
2578 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2579 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2580 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2582 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2583 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2584 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2585 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2587 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2588 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2589 if ( myIsPreviewMode )
2591 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2592 // previewType = SMDSAbs_Edge;
2594 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2595 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2596 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2597 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2598 workElements = & copyElements[0];
2600 params.SetNoGroups();
2602 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2604 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2605 ::SMESH_MeshEditor::PGroupIDs groupIds =
2606 getEditor().ExtrusionSweep( workElements, params, aHistory );
2608 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2610 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2612 if ( !myIsPreviewMode )
2614 dumpGroupsList( aPythonDump, aGroups );
2615 aPythonDump << this<< ".ExtrusionSweepObjects( "
2619 << theStepVector << ", "
2620 << TVar( theNbOfSteps ) << ", "
2621 << theToMakeGroups << " )";
2625 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2628 return aGroups ? aGroups : new SMESH::ListOfGroups;
2630 SMESH_CATCH( SMESH::throwCorbaException );
2634 //=======================================================================
2635 //function : ExtrusionByNormal
2637 //=======================================================================
2639 SMESH::ListOfGroups*
2640 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2641 CORBA::Double stepSize,
2642 CORBA::Long nbOfSteps,
2643 CORBA::Boolean byAverageNormal,
2644 CORBA::Boolean useInputElemsOnly,
2645 CORBA::Boolean makeGroups,
2647 throw (SALOME::SALOME_Exception)
2652 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2654 ExtrusionParams params( stepSize, nbOfSteps, dim,
2655 byAverageNormal, useInputElemsOnly, makeGroups );
2657 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2658 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2660 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2661 if (( elemTypes->length() == 1 ) &&
2662 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2663 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2666 TIDSortedElemSet elemsNodes[2];
2667 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2668 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2670 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2671 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2672 if ( myIsPreviewMode )
2674 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2675 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2676 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2677 workElements = & copyElements[0];
2679 params.SetNoGroups();
2682 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2683 ::SMESH_MeshEditor::PGroupIDs groupIds =
2684 getEditor().ExtrusionSweep( workElements, params, aHistory );
2686 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2688 if (!myIsPreviewMode) {
2689 dumpGroupsList(aPythonDump, aGroups);
2690 aPythonDump << this << ".ExtrusionByNormal( " << objects
2691 << ", " << TVar( stepSize )
2692 << ", " << TVar( nbOfSteps )
2693 << ", " << byAverageNormal
2694 << ", " << useInputElemsOnly
2695 << ", " << makeGroups
2701 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2704 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2706 return aGroups ? aGroups : new SMESH::ListOfGroups;
2708 SMESH_CATCH( SMESH::throwCorbaException );
2712 //=======================================================================
2713 //function : AdvancedExtrusion
2715 //=======================================================================
2717 SMESH::ListOfGroups*
2718 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2719 const SMESH::DirStruct & theStepVector,
2720 CORBA::Long theNbOfSteps,
2721 CORBA::Long theExtrFlags,
2722 CORBA::Double theSewTolerance,
2723 CORBA::Boolean theMakeGroups)
2724 throw (SALOME::SALOME_Exception)
2729 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2731 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2732 theExtrFlags, theSewTolerance );
2734 TIDSortedElemSet elemsNodes[2];
2735 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2737 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2738 ::SMESH_MeshEditor::PGroupIDs groupIds =
2739 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2741 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2743 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2745 if ( !myIsPreviewMode ) {
2746 dumpGroupsList(aPythonDump, aGroups);
2747 aPythonDump << this << ".AdvancedExtrusion( "
2748 << theIDsOfElements << ", "
2749 << theStepVector << ", "
2750 << theNbOfSteps << ", "
2751 << theExtrFlags << ", "
2752 << theSewTolerance << ", "
2753 << theMakeGroups << " )";
2757 getPreviewMesh()->Remove( SMDSAbs_Volume );
2760 return aGroups ? aGroups : new SMESH::ListOfGroups;
2762 SMESH_CATCH( SMESH::throwCorbaException );
2766 //================================================================================
2768 * \brief Convert extrusion error to IDL enum
2770 //================================================================================
2774 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2776 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2780 RETCASE( EXTR_NO_ELEMENTS );
2781 RETCASE( EXTR_PATH_NOT_EDGE );
2782 RETCASE( EXTR_BAD_PATH_SHAPE );
2783 RETCASE( EXTR_BAD_STARTING_NODE );
2784 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2785 RETCASE( EXTR_CANT_GET_TANGENT );
2787 return SMESH::SMESH_MeshEditor::EXTR_OK;
2791 //=======================================================================
2792 //function : extrusionAlongPath
2794 //=======================================================================
2795 SMESH::ListOfGroups*
2796 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2797 const SMESH::ListOfIDSources & theEdges,
2798 const SMESH::ListOfIDSources & theFaces,
2799 SMESH::SMESH_IDSource_ptr thePathMesh,
2800 GEOM::GEOM_Object_ptr thePathShape,
2801 CORBA::Long theNodeStart,
2802 CORBA::Boolean theHasAngles,
2803 const SMESH::double_array & theAngles,
2804 CORBA::Boolean theLinearVariation,
2805 CORBA::Boolean theHasRefPoint,
2806 const SMESH::PointStruct & theRefPoint,
2808 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2809 throw (SALOME::SALOME_Exception)
2814 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2816 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2817 if ( thePathMesh->_is_nil() )
2818 return aGroups._retn();
2821 SMESH_subMesh* aSubMesh = 0;
2822 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2823 if ( thePathShape->_is_nil() )
2825 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2826 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2828 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2829 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2830 if ( !aMeshImp ) return aGroups._retn();
2831 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2832 if ( !aSubMesh ) return aGroups._retn();
2834 else if ( !aMeshImp ||
2835 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2837 return aGroups._retn();
2842 if ( !aMeshImp ) return aGroups._retn();
2843 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2844 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2845 if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
2846 return aGroups._retn();
2849 SMDS_MeshNode* nodeStart =
2850 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2852 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2853 return aGroups._retn();
2856 TIDSortedElemSet elemsNodes[2];
2857 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2858 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2859 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2861 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2862 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2863 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2864 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2866 list<double> angles;
2867 for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) {
2868 angles.push_back( theAngles[i] );
2871 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2873 int nbOldGroups = myMesh->NbGroup();
2875 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2876 if ( myIsPreviewMode )
2878 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2879 TPreviewMesh * tmpMesh = getPreviewMesh();
2880 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2881 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2882 workElements = & copyElements[0];
2883 theMakeGroups = false;
2886 ::SMESH_MeshEditor::Extrusion_Error error;
2888 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2889 theHasAngles, angles, theLinearVariation,
2890 theHasRefPoint, refPnt, theMakeGroups );
2892 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2893 theHasAngles, angles, theLinearVariation,
2894 theHasRefPoint, refPnt, theMakeGroups );
2896 declareMeshModified( /*isReComputeSafe=*/true );
2897 theError = convExtrError( error );
2899 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2900 if ( theMakeGroups ) {
2901 list<int> groupIDs = myMesh->GetGroupIds();
2902 list<int>::iterator newBegin = groupIDs.begin();
2903 std::advance( newBegin, nbOldGroups ); // skip old groups
2904 groupIDs.erase( groupIDs.begin(), newBegin );
2905 aGroups = getGroups( & groupIDs );
2906 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2909 if ( !myIsPreviewMode ) {
2910 aPythonDump << "(" << aGroups << ", error) = "
2911 << this << ".ExtrusionAlongPathObjects( "
2915 << thePathMesh << ", "
2916 << thePathShape << ", "
2917 << theNodeStart << ", "
2918 << theHasAngles << ", "
2919 << theAngles << ", "
2920 << theLinearVariation << ", "
2921 << theHasRefPoint << ", "
2922 << "SMESH.PointStruct( "
2923 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2924 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2925 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2926 << theMakeGroups << " )";
2930 getPreviewMesh()->Remove( SMDSAbs_Volume );
2933 return aGroups._retn();
2935 SMESH_CATCH( SMESH::throwCorbaException );
2939 //================================================================================
2941 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2942 * of given angles along path steps
2943 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2944 * which proceeds the extrusion
2945 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2946 * is used to define the sub-mesh for the path
2948 //================================================================================
2950 SMESH::double_array*
2951 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2952 GEOM::GEOM_Object_ptr thePathShape,
2953 const SMESH::double_array & theAngles)
2955 SMESH::double_array_var aResult = new SMESH::double_array();
2956 int nbAngles = theAngles.length();
2957 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2959 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2960 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2961 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2962 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2963 return aResult._retn();
2964 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2965 if ( nbSteps == nbAngles )
2967 aResult.inout() = theAngles;
2971 aResult->length( nbSteps );
2972 double rAn2St = double( nbAngles ) / double( nbSteps );
2973 double angPrev = 0, angle;
2974 for ( int iSt = 0; iSt < nbSteps; ++iSt )
2976 double angCur = rAn2St * ( iSt+1 );
2977 double angCurFloor = floor( angCur );
2978 double angPrevFloor = floor( angPrev );
2979 if ( angPrevFloor == angCurFloor )
2980 angle = rAn2St * theAngles[ int( angCurFloor ) ];
2983 int iP = int( angPrevFloor );
2984 double angPrevCeil = ceil(angPrev);
2985 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2987 int iC = int( angCurFloor );
2988 if ( iC < nbAngles )
2989 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2991 iP = int( angPrevCeil );
2993 angle += theAngles[ iC ];
2995 aResult[ iSt ] = angle;
3000 // Update Python script
3001 TPythonDump() << "rotAngles = " << theAngles;
3002 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3003 << thePathMesh << ", "
3004 << thePathShape << ", "
3007 return aResult._retn();
3010 //=======================================================================
3013 //=======================================================================
3015 SMESH::ListOfGroups*
3016 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3017 const SMESH::AxisStruct & theAxis,
3018 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3019 CORBA::Boolean theCopy,
3021 ::SMESH_Mesh* theTargetMesh)
3022 throw (SALOME::SALOME_Exception)
3027 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3028 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3030 if ( theTargetMesh )
3034 switch ( theMirrorType ) {
3035 case SMESH::SMESH_MeshEditor::POINT:
3036 aTrsf.SetMirror( P );
3038 case SMESH::SMESH_MeshEditor::AXIS:
3039 aTrsf.SetMirror( gp_Ax1( P, V ));
3042 aTrsf.SetMirror( gp_Ax2( P, V ));
3045 TIDSortedElemSet copyElements;
3046 TIDSortedElemSet* workElements = & theElements;
3048 if ( myIsPreviewMode )
3050 TPreviewMesh * tmpMesh = getPreviewMesh();
3051 tmpMesh->Copy( theElements, copyElements);
3052 if ( !theCopy && !theTargetMesh )
3054 TIDSortedElemSet elemsAround, elemsAroundCopy;
3055 getElementsAround( theElements, getMeshDS(), elemsAround );
3056 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3058 workElements = & copyElements;
3059 theMakeGroups = false;
3062 ::SMESH_MeshEditor::PGroupIDs groupIds =
3063 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3065 if ( theCopy && !myIsPreviewMode)
3067 if ( theTargetMesh )
3069 theTargetMesh->GetMeshDS()->Modified();
3073 declareMeshModified( /*isReComputeSafe=*/false );
3076 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3078 SMESH_CATCH( SMESH::throwCorbaException );
3082 //=======================================================================
3085 //=======================================================================
3087 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3088 const SMESH::AxisStruct & theAxis,
3089 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3090 CORBA::Boolean theCopy)
3091 throw (SALOME::SALOME_Exception)
3093 if ( !myIsPreviewMode ) {
3094 TPythonDump() << this << ".Mirror( "
3095 << theIDsOfElements << ", "
3097 << mirrorTypeName(theMirrorType) << ", "
3100 if ( theIDsOfElements.length() > 0 )
3102 TIDSortedElemSet elements;
3103 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3104 mirror(elements, theAxis, theMirrorType, theCopy, false);
3109 //=======================================================================
3110 //function : MirrorObject
3112 //=======================================================================
3114 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3115 const SMESH::AxisStruct & theAxis,
3116 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3117 CORBA::Boolean theCopy)
3118 throw (SALOME::SALOME_Exception)
3120 if ( !myIsPreviewMode ) {
3121 TPythonDump() << this << ".MirrorObject( "
3122 << theObject << ", "
3124 << mirrorTypeName(theMirrorType) << ", "
3127 TIDSortedElemSet elements;
3129 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3131 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3132 mirror(elements, theAxis, theMirrorType, theCopy, false);
3135 //=======================================================================
3136 //function : MirrorMakeGroups
3138 //=======================================================================
3140 SMESH::ListOfGroups*
3141 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3142 const SMESH::AxisStruct& theMirror,
3143 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3144 throw (SALOME::SALOME_Exception)
3146 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3148 SMESH::ListOfGroups * aGroups = 0;
3149 if ( theIDsOfElements.length() > 0 )
3151 TIDSortedElemSet elements;
3152 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3153 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3155 if (!myIsPreviewMode) {
3156 dumpGroupsList(aPythonDump, aGroups);
3157 aPythonDump << this << ".MirrorMakeGroups( "
3158 << theIDsOfElements << ", "
3159 << theMirror << ", "
3160 << mirrorTypeName(theMirrorType) << " )";
3165 //=======================================================================
3166 //function : MirrorObjectMakeGroups
3168 //=======================================================================
3170 SMESH::ListOfGroups*
3171 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3172 const SMESH::AxisStruct& theMirror,
3173 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3174 throw (SALOME::SALOME_Exception)
3176 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3178 SMESH::ListOfGroups * aGroups = 0;
3179 TIDSortedElemSet elements;
3180 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3181 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3183 if (!myIsPreviewMode)
3185 dumpGroupsList(aPythonDump,aGroups);
3186 aPythonDump << this << ".MirrorObjectMakeGroups( "
3187 << theObject << ", "
3188 << theMirror << ", "
3189 << mirrorTypeName(theMirrorType) << " )";
3194 //=======================================================================
3195 //function : MirrorMakeMesh
3197 //=======================================================================
3199 SMESH::SMESH_Mesh_ptr
3200 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3201 const SMESH::AxisStruct& theMirror,
3202 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3203 CORBA::Boolean theCopyGroups,
3204 const char* theMeshName)
3205 throw (SALOME::SALOME_Exception)
3207 SMESH_Mesh_i* mesh_i;
3208 SMESH::SMESH_Mesh_var mesh;
3209 { // open new scope to dump "MakeMesh" command
3210 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3212 TPythonDump pydump; // to prevent dump at mesh creation
3214 mesh = makeMesh( theMeshName );
3215 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3216 if (mesh_i && theIDsOfElements.length() > 0 )
3218 TIDSortedElemSet elements;
3219 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3220 mirror(elements, theMirror, theMirrorType,
3221 false, theCopyGroups, & mesh_i->GetImpl());
3222 mesh_i->CreateGroupServants();
3225 if (!myIsPreviewMode) {
3226 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3227 << theIDsOfElements << ", "
3228 << theMirror << ", "
3229 << mirrorTypeName(theMirrorType) << ", "
3230 << theCopyGroups << ", '"
3231 << theMeshName << "' )";
3236 if (!myIsPreviewMode && mesh_i)
3237 mesh_i->GetGroups();
3239 return mesh._retn();
3242 //=======================================================================
3243 //function : MirrorObjectMakeMesh
3245 //=======================================================================
3247 SMESH::SMESH_Mesh_ptr
3248 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3249 const SMESH::AxisStruct& theMirror,
3250 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3251 CORBA::Boolean theCopyGroups,
3252 const char* theMeshName)
3253 throw (SALOME::SALOME_Exception)
3255 SMESH_Mesh_i* mesh_i;
3256 SMESH::SMESH_Mesh_var mesh;
3257 { // open new scope to dump "MakeMesh" command
3258 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3260 TPythonDump pydump; // to prevent dump at mesh creation
3262 mesh = makeMesh( theMeshName );
3263 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3264 TIDSortedElemSet elements;
3266 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3268 mirror(elements, theMirror, theMirrorType,
3269 false, theCopyGroups, & mesh_i->GetImpl());
3270 mesh_i->CreateGroupServants();
3272 if (!myIsPreviewMode) {
3273 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3274 << theObject << ", "
3275 << theMirror << ", "
3276 << mirrorTypeName(theMirrorType) << ", "
3277 << theCopyGroups << ", '"
3278 << theMeshName << "' )";
3283 if (!myIsPreviewMode && mesh_i)
3284 mesh_i->GetGroups();
3286 return mesh._retn();
3289 //=======================================================================
3290 //function : translate
3292 //=======================================================================
3294 SMESH::ListOfGroups*
3295 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3296 const SMESH::DirStruct & theVector,
3297 CORBA::Boolean theCopy,
3299 ::SMESH_Mesh* theTargetMesh)
3300 throw (SALOME::SALOME_Exception)
3305 if ( theTargetMesh )
3309 const SMESH::PointStruct * P = &theVector.PS;
3310 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3312 TIDSortedElemSet copyElements;
3313 TIDSortedElemSet* workElements = &theElements;
3315 if ( myIsPreviewMode )
3317 TPreviewMesh * tmpMesh = getPreviewMesh();
3318 tmpMesh->Copy( theElements, copyElements);
3319 if ( !theCopy && !theTargetMesh )
3321 TIDSortedElemSet elemsAround, elemsAroundCopy;
3322 getElementsAround( theElements, getMeshDS(), elemsAround );
3323 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3325 workElements = & copyElements;
3326 theMakeGroups = false;
3329 ::SMESH_MeshEditor::PGroupIDs groupIds =
3330 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3332 if ( theCopy && !myIsPreviewMode )
3334 if ( theTargetMesh )
3336 theTargetMesh->GetMeshDS()->Modified();
3340 declareMeshModified( /*isReComputeSafe=*/false );
3344 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3346 SMESH_CATCH( SMESH::throwCorbaException );
3350 //=======================================================================
3351 //function : Translate
3353 //=======================================================================
3355 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3356 const SMESH::DirStruct & theVector,
3357 CORBA::Boolean theCopy)
3358 throw (SALOME::SALOME_Exception)
3360 if (!myIsPreviewMode) {
3361 TPythonDump() << this << ".Translate( "
3362 << theIDsOfElements << ", "
3363 << theVector << ", "
3366 if (theIDsOfElements.length()) {
3367 TIDSortedElemSet elements;
3368 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3369 translate(elements, theVector, theCopy, false);
3373 //=======================================================================
3374 //function : TranslateObject
3376 //=======================================================================
3378 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3379 const SMESH::DirStruct & theVector,
3380 CORBA::Boolean theCopy)
3381 throw (SALOME::SALOME_Exception)
3383 if (!myIsPreviewMode) {
3384 TPythonDump() << this << ".TranslateObject( "
3385 << theObject << ", "
3386 << theVector << ", "
3389 TIDSortedElemSet elements;
3391 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3393 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3394 translate(elements, theVector, theCopy, false);
3397 //=======================================================================
3398 //function : TranslateMakeGroups
3400 //=======================================================================
3402 SMESH::ListOfGroups*
3403 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3404 const SMESH::DirStruct& theVector)
3405 throw (SALOME::SALOME_Exception)
3407 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3409 SMESH::ListOfGroups * aGroups = 0;
3410 if (theIDsOfElements.length()) {
3411 TIDSortedElemSet elements;
3412 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3413 aGroups = translate(elements,theVector,true,true);
3415 if (!myIsPreviewMode) {
3416 dumpGroupsList(aPythonDump, aGroups);
3417 aPythonDump << this << ".TranslateMakeGroups( "
3418 << theIDsOfElements << ", "
3419 << theVector << " )";
3424 //=======================================================================
3425 //function : TranslateObjectMakeGroups
3427 //=======================================================================
3429 SMESH::ListOfGroups*
3430 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3431 const SMESH::DirStruct& theVector)
3432 throw (SALOME::SALOME_Exception)
3434 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3436 SMESH::ListOfGroups * aGroups = 0;
3437 TIDSortedElemSet elements;
3438 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3439 aGroups = translate(elements, theVector, true, true);
3441 if (!myIsPreviewMode) {
3442 dumpGroupsList(aPythonDump, aGroups);
3443 aPythonDump << this << ".TranslateObjectMakeGroups( "
3444 << theObject << ", "
3445 << theVector << " )";
3450 //=======================================================================
3451 //function : TranslateMakeMesh
3453 //=======================================================================
3455 SMESH::SMESH_Mesh_ptr
3456 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3457 const SMESH::DirStruct& theVector,
3458 CORBA::Boolean theCopyGroups,
3459 const char* theMeshName)
3460 throw (SALOME::SALOME_Exception)
3462 SMESH_Mesh_i* mesh_i;
3463 SMESH::SMESH_Mesh_var mesh;
3465 { // open new scope to dump "MakeMesh" command
3466 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3468 TPythonDump pydump; // to prevent dump at mesh creation
3470 mesh = makeMesh( theMeshName );
3471 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3473 if ( mesh_i && theIDsOfElements.length() )
3475 TIDSortedElemSet elements;
3476 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3477 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3478 mesh_i->CreateGroupServants();
3481 if ( !myIsPreviewMode ) {
3482 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3483 << theIDsOfElements << ", "
3484 << theVector << ", "
3485 << theCopyGroups << ", '"
3486 << theMeshName << "' )";
3491 if (!myIsPreviewMode && mesh_i)
3492 mesh_i->GetGroups();
3494 return mesh._retn();
3497 //=======================================================================
3498 //function : TranslateObjectMakeMesh
3500 //=======================================================================
3502 SMESH::SMESH_Mesh_ptr
3503 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3504 const SMESH::DirStruct& theVector,
3505 CORBA::Boolean theCopyGroups,
3506 const char* theMeshName)
3507 throw (SALOME::SALOME_Exception)
3510 SMESH_Mesh_i* mesh_i;
3511 SMESH::SMESH_Mesh_var mesh;
3512 { // open new scope to dump "MakeMesh" command
3513 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3515 TPythonDump pydump; // to prevent dump at mesh creation
3516 mesh = makeMesh( theMeshName );
3517 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3519 TIDSortedElemSet elements;
3521 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3523 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3524 mesh_i->CreateGroupServants();
3526 if ( !myIsPreviewMode ) {
3527 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3528 << theObject << ", "
3529 << theVector << ", "
3530 << theCopyGroups << ", '"
3531 << theMeshName << "' )";
3536 if (!myIsPreviewMode && mesh_i)
3537 mesh_i->GetGroups();
3539 return mesh._retn();
3541 SMESH_CATCH( SMESH::throwCorbaException );
3545 //=======================================================================
3548 //=======================================================================
3550 SMESH::ListOfGroups*
3551 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3552 const SMESH::AxisStruct & theAxis,
3553 CORBA::Double theAngle,
3554 CORBA::Boolean theCopy,
3556 ::SMESH_Mesh* theTargetMesh)
3557 throw (SALOME::SALOME_Exception)
3562 if ( theTargetMesh )
3565 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3566 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3569 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3571 TIDSortedElemSet copyElements;
3572 TIDSortedElemSet* workElements = &theElements;
3573 if ( myIsPreviewMode ) {
3574 TPreviewMesh * tmpMesh = getPreviewMesh();
3575 tmpMesh->Copy( theElements, copyElements );
3576 if ( !theCopy && !theTargetMesh )
3578 TIDSortedElemSet elemsAround, elemsAroundCopy;
3579 getElementsAround( theElements, getMeshDS(), elemsAround );
3580 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3582 workElements = ©Elements;
3583 theMakeGroups = false;
3586 ::SMESH_MeshEditor::PGroupIDs groupIds =
3587 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3589 if ( theCopy && !myIsPreviewMode)
3591 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3592 else declareMeshModified( /*isReComputeSafe=*/false );
3595 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3597 SMESH_CATCH( SMESH::throwCorbaException );
3601 //=======================================================================
3604 //=======================================================================
3606 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3607 const SMESH::AxisStruct & theAxis,
3608 CORBA::Double theAngle,
3609 CORBA::Boolean theCopy)
3610 throw (SALOME::SALOME_Exception)
3612 if (!myIsPreviewMode) {
3613 TPythonDump() << this << ".Rotate( "
3614 << theIDsOfElements << ", "
3616 << TVar( theAngle ) << ", "
3619 if (theIDsOfElements.length() > 0)
3621 TIDSortedElemSet elements;
3622 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3623 rotate(elements,theAxis,theAngle,theCopy,false);
3627 //=======================================================================
3628 //function : RotateObject
3630 //=======================================================================
3632 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3633 const SMESH::AxisStruct & theAxis,
3634 CORBA::Double theAngle,
3635 CORBA::Boolean theCopy)
3636 throw (SALOME::SALOME_Exception)
3638 if ( !myIsPreviewMode ) {
3639 TPythonDump() << this << ".RotateObject( "
3640 << theObject << ", "
3642 << TVar( theAngle ) << ", "
3645 TIDSortedElemSet elements;
3646 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3647 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3648 rotate(elements,theAxis,theAngle,theCopy,false);
3651 //=======================================================================
3652 //function : RotateMakeGroups
3654 //=======================================================================
3656 SMESH::ListOfGroups*
3657 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3658 const SMESH::AxisStruct& theAxis,
3659 CORBA::Double theAngle)
3660 throw (SALOME::SALOME_Exception)
3662 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3664 SMESH::ListOfGroups * aGroups = 0;
3665 if (theIDsOfElements.length() > 0)
3667 TIDSortedElemSet elements;
3668 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3669 aGroups = rotate(elements,theAxis,theAngle,true,true);
3671 if (!myIsPreviewMode) {
3672 dumpGroupsList(aPythonDump, aGroups);
3673 aPythonDump << this << ".RotateMakeGroups( "
3674 << theIDsOfElements << ", "
3676 << TVar( theAngle ) << " )";
3681 //=======================================================================
3682 //function : RotateObjectMakeGroups
3684 //=======================================================================
3686 SMESH::ListOfGroups*
3687 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3688 const SMESH::AxisStruct& theAxis,
3689 CORBA::Double theAngle)
3690 throw (SALOME::SALOME_Exception)
3692 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3694 SMESH::ListOfGroups * aGroups = 0;
3695 TIDSortedElemSet elements;
3696 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3697 aGroups = rotate(elements, theAxis, theAngle, true, true);
3699 if (!myIsPreviewMode) {
3700 dumpGroupsList(aPythonDump, aGroups);
3701 aPythonDump << this << ".RotateObjectMakeGroups( "
3702 << theObject << ", "
3704 << TVar( theAngle ) << " )";
3709 //=======================================================================
3710 //function : RotateMakeMesh
3712 //=======================================================================
3714 SMESH::SMESH_Mesh_ptr
3715 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3716 const SMESH::AxisStruct& theAxis,
3717 CORBA::Double theAngleInRadians,
3718 CORBA::Boolean theCopyGroups,
3719 const char* theMeshName)
3720 throw (SALOME::SALOME_Exception)
3723 SMESH::SMESH_Mesh_var mesh;
3724 SMESH_Mesh_i* mesh_i;
3726 { // open new scope to dump "MakeMesh" command
3727 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3729 TPythonDump pydump; // to prevent dump at mesh creation
3731 mesh = makeMesh( theMeshName );
3732 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3734 if ( mesh_i && theIDsOfElements.length() > 0 )
3736 TIDSortedElemSet elements;
3737 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3738 rotate(elements, theAxis, theAngleInRadians,
3739 false, theCopyGroups, & mesh_i->GetImpl());
3740 mesh_i->CreateGroupServants();
3742 if ( !myIsPreviewMode ) {
3743 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3744 << theIDsOfElements << ", "
3746 << TVar( theAngleInRadians ) << ", "
3747 << theCopyGroups << ", '"
3748 << theMeshName << "' )";
3753 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3754 mesh_i->GetGroups();
3756 return mesh._retn();
3758 SMESH_CATCH( SMESH::throwCorbaException );
3762 //=======================================================================
3763 //function : RotateObjectMakeMesh
3765 //=======================================================================
3767 SMESH::SMESH_Mesh_ptr
3768 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3769 const SMESH::AxisStruct& theAxis,
3770 CORBA::Double theAngleInRadians,
3771 CORBA::Boolean theCopyGroups,
3772 const char* theMeshName)
3773 throw (SALOME::SALOME_Exception)
3776 SMESH::SMESH_Mesh_var mesh;
3777 SMESH_Mesh_i* mesh_i;
3779 {// open new scope to dump "MakeMesh" command
3780 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3782 TPythonDump pydump; // to prevent dump at mesh creation
3783 mesh = makeMesh( theMeshName );
3784 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3786 TIDSortedElemSet elements;
3788 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3790 rotate(elements, theAxis, theAngleInRadians,
3791 false, theCopyGroups, & mesh_i->GetImpl());
3792 mesh_i->CreateGroupServants();
3794 if ( !myIsPreviewMode ) {
3795 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3796 << theObject << ", "
3798 << TVar( theAngleInRadians ) << ", "
3799 << theCopyGroups << ", '"
3800 << theMeshName << "' )";
3805 if (!myIsPreviewMode && mesh_i)
3806 mesh_i->GetGroups();
3808 return mesh._retn();
3810 SMESH_CATCH( SMESH::throwCorbaException );
3814 //=======================================================================
3817 //=======================================================================
3819 SMESH::ListOfGroups*
3820 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3821 const SMESH::PointStruct& thePoint,
3822 const SMESH::double_array& theScaleFact,
3823 CORBA::Boolean theCopy,
3825 ::SMESH_Mesh* theTargetMesh)
3826 throw (SALOME::SALOME_Exception)
3830 if ( theScaleFact.length() < 1 )
3831 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3832 if ( theScaleFact.length() == 2 )
3833 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3835 if ( theTargetMesh )
3838 TIDSortedElemSet elements;
3839 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3840 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3845 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3846 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3850 #if OCC_VERSION_LARGE > 0x06070100
3851 // fight against orthogonalization
3852 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3853 // 0, S[1], 0, thePoint.y * (1-S[1]),
3854 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3855 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3856 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3857 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3858 loc.SetCoord( thePoint.x * (1-S[0]),
3859 thePoint.y * (1-S[1]),
3860 thePoint.z * (1-S[2]));
3861 M.SetDiagonal( S[0], S[1], S[2] );
3864 double tol = std::numeric_limits<double>::max();
3865 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3866 0, S[1], 0, thePoint.y * (1-S[1]),
3867 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3870 TIDSortedElemSet copyElements;
3871 TIDSortedElemSet* workElements = &elements;
3872 if ( myIsPreviewMode )
3874 TPreviewMesh * tmpMesh = getPreviewMesh();
3875 tmpMesh->Copy( elements, copyElements);
3876 if ( !theCopy && !theTargetMesh )
3878 TIDSortedElemSet elemsAround, elemsAroundCopy;
3879 getElementsAround( elements, getMeshDS(), elemsAround );
3880 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3882 workElements = & copyElements;
3883 theMakeGroups = false;
3886 ::SMESH_MeshEditor::PGroupIDs groupIds =
3887 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3889 if ( theCopy && !myIsPreviewMode )
3891 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3892 else declareMeshModified( /*isReComputeSafe=*/false );
3894 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3896 SMESH_CATCH( SMESH::throwCorbaException );
3900 //=======================================================================
3903 //=======================================================================
3905 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3906 const SMESH::PointStruct& thePoint,
3907 const SMESH::double_array& theScaleFact,
3908 CORBA::Boolean theCopy)
3909 throw (SALOME::SALOME_Exception)
3911 if ( !myIsPreviewMode ) {
3912 TPythonDump() << this << ".Scale( "
3913 << theObject << ", "
3915 << TVar( theScaleFact ) << ", "
3918 scale(theObject, thePoint, theScaleFact, theCopy, false);
3922 //=======================================================================
3923 //function : ScaleMakeGroups
3925 //=======================================================================
3927 SMESH::ListOfGroups*
3928 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3929 const SMESH::PointStruct& thePoint,
3930 const SMESH::double_array& theScaleFact)
3931 throw (SALOME::SALOME_Exception)
3933 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3935 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3936 if (!myIsPreviewMode) {
3937 dumpGroupsList(aPythonDump, aGroups);
3938 aPythonDump << this << ".Scale("
3941 << TVar( theScaleFact ) << ",True,True)";
3947 //=======================================================================
3948 //function : ScaleMakeMesh
3950 //=======================================================================
3952 SMESH::SMESH_Mesh_ptr
3953 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3954 const SMESH::PointStruct& thePoint,
3955 const SMESH::double_array& theScaleFact,
3956 CORBA::Boolean theCopyGroups,
3957 const char* theMeshName)
3958 throw (SALOME::SALOME_Exception)
3960 SMESH_Mesh_i* mesh_i;
3961 SMESH::SMESH_Mesh_var mesh;
3962 { // open new scope to dump "MakeMesh" command
3963 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3965 TPythonDump pydump; // to prevent dump at mesh creation
3966 mesh = makeMesh( theMeshName );
3967 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3971 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3972 mesh_i->CreateGroupServants();
3974 if ( !myIsPreviewMode )
3975 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3976 << theObject << ", "
3978 << TVar( theScaleFact ) << ", "
3979 << theCopyGroups << ", '"
3980 << theMeshName << "' )";
3984 if (!myIsPreviewMode && mesh_i)
3985 mesh_i->GetGroups();
3987 return mesh._retn();
3991 //=======================================================================
3992 //function : findCoincidentNodes
3994 //=======================================================================
3996 void SMESH_MeshEditor_i::
3997 findCoincidentNodes (TIDSortedNodeSet & Nodes,
3998 CORBA::Double Tolerance,
3999 SMESH::array_of_long_array_out GroupsOfNodes,
4000 CORBA::Boolean SeparateCornersAndMedium)
4002 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4003 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4005 GroupsOfNodes = new SMESH::array_of_long_array;
4006 GroupsOfNodes->length( aListOfListOfNodes.size() );
4007 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4008 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4010 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4011 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4012 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4013 aGroup.length( aListOfNodes.size() );
4014 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4015 aGroup[ j ] = (*lIt)->GetID();
4019 //=======================================================================
4020 //function : FindCoincidentNodes
4022 //=======================================================================
4024 void SMESH_MeshEditor_i::
4025 FindCoincidentNodes (CORBA::Double Tolerance,
4026 SMESH::array_of_long_array_out GroupsOfNodes,
4027 CORBA::Boolean SeparateCornersAndMedium)
4028 throw (SALOME::SALOME_Exception)
4033 TIDSortedNodeSet nodes; // no input nodes
4034 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4036 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4037 << Tolerance << ", "
4038 << SeparateCornersAndMedium << " )";
4040 SMESH_CATCH( SMESH::throwCorbaException );
4043 //=======================================================================
4044 //function : FindCoincidentNodesOnPart
4046 //=======================================================================
4048 void SMESH_MeshEditor_i::
4049 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4050 CORBA::Double Tolerance,
4051 SMESH::array_of_long_array_out GroupsOfNodes,
4052 CORBA::Boolean SeparateCornersAndMedium)
4053 throw (SALOME::SALOME_Exception)
4058 TIDSortedNodeSet nodes;
4059 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4061 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4063 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4065 << Tolerance << ", "
4066 << SeparateCornersAndMedium << " )";
4068 SMESH_CATCH( SMESH::throwCorbaException );
4071 //================================================================================
4073 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4074 * ExceptSubMeshOrGroups
4076 //================================================================================
4078 void SMESH_MeshEditor_i::
4079 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4080 CORBA::Double theTolerance,
4081 SMESH::array_of_long_array_out theGroupsOfNodes,
4082 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4083 CORBA::Boolean theSeparateCornersAndMedium)
4084 throw (SALOME::SALOME_Exception)
4089 TIDSortedNodeSet nodes;
4090 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4092 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4094 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4096 while ( nodeIt->more() )
4097 nodes.erase( cast2Node( nodeIt->next() ));
4099 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4101 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4103 << theTolerance << ", "
4104 << theExceptSubMeshOrGroups << ", "
4105 << theSeparateCornersAndMedium << " )";
4107 SMESH_CATCH( SMESH::throwCorbaException );
4110 //=======================================================================
4111 //function : MergeNodes
4113 //=======================================================================
4115 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4116 const SMESH::ListOfIDSources& NodesToKeep)
4117 throw (SALOME::SALOME_Exception)
4122 SMESHDS_Mesh* aMesh = getMeshDS();
4124 TPythonDump aTPythonDump;
4125 aTPythonDump << this << ".MergeNodes([";
4127 TIDSortedNodeSet setOfNodesToKeep;
4128 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4130 prepareIdSource( NodesToKeep[i] );
4131 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
4132 while ( nodeIt->more() )
4133 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4136 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4137 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4139 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4140 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4141 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4142 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4144 CORBA::Long index = aNodeGroup[ j ];
4145 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4147 if ( setOfNodesToKeep.count( node ))
4148 aListOfNodes.push_front( node );
4150 aListOfNodes.push_back( node );
4153 if ( aListOfNodes.size() < 2 )
4154 aListOfListOfNodes.pop_back();
4156 if ( i > 0 ) aTPythonDump << ", ";
4157 aTPythonDump << aNodeGroup;
4160 getEditor().MergeNodes( aListOfListOfNodes );
4162 aTPythonDump << "], " << NodesToKeep << ")";
4164 declareMeshModified( /*isReComputeSafe=*/false );
4166 SMESH_CATCH( SMESH::throwCorbaException );
4169 //=======================================================================
4170 //function : FindEqualElements
4172 //=======================================================================
4174 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4175 SMESH::array_of_long_array_out GroupsOfElementsID)
4176 throw (SALOME::SALOME_Exception)
4181 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4182 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4184 TIDSortedElemSet elems;
4185 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4187 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4188 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4190 GroupsOfElementsID = new SMESH::array_of_long_array;
4191 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4193 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4194 aListOfListOfElementsID.begin();
4195 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4197 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4198 list<int>& listOfIDs = *arraysIt;
4199 aGroup.length( listOfIDs.size() );
4200 list<int>::iterator idIt = listOfIDs.begin();
4201 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4202 aGroup[ k ] = *idIt;
4205 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4209 SMESH_CATCH( SMESH::throwCorbaException );
4212 //=======================================================================
4213 //function : MergeElements
4215 //=======================================================================
4217 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4218 throw (SALOME::SALOME_Exception)
4223 TPythonDump aTPythonDump;
4224 aTPythonDump << this << ".MergeElements( [";
4226 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4228 for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) {
4229 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4230 aListOfListOfElementsID.push_back( list< int >() );
4231 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4232 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) {
4233 CORBA::Long id = anElemsIDGroup[ j ];
4234 aListOfElemsID.push_back( id );
4236 if ( aListOfElemsID.size() < 2 )
4237 aListOfListOfElementsID.pop_back();
4238 if ( i > 0 ) aTPythonDump << ", ";
4239 aTPythonDump << anElemsIDGroup;
4242 getEditor().MergeElements(aListOfListOfElementsID);
4244 declareMeshModified( /*isReComputeSafe=*/true );
4246 aTPythonDump << "] )";
4248 SMESH_CATCH( SMESH::throwCorbaException );
4251 //=======================================================================
4252 //function : MergeEqualElements
4254 //=======================================================================
4256 void SMESH_MeshEditor_i::MergeEqualElements()
4257 throw (SALOME::SALOME_Exception)
4262 getEditor().MergeEqualElements();
4264 declareMeshModified( /*isReComputeSafe=*/true );
4266 TPythonDump() << this << ".MergeEqualElements()";
4268 SMESH_CATCH( SMESH::throwCorbaException );
4271 //=============================================================================
4273 * Move the node to a given point
4275 //=============================================================================
4277 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4281 throw (SALOME::SALOME_Exception)
4284 initData(/*deleteSearchers=*/false);
4286 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4290 if ( theNodeSearcher )
4291 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4293 if ( myIsPreviewMode ) // make preview data
4295 // in a preview mesh, make edges linked to a node
4296 TPreviewMesh& tmpMesh = *getPreviewMesh();
4297 TIDSortedElemSet linkedNodes;
4298 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4299 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4300 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4301 for ( ; nIt != linkedNodes.end(); ++nIt )
4303 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4304 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4308 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4309 // fill preview data
4311 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4312 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4314 getMeshDS()->MoveNode(node, x, y, z);
4316 if ( !myIsPreviewMode )
4318 // Update Python script
4319 TPythonDump() << "isDone = " << this << ".MoveNode( "
4320 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4321 declareMeshModified( /*isReComputeSafe=*/false );
4324 SMESH_CATCH( SMESH::throwCorbaException );
4329 //================================================================================
4331 * \brief Return ID of node closest to a given point
4333 //================================================================================
4335 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4338 throw (SALOME::SALOME_Exception)
4341 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4343 if ( !theNodeSearcher ) {
4344 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4347 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4348 return node->GetID();
4350 SMESH_CATCH( SMESH::throwCorbaException );
4354 //================================================================================
4356 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4357 * move the node closest to the point to point's location and return ID of the node
4359 //================================================================================
4361 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4364 CORBA::Long theNodeID)
4365 throw (SALOME::SALOME_Exception)
4368 // We keep theNodeSearcher until any mesh modification:
4369 // 1) initData() deletes theNodeSearcher at any edition,
4370 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4372 initData(/*deleteSearchers=*/false);
4374 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4376 int nodeID = theNodeID;
4377 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4378 if ( !node ) // preview moving node
4380 if ( !theNodeSearcher ) {
4381 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4384 node = theNodeSearcher->FindClosestTo( p );
4387 nodeID = node->GetID();
4388 if ( myIsPreviewMode ) // make preview data
4390 // in a preview mesh, make edges linked to a node
4391 TPreviewMesh tmpMesh = *getPreviewMesh();
4392 TIDSortedElemSet linkedNodes;
4393 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4394 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4395 for ( ; nIt != linkedNodes.end(); ++nIt )
4397 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4398 tmpMesh.Copy( &edge );
4401 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4403 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4404 // fill preview data
4406 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4408 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4412 getMeshDS()->MoveNode(node, x, y, z);
4416 if ( !myIsPreviewMode )
4418 TPythonDump() << "nodeID = " << this
4419 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4420 << ", " << nodeID << " )";
4422 declareMeshModified( /*isReComputeSafe=*/false );
4427 SMESH_CATCH( SMESH::throwCorbaException );
4431 //=======================================================================
4433 * Return elements of given type where the given point is IN or ON.
4435 * 'ALL' type means elements of any type excluding nodes
4437 //=======================================================================
4439 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4442 SMESH::ElementType type)
4443 throw (SALOME::SALOME_Exception)
4446 SMESH::long_array_var res = new SMESH::long_array;
4447 vector< const SMDS_MeshElement* > foundElems;
4449 theSearchersDeleter.Set( myMesh );
4450 if ( !theElementSearcher ) {
4451 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4453 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4454 SMDSAbs_ElementType( type ),
4456 res->length( foundElems.size() );
4457 for ( size_t i = 0; i < foundElems.size(); ++i )
4458 res[i] = foundElems[i]->GetID();
4462 SMESH_CATCH( SMESH::throwCorbaException );
4466 //=======================================================================
4467 //function : FindAmongElementsByPoint
4468 //purpose : Searching among the given elements, return elements of given type
4469 // where the given point is IN or ON.
4470 // 'ALL' type means elements of any type excluding nodes
4471 //=======================================================================
4474 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4478 SMESH::ElementType type)
4479 throw (SALOME::SALOME_Exception)
4482 SMESH::long_array_var res = new SMESH::long_array;
4484 if ( type != SMESH::NODE )
4486 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4487 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4488 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4489 type != types[0] ) // but search of elements of dim > 0
4492 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4493 return FindElementsByPoint( x,y,z, type );
4495 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4497 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4498 if ( !theElementSearcher )
4500 // create a searcher from elementIDs
4501 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4502 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4504 if ( !idSourceToSet( elementIDs, meshDS, elements,
4505 ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ),
4506 /*emptyIfIsMesh=*/true))
4509 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4510 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4512 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4515 vector< const SMDS_MeshElement* > foundElems;
4517 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4518 SMDSAbs_ElementType( type ),
4520 res->length( foundElems.size() );
4521 for ( size_t i = 0; i < foundElems.size(); ++i )
4522 res[i] = foundElems[i]->GetID();
4526 SMESH_CATCH( SMESH::throwCorbaException );
4530 //=======================================================================
4531 //function : GetPointState
4532 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4533 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4534 //=======================================================================
4536 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4539 throw (SALOME::SALOME_Exception)
4542 theSearchersDeleter.Set( myMesh );
4543 if ( !theElementSearcher ) {
4544 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4546 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4548 SMESH_CATCH( SMESH::throwCorbaException );
4552 //=======================================================================
4553 //function : convError
4555 //=======================================================================
4557 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4559 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4563 RETCASE( SEW_BORDER1_NOT_FOUND );
4564 RETCASE( SEW_BORDER2_NOT_FOUND );
4565 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4566 RETCASE( SEW_BAD_SIDE_NODES );
4567 RETCASE( SEW_VOLUMES_TO_SPLIT );
4568 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4569 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4570 RETCASE( SEW_BAD_SIDE1_NODES );
4571 RETCASE( SEW_BAD_SIDE2_NODES );
4572 RETCASE( SEW_INTERNAL_ERROR );
4574 return SMESH::SMESH_MeshEditor::SEW_OK;
4577 //=======================================================================
4579 * Returns groups of FreeBorder's coincident within the given tolerance.
4580 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
4581 * to free borders being compared is used.
4583 //=======================================================================
4585 SMESH::CoincidentFreeBorders*
4586 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
4588 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
4592 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
4593 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
4595 // copy free borders
4596 aCFB->borders.length( cfb._borders.size() );
4597 for ( size_t i = 0; i < cfb._borders.size(); ++i )
4599 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
4600 SMESH::FreeBorder& aBRD = aCFB->borders[i];
4601 aBRD.nodeIDs.length( nodes.size() );
4602 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4603 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
4606 // copy coincident parts
4607 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
4608 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
4610 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
4611 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
4612 aGRP.length( grp.size() );
4613 for ( size_t iP = 0; iP < grp.size(); ++iP )
4615 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
4616 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4617 aPART.border = part._border;
4618 aPART.node1 = part._node1;
4619 aPART.node2 = part._node2;
4620 aPART.nodeLast = part._nodeLast;
4623 SMESH_CATCH( SMESH::doNothing );
4625 TPythonDump() << "CoincidentFreeBorders = "
4626 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
4628 return aCFB._retn();
4631 //=======================================================================
4633 * Sew FreeBorder's of each group
4635 //=======================================================================
4637 CORBA::Short SMESH_MeshEditor_i::
4638 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
4639 CORBA::Boolean createPolygons,
4640 CORBA::Boolean createPolyhedra)
4641 throw (SALOME::SALOME_Exception)
4643 CORBA::Short nbSewed = 0;
4645 SMESH_MeshAlgos::TFreeBorderVec groups;
4646 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
4648 // check the input and collect nodes
4649 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
4651 borderNodes.clear();
4652 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
4653 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
4655 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4656 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
4657 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
4659 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
4661 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
4662 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
4663 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
4664 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
4665 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
4666 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4668 // do not keep these nodes for further sewing as nodes can be removed by the sewing
4669 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
4670 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
4671 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
4673 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
4675 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
4677 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4679 borderNodes.push_back( n1 );
4680 borderNodes.push_back( n2 );
4681 borderNodes.push_back( n3 );
4683 groups.push_back( borderNodes );
4686 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
4687 // to get nodes that replace other nodes during merge we create 0D elements
4688 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
4691 vector< const SMDS_MeshElement* > tmp0Delems;
4692 for ( size_t i = 0; i < groups.size(); ++i )
4694 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4695 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4697 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
4699 tmp0Delems.push_back( it0D->next() );
4701 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
4705 // cout << endl << "INIT" << endl;
4706 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4708 // cout << i << " ";
4709 // if ( i % 3 == 0 ) cout << "^ ";
4710 // tmp0Delems[i]->GetNode(0)->Print( cout );
4715 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
4717 for ( size_t i = 0; i < groups.size(); ++i )
4719 bool isBordToBord = true;
4720 bool groupSewed = false;
4721 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4722 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
4724 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
4725 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
4726 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
4728 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
4729 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
4730 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
4732 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
4735 // TIDSortedElemSet emptySet, avoidSet;
4736 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
4738 // cout << "WRONG 2nd 1" << endl;
4739 // n0->Print( cout );
4740 // n1->Print( cout );
4742 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
4744 // cout << "WRONG 2nd 2" << endl;
4745 // n3->Print( cout );
4746 // n4->Print( cout );
4749 if ( !isBordToBord )
4751 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
4752 n2 = 0; // and n2 is not used
4754 // 1st border moves to 2nd
4755 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
4757 /*2ndIsFreeBorder=*/ isBordToBord,
4758 createPolygons, createPolyhedra);
4759 groupSewed = ( res == ok );
4761 isBordToBord = false;
4762 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
4763 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
4765 // cout << t << " ";
4766 // if ( t % 3 == 0 ) cout << "^ ";
4767 // tmp0Delems[t]->GetNode(0)->Print( cout );
4770 i0D += nodes.size();
4771 nbSewed += groupSewed;
4774 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
4775 << freeBorders << ", "
4776 << createPolygons << ", "
4777 << createPolyhedra << " )";
4779 SMESH_CATCH( SMESH::doNothing );
4781 declareMeshModified( /*isReComputeSafe=*/false );
4783 // remove tmp 0D elements
4785 set< const SMDS_MeshElement* > removed0D;
4786 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4788 if ( removed0D.insert( tmp0Delems[i] ).second )
4789 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
4791 SMESH_CATCH( SMESH::throwCorbaException );
4796 //=======================================================================
4797 //function : SewFreeBorders
4799 //=======================================================================
4801 SMESH::SMESH_MeshEditor::Sew_Error
4802 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4803 CORBA::Long SecondNodeID1,
4804 CORBA::Long LastNodeID1,
4805 CORBA::Long FirstNodeID2,
4806 CORBA::Long SecondNodeID2,
4807 CORBA::Long LastNodeID2,
4808 CORBA::Boolean CreatePolygons,
4809 CORBA::Boolean CreatePolyedrs)
4810 throw (SALOME::SALOME_Exception)
4815 SMESHDS_Mesh* aMesh = getMeshDS();
4817 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4818 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4819 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4820 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4821 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4822 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4824 if (!aBorderFirstNode ||
4825 !aBorderSecondNode||
4827 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4828 if (!aSide2FirstNode ||
4829 !aSide2SecondNode ||
4831 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4833 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4834 << FirstNodeID1 << ", "
4835 << SecondNodeID1 << ", "
4836 << LastNodeID1 << ", "
4837 << FirstNodeID2 << ", "
4838 << SecondNodeID2 << ", "
4839 << LastNodeID2 << ", "
4840 << CreatePolygons<< ", "
4841 << CreatePolyedrs<< " )";
4843 SMESH::SMESH_MeshEditor::Sew_Error error =
4844 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4855 declareMeshModified( /*isReComputeSafe=*/false );
4858 SMESH_CATCH( SMESH::throwCorbaException );
4859 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4863 //=======================================================================
4864 //function : SewConformFreeBorders
4866 //=======================================================================
4868 SMESH::SMESH_MeshEditor::Sew_Error
4869 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4870 CORBA::Long SecondNodeID1,
4871 CORBA::Long LastNodeID1,
4872 CORBA::Long FirstNodeID2,
4873 CORBA::Long SecondNodeID2)
4874 throw (SALOME::SALOME_Exception)
4879 SMESHDS_Mesh* aMesh = getMeshDS();
4881 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4882 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4883 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4884 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4885 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4886 const SMDS_MeshNode* aSide2ThirdNode = 0;
4888 if (!aBorderFirstNode ||
4889 !aBorderSecondNode||
4891 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4892 if (!aSide2FirstNode ||
4894 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4896 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4897 << FirstNodeID1 << ", "
4898 << SecondNodeID1 << ", "
4899 << LastNodeID1 << ", "
4900 << FirstNodeID2 << ", "
4901 << SecondNodeID2 << " )";
4903 SMESH::SMESH_MeshEditor::Sew_Error error =
4904 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4913 declareMeshModified( /*isReComputeSafe=*/false );
4916 SMESH_CATCH( SMESH::throwCorbaException );
4917 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4921 //=======================================================================
4922 //function : SewBorderToSide
4924 //=======================================================================
4926 SMESH::SMESH_MeshEditor::Sew_Error
4927 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4928 CORBA::Long SecondNodeIDOnFreeBorder,
4929 CORBA::Long LastNodeIDOnFreeBorder,
4930 CORBA::Long FirstNodeIDOnSide,
4931 CORBA::Long LastNodeIDOnSide,
4932 CORBA::Boolean CreatePolygons,
4933 CORBA::Boolean CreatePolyedrs)
4934 throw (SALOME::SALOME_Exception)
4939 SMESHDS_Mesh* aMesh = getMeshDS();
4941 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4942 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4943 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4944 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4945 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4946 const SMDS_MeshNode* aSide2ThirdNode = 0;
4948 if (!aBorderFirstNode ||
4949 !aBorderSecondNode||
4951 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4952 if (!aSide2FirstNode ||
4954 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4956 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4957 << FirstNodeIDOnFreeBorder << ", "
4958 << SecondNodeIDOnFreeBorder << ", "
4959 << LastNodeIDOnFreeBorder << ", "
4960 << FirstNodeIDOnSide << ", "
4961 << LastNodeIDOnSide << ", "
4962 << CreatePolygons << ", "
4963 << CreatePolyedrs << ") ";
4965 SMESH::SMESH_MeshEditor::Sew_Error error =
4966 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4976 declareMeshModified( /*isReComputeSafe=*/false );
4979 SMESH_CATCH( SMESH::throwCorbaException );
4980 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4984 //=======================================================================
4985 //function : SewSideElements
4987 //=======================================================================
4989 SMESH::SMESH_MeshEditor::Sew_Error
4990 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4991 const SMESH::long_array& IDsOfSide2Elements,
4992 CORBA::Long NodeID1OfSide1ToMerge,
4993 CORBA::Long NodeID1OfSide2ToMerge,
4994 CORBA::Long NodeID2OfSide1ToMerge,
4995 CORBA::Long NodeID2OfSide2ToMerge)
4996 throw (SALOME::SALOME_Exception)
5001 SMESHDS_Mesh* aMesh = getMeshDS();
5003 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5004 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5005 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5006 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5008 if (!aFirstNode1ToMerge ||
5009 !aFirstNode2ToMerge )
5010 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5011 if (!aSecondNode1ToMerge||
5012 !aSecondNode2ToMerge)
5013 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5015 TIDSortedElemSet aSide1Elems, aSide2Elems;
5016 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5017 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5019 TPythonDump() << "error = " << this << ".SewSideElements( "
5020 << IDsOfSide1Elements << ", "
5021 << IDsOfSide2Elements << ", "
5022 << NodeID1OfSide1ToMerge << ", "
5023 << NodeID1OfSide2ToMerge << ", "
5024 << NodeID2OfSide1ToMerge << ", "
5025 << NodeID2OfSide2ToMerge << ")";
5027 SMESH::SMESH_MeshEditor::Sew_Error error =
5028 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5031 aSecondNode1ToMerge,
5032 aSecondNode2ToMerge));
5034 declareMeshModified( /*isReComputeSafe=*/false );
5037 SMESH_CATCH( SMESH::throwCorbaException );
5038 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5041 //================================================================================
5043 * \brief Set new nodes for given element
5044 * \param ide - element id
5045 * \param newIDs - new node ids
5046 * \retval CORBA::Boolean - true if result is OK
5048 //================================================================================
5050 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5051 const SMESH::long_array& newIDs)
5052 throw (SALOME::SALOME_Exception)
5057 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5058 if(!elem) return false;
5060 int nbn = newIDs.length();
5062 vector<const SMDS_MeshNode*> aNodes(nbn);
5065 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5068 aNodes[nbn1] = aNode;
5071 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5072 << ide << ", " << newIDs << " )";
5074 MESSAGE("ChangeElementNodes");
5075 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5077 declareMeshModified( /*isReComputeSafe=*/ !res );
5081 SMESH_CATCH( SMESH::throwCorbaException );
5085 //=======================================================================
5087 * \brief Makes a part of the mesh quadratic or bi-quadratic
5089 //=======================================================================
5091 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5092 CORBA::Boolean theToBiQuad,
5093 SMESH::SMESH_IDSource_ptr theObject)
5094 throw (SALOME::SALOME_Exception)
5099 TIDSortedElemSet elems;
5101 if ( !( elemsOK = CORBA::is_nil( theObject )))
5103 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5104 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5108 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5109 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5111 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5112 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5114 declareMeshModified( /*isReComputeSafe=*/false );
5117 SMESH_CATCH( SMESH::throwCorbaException );
5120 //=======================================================================
5121 //function : ConvertFromQuadratic
5123 //=======================================================================
5125 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5126 throw (SALOME::SALOME_Exception)
5131 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5132 TPythonDump() << this << ".ConvertFromQuadratic()";
5133 declareMeshModified( /*isReComputeSafe=*/!isDone );
5136 SMESH_CATCH( SMESH::throwCorbaException );
5140 //=======================================================================
5141 //function : ConvertToQuadratic
5143 //=======================================================================
5145 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5146 throw (SALOME::SALOME_Exception)
5148 convertToQuadratic( theForce3d, false );
5149 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5152 //================================================================================
5154 * \brief Makes a part of the mesh quadratic
5156 //================================================================================
5158 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5159 SMESH::SMESH_IDSource_ptr theObject)
5160 throw (SALOME::SALOME_Exception)
5162 convertToQuadratic( theForce3d, false, theObject );
5163 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5166 //================================================================================
5168 * \brief Makes a part of the mesh bi-quadratic
5170 //================================================================================
5172 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5173 SMESH::SMESH_IDSource_ptr theObject)
5174 throw (SALOME::SALOME_Exception)
5176 convertToQuadratic( theForce3d, true, theObject );
5177 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5180 //================================================================================
5182 * \brief Makes a part of the mesh linear
5184 //================================================================================
5186 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5187 throw (SALOME::SALOME_Exception)
5194 TIDSortedElemSet elems;
5195 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5197 if ( elems.empty() )
5199 ConvertFromQuadratic();
5201 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5203 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5207 getEditor().ConvertFromQuadratic(elems);
5210 declareMeshModified( /*isReComputeSafe=*/false );
5212 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5214 SMESH_CATCH( SMESH::throwCorbaException );
5217 //=======================================================================
5218 //function : makeMesh
5219 //purpose : create a named imported mesh
5220 //=======================================================================
5222 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5224 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5225 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5226 SALOMEDS::Study_var study = gen->GetCurrentStudy();
5227 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5228 gen->SetName( meshSO, theMeshName, "Mesh" );
5229 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5231 return mesh._retn();
5234 //=======================================================================
5235 //function : dumpGroupsList
5237 //=======================================================================
5239 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5240 const SMESH::ListOfGroups * theGroupList)
5242 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5243 if ( isDumpGroupList )
5244 theDumpPython << theGroupList << " = ";
5247 //================================================================================
5249 \brief Generates the unique group name.
5250 \param thePrefix name prefix
5253 //================================================================================
5255 std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix)
5257 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5258 set<std::string> groupNames;
5260 // Get existing group names
5261 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5262 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5263 if (CORBA::is_nil(aGroup))
5266 CORBA::String_var name = aGroup->GetName();
5267 groupNames.insert( name.in() );
5271 std::string name = thePrefix;
5274 while (!groupNames.insert(name).second)
5275 name = SMESH_Comment( thePrefix ) << "_" << index++;
5280 //================================================================================
5282 * \brief Prepare SMESH_IDSource for work
5284 //================================================================================
5286 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5288 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5290 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5291 filter->SetMesh( mesh );
5294 //================================================================================
5296 * \brief Retrieve elements of given type from SMESH_IDSource
5298 //================================================================================
5300 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5301 const SMESHDS_Mesh* theMeshDS,
5302 TIDSortedElemSet& theElemSet,
5303 const SMDSAbs_ElementType theType,
5304 const bool emptyIfIsMesh,
5305 IDSource_Error* error)
5308 if ( error ) *error = IDSource_OK;
5310 if ( CORBA::is_nil( theIDSource ))
5312 if ( error ) *error = IDSource_INVALID;
5315 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5317 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5318 *error = IDSource_EMPTY;
5321 prepareIdSource( theIDSource );
5322 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5323 if ( anIDs->length() == 0 )
5325 if ( error ) *error = IDSource_EMPTY;
5328 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5329 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5331 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5333 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5337 if ( error ) *error = IDSource_INVALID;
5343 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5344 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5346 if ( error ) *error = IDSource_INVALID;
5353 //================================================================================
5355 * \brief Duplicates given elements, i.e. creates new elements based on the
5356 * same nodes as the given ones.
5357 * \param theElements - container of elements to duplicate.
5358 * \param theGroupName - a name of group to contain the generated elements.
5359 * If a group with such a name already exists, the new elements
5360 * are added to the existng group, else a new group is created.
5361 * If \a theGroupName is empty, new elements are not added
5363 * \return a group where the new elements are added. NULL if theGroupName == "".
5366 //================================================================================
5368 SMESH::SMESH_Group_ptr
5369 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5370 const char* theGroupName)
5371 throw (SALOME::SALOME_Exception)
5373 SMESH::SMESH_Group_var newGroup;
5380 TIDSortedElemSet elems;
5381 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5383 getEditor().DoubleElements( elems );
5385 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5388 SMESH::ElementType type =
5389 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5390 // find existing group
5391 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5392 for ( size_t i = 0; i < groups->length(); ++i )
5393 if ( groups[i]->GetType() == type )
5395 CORBA::String_var name = groups[i]->GetName();
5396 if ( strcmp( name, theGroupName ) == 0 ) {
5397 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5401 // create a new group
5402 if ( newGroup->_is_nil() )
5403 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5405 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5407 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5408 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5409 for ( int i = 1; i <= aSeq.Length(); i++ )
5410 groupDS->SMDSGroup().Add( aSeq(i) );
5415 if ( !newGroup->_is_nil() )
5416 pyDump << newGroup << " = ";
5417 pyDump << this << ".DoubleElements( "
5418 << theElements << ", " << "'" << theGroupName <<"')";
5420 SMESH_CATCH( SMESH::throwCorbaException );
5422 return newGroup._retn();
5425 //================================================================================
5427 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5428 \param theNodes - identifiers of nodes to be doubled
5429 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5430 nodes. If list of element identifiers is empty then nodes are doubled but
5431 they not assigned to elements
5432 \return TRUE if operation has been completed successfully, FALSE otherwise
5433 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5435 //================================================================================
5437 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5438 const SMESH::long_array& theModifiedElems )
5439 throw (SALOME::SALOME_Exception)
5444 list< int > aListOfNodes;
5446 for ( i = 0, n = theNodes.length(); i < n; i++ )
5447 aListOfNodes.push_back( theNodes[ i ] );
5449 list< int > aListOfElems;
5450 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5451 aListOfElems.push_back( theModifiedElems[ i ] );
5453 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5455 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5457 // Update Python script
5458 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5462 SMESH_CATCH( SMESH::throwCorbaException );
5466 //================================================================================
5468 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5469 This method provided for convenience works as DoubleNodes() described above.
5470 \param theNodeId - identifier of node to be doubled.
5471 \param theModifiedElems - identifiers of elements to be updated.
5472 \return TRUE if operation has been completed successfully, FALSE otherwise
5473 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5475 //================================================================================
5477 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5478 const SMESH::long_array& theModifiedElems )
5479 throw (SALOME::SALOME_Exception)
5482 SMESH::long_array_var aNodes = new SMESH::long_array;
5483 aNodes->length( 1 );
5484 aNodes[ 0 ] = theNodeId;
5486 TPythonDump pyDump; // suppress dump by the next line
5488 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5490 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5494 SMESH_CATCH( SMESH::throwCorbaException );
5498 //================================================================================
5500 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5501 This method provided for convenience works as DoubleNodes() described above.
5502 \param theNodes - group of nodes to be doubled.
5503 \param theModifiedElems - group of elements to be updated.
5504 \return TRUE if operation has been completed successfully, FALSE otherwise
5505 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5507 //================================================================================
5509 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5510 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5511 throw (SALOME::SALOME_Exception)
5514 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5517 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5518 SMESH::long_array_var aModifiedElems;
5519 if ( !CORBA::is_nil( theModifiedElems ) )
5520 aModifiedElems = theModifiedElems->GetListOfID();
5523 aModifiedElems = new SMESH::long_array;
5524 aModifiedElems->length( 0 );
5527 TPythonDump pyDump; // suppress dump by the next line
5529 bool done = DoubleNodes( aNodes, aModifiedElems );
5531 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5535 SMESH_CATCH( SMESH::throwCorbaException );
5539 //================================================================================
5541 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5542 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5543 * \param theNodes - group of nodes to be doubled.
5544 * \param theModifiedElems - group of elements to be updated.
5545 * \return a new group with newly created nodes
5546 * \sa DoubleNodeGroup()
5548 //================================================================================
5550 SMESH::SMESH_Group_ptr
5551 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5552 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5553 throw (SALOME::SALOME_Exception)
5556 SMESH::SMESH_Group_var aNewGroup;
5558 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5559 return aNewGroup._retn();
5562 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5563 SMESH::long_array_var aModifiedElems;
5564 if ( !CORBA::is_nil( theModifiedElems ) )
5565 aModifiedElems = theModifiedElems->GetListOfID();
5567 aModifiedElems = new SMESH::long_array;
5568 aModifiedElems->length( 0 );
5571 TPythonDump pyDump; // suppress dump by the next line
5573 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5576 // Create group with newly created nodes
5577 SMESH::long_array_var anIds = GetLastCreatedNodes();
5578 if (anIds->length() > 0) {
5579 std::string anUnindexedName (theNodes->GetName());
5580 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5581 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5582 aNewGroup->Add(anIds);
5583 pyDump << aNewGroup << " = ";
5587 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5588 << theModifiedElems << " )";
5590 return aNewGroup._retn();
5592 SMESH_CATCH( SMESH::throwCorbaException );
5596 //================================================================================
5598 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5599 This method provided for convenience works as DoubleNodes() described above.
5600 \param theNodes - list of groups of nodes to be doubled
5601 \param theModifiedElems - list of groups of elements to be updated.
5602 \return TRUE if operation has been completed successfully, FALSE otherwise
5603 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5605 //================================================================================
5607 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5608 const SMESH::ListOfGroups& theModifiedElems )
5609 throw (SALOME::SALOME_Exception)
5614 std::list< int > aNodes;
5616 for ( i = 0, n = theNodes.length(); i < n; i++ )
5618 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5619 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5621 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5622 for ( j = 0, m = aCurr->length(); j < m; j++ )
5623 aNodes.push_back( aCurr[ j ] );
5627 std::list< int > anElems;
5628 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5630 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5631 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5633 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5634 for ( j = 0, m = aCurr->length(); j < m; j++ )
5635 anElems.push_back( aCurr[ j ] );
5639 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5641 declareMeshModified( /*isReComputeSafe=*/false );
5643 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5647 SMESH_CATCH( SMESH::throwCorbaException );
5651 //================================================================================
5653 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5654 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5655 * \param theNodes - group of nodes to be doubled.
5656 * \param theModifiedElems - group of elements to be updated.
5657 * \return a new group with newly created nodes
5658 * \sa DoubleNodeGroups()
5660 //================================================================================
5662 SMESH::SMESH_Group_ptr
5663 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5664 const SMESH::ListOfGroups& theModifiedElems )
5665 throw (SALOME::SALOME_Exception)
5667 SMESH::SMESH_Group_var aNewGroup;
5669 TPythonDump pyDump; // suppress dump by the next line
5671 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5675 // Create group with newly created nodes
5676 SMESH::long_array_var anIds = GetLastCreatedNodes();
5677 if (anIds->length() > 0) {
5678 std::string anUnindexedName (theNodes[0]->GetName());
5679 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5680 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5681 aNewGroup->Add(anIds);
5682 pyDump << aNewGroup << " = ";
5686 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5687 << theModifiedElems << " )";
5689 return aNewGroup._retn();
5693 //================================================================================
5695 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5696 \param theElems - the list of elements (edges or faces) to be replicated
5697 The nodes for duplication could be found from these elements
5698 \param theNodesNot - list of nodes to NOT replicate
5699 \param theAffectedElems - the list of elements (cells and edges) to which the
5700 replicated nodes should be associated to.
5701 \return TRUE if operation has been completed successfully, FALSE otherwise
5702 \sa DoubleNodeGroup(), DoubleNodeGroups()
5704 //================================================================================
5706 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5707 const SMESH::long_array& theNodesNot,
5708 const SMESH::long_array& theAffectedElems )
5709 throw (SALOME::SALOME_Exception)
5714 SMESHDS_Mesh* aMeshDS = getMeshDS();
5715 TIDSortedElemSet anElems, aNodes, anAffected;
5716 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5717 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5718 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5720 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5722 // Update Python script
5723 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5724 << theNodesNot << ", " << theAffectedElems << " )";
5726 declareMeshModified( /*isReComputeSafe=*/false );
5729 SMESH_CATCH( SMESH::throwCorbaException );
5733 //================================================================================
5735 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5736 \param theElems - the list of elements (edges or faces) to be replicated
5737 The nodes for duplication could be found from these elements
5738 \param theNodesNot - list of nodes to NOT replicate
5739 \param theShape - shape to detect affected elements (element which geometric center
5740 located on or inside shape).
5741 The replicated nodes should be associated to affected elements.
5742 \return TRUE if operation has been completed successfully, FALSE otherwise
5743 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5745 //================================================================================
5747 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5748 const SMESH::long_array& theNodesNot,
5749 GEOM::GEOM_Object_ptr theShape )
5750 throw (SALOME::SALOME_Exception)
5756 SMESHDS_Mesh* aMeshDS = getMeshDS();
5757 TIDSortedElemSet anElems, aNodes;
5758 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5759 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5761 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5762 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5764 // Update Python script
5765 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5766 << theNodesNot << ", " << theShape << " )";
5768 declareMeshModified( /*isReComputeSafe=*/false );
5771 SMESH_CATCH( SMESH::throwCorbaException );
5775 //================================================================================
5777 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5778 \param theElems - group of of elements (edges or faces) to be replicated
5779 \param theNodesNot - group of nodes not to replicated
5780 \param theAffectedElems - group of elements to which the replicated nodes
5781 should be associated to.
5782 \return TRUE if operation has been completed successfully, FALSE otherwise
5783 \sa DoubleNodes(), DoubleNodeGroups()
5785 //================================================================================
5788 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5789 SMESH::SMESH_GroupBase_ptr theNodesNot,
5790 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5791 throw (SALOME::SALOME_Exception)
5794 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5800 SMESHDS_Mesh* aMeshDS = getMeshDS();
5801 TIDSortedElemSet anElems, aNodes, anAffected;
5802 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5803 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5804 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5806 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5808 // Update Python script
5809 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5810 << theNodesNot << ", " << theAffectedElems << " )";
5812 declareMeshModified( /*isReComputeSafe=*/false );
5815 SMESH_CATCH( SMESH::throwCorbaException );
5819 //================================================================================
5821 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5822 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5823 * \param theElems - group of of elements (edges or faces) to be replicated
5824 * \param theNodesNot - group of nodes not to replicated
5825 * \param theAffectedElems - group of elements to which the replicated nodes
5826 * should be associated to.
5827 * \return a new group with newly created elements
5828 * \sa DoubleNodeElemGroup()
5830 //================================================================================
5832 SMESH::SMESH_Group_ptr
5833 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5834 SMESH::SMESH_GroupBase_ptr theNodesNot,
5835 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5836 throw (SALOME::SALOME_Exception)
5839 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5843 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5844 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5846 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5848 << theNodesNot << ", "
5849 << theAffectedElems << " )";
5851 return elemGroup._retn();
5854 //================================================================================
5856 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5857 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5858 * \param theElems - group of of elements (edges or faces) to be replicated
5859 * \param theNodesNot - group of nodes not to replicated
5860 * \param theAffectedElems - group of elements to which the replicated nodes
5861 * should be associated to.
5862 * \return a new group with newly created elements
5863 * \sa DoubleNodeElemGroup()
5865 //================================================================================
5867 SMESH::ListOfGroups*
5868 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5869 SMESH::SMESH_GroupBase_ptr theNodesNot,
5870 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5871 CORBA::Boolean theElemGroupNeeded,
5872 CORBA::Boolean theNodeGroupNeeded)
5873 throw (SALOME::SALOME_Exception)
5876 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5877 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5878 aTwoGroups->length( 2 );
5880 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5881 return aTwoGroups._retn();
5886 SMESHDS_Mesh* aMeshDS = getMeshDS();
5887 TIDSortedElemSet anElems, aNodes, anAffected;
5888 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5889 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5890 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5893 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5895 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5901 // Create group with newly created elements
5902 CORBA::String_var elemGroupName = theElems->GetName();
5903 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
5904 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5906 SMESH::long_array_var anIds = GetLastCreatedElems();
5907 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5908 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5909 aNewElemGroup->Add(anIds);
5911 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5913 SMESH::long_array_var anIds = GetLastCreatedNodes();
5914 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5915 aNewNodeGroup->Add(anIds);
5919 // Update Python script
5922 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5923 else pyDump << aNewElemGroup << ", ";
5924 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5925 else pyDump << aNewNodeGroup << " ] = ";
5927 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5928 << theNodesNot << ", "
5929 << theAffectedElems << ", "
5930 << theElemGroupNeeded << ", "
5931 << theNodeGroupNeeded <<" )";
5933 aTwoGroups[0] = aNewElemGroup._retn();
5934 aTwoGroups[1] = aNewNodeGroup._retn();
5935 return aTwoGroups._retn();
5937 SMESH_CATCH( SMESH::throwCorbaException );
5941 //================================================================================
5943 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5944 \param theElems - group of of elements (edges or faces) to be replicated
5945 \param theNodesNot - group of nodes not to replicated
5946 \param theShape - shape to detect affected elements (element which geometric center
5947 located on or inside shape).
5948 The replicated nodes should be associated to affected elements.
5949 \return TRUE if operation has been completed successfully, FALSE otherwise
5950 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5952 //================================================================================
5955 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5956 SMESH::SMESH_GroupBase_ptr theNodesNot,
5957 GEOM::GEOM_Object_ptr theShape )
5958 throw (SALOME::SALOME_Exception)
5961 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5967 SMESHDS_Mesh* aMeshDS = getMeshDS();
5968 TIDSortedElemSet anElems, aNodes, anAffected;
5969 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5970 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5972 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5973 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5976 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5978 // Update Python script
5979 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5980 << theNodesNot << ", " << theShape << " )";
5983 SMESH_CATCH( SMESH::throwCorbaException );
5987 //================================================================================
5989 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5990 * \param [in] theGrpList - groups
5991 * \param [in] theMeshDS - mesh
5992 * \param [out] theElemSet - set of elements
5993 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5995 //================================================================================
5997 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5998 SMESHDS_Mesh* theMeshDS,
5999 TIDSortedElemSet& theElemSet,
6000 const bool theIsNodeGrp)
6002 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6004 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6005 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6006 : aGrp->GetType() != SMESH::NODE ) )
6008 SMESH::long_array_var anIDs = aGrp->GetIDs();
6009 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6014 //================================================================================
6016 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6017 This method provided for convenience works as DoubleNodes() described above.
6018 \param theElems - list of groups of elements (edges or faces) to be replicated
6019 \param theNodesNot - list of groups of nodes not to replicated
6020 \param theAffectedElems - group of elements to which the replicated nodes
6021 should be associated to.
6022 \return TRUE if operation has been completed successfully, FALSE otherwise
6023 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6025 //================================================================================
6028 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6029 const SMESH::ListOfGroups& theNodesNot,
6030 const SMESH::ListOfGroups& theAffectedElems)
6031 throw (SALOME::SALOME_Exception)
6037 SMESHDS_Mesh* aMeshDS = getMeshDS();
6038 TIDSortedElemSet anElems, aNodes, anAffected;
6039 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6040 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6041 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6043 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6045 // Update Python script
6046 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6047 << &theNodesNot << ", " << &theAffectedElems << " )";
6049 declareMeshModified( /*isReComputeSafe=*/false );
6052 SMESH_CATCH( SMESH::throwCorbaException );
6056 //================================================================================
6058 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6059 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6060 \param theElems - list of groups of elements (edges or faces) to be replicated
6061 \param theNodesNot - list of groups of nodes not to replicated
6062 \param theAffectedElems - group of elements to which the replicated nodes
6063 should be associated to.
6064 * \return a new group with newly created elements
6065 * \sa DoubleNodeElemGroups()
6067 //================================================================================
6069 SMESH::SMESH_Group_ptr
6070 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6071 const SMESH::ListOfGroups& theNodesNot,
6072 const SMESH::ListOfGroups& theAffectedElems)
6073 throw (SALOME::SALOME_Exception)
6076 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6080 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6081 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6083 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6085 << theNodesNot << ", "
6086 << theAffectedElems << " )";
6088 return elemGroup._retn();
6091 //================================================================================
6093 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6094 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6095 \param theElems - list of groups of elements (edges or faces) to be replicated
6096 \param theNodesNot - list of groups of nodes not to replicated
6097 \param theAffectedElems - group of elements to which the replicated nodes
6098 should be associated to.
6099 * \return a new group with newly created elements
6100 * \sa DoubleNodeElemGroups()
6102 //================================================================================
6104 SMESH::ListOfGroups*
6105 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6106 const SMESH::ListOfGroups& theNodesNot,
6107 const SMESH::ListOfGroups& theAffectedElems,
6108 CORBA::Boolean theElemGroupNeeded,
6109 CORBA::Boolean theNodeGroupNeeded)
6110 throw (SALOME::SALOME_Exception)
6113 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6114 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6115 aTwoGroups->length( 2 );
6120 SMESHDS_Mesh* aMeshDS = getMeshDS();
6121 TIDSortedElemSet anElems, aNodes, anAffected;
6122 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6123 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6124 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6126 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6128 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6133 // Create group with newly created elements
6134 CORBA::String_var elemGroupName = theElems[0]->GetName();
6135 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6136 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6138 SMESH::long_array_var anIds = GetLastCreatedElems();
6139 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6140 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6141 aNewElemGroup->Add(anIds);
6143 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6145 SMESH::long_array_var anIds = GetLastCreatedNodes();
6146 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6147 aNewNodeGroup->Add(anIds);
6151 // Update Python script
6154 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6155 else pyDump << aNewElemGroup << ", ";
6156 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6157 else pyDump << aNewNodeGroup << " ] = ";
6159 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6160 << &theNodesNot << ", "
6161 << &theAffectedElems << ", "
6162 << theElemGroupNeeded << ", "
6163 << theNodeGroupNeeded << " )";
6165 aTwoGroups[0] = aNewElemGroup._retn();
6166 aTwoGroups[1] = aNewNodeGroup._retn();
6167 return aTwoGroups._retn();
6169 SMESH_CATCH( SMESH::throwCorbaException );
6173 //================================================================================
6175 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6176 This method provided for convenience works as DoubleNodes() described above.
6177 \param theElems - list of groups of elements (edges or faces) to be replicated
6178 \param theNodesNot - list of groups of nodes not to replicated
6179 \param theShape - shape to detect affected elements (element which geometric center
6180 located on or inside shape).
6181 The replicated nodes should be associated to affected elements.
6182 \return TRUE if operation has been completed successfully, FALSE otherwise
6183 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6185 //================================================================================
6188 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6189 const SMESH::ListOfGroups& theNodesNot,
6190 GEOM::GEOM_Object_ptr theShape )
6191 throw (SALOME::SALOME_Exception)
6197 SMESHDS_Mesh* aMeshDS = getMeshDS();
6198 TIDSortedElemSet anElems, aNodes;
6199 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6200 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6202 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6203 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6205 // Update Python script
6206 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6207 << &theNodesNot << ", " << theShape << " )";
6209 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6212 SMESH_CATCH( SMESH::throwCorbaException );
6216 //================================================================================
6218 \brief Identify the elements that will be affected by node duplication (actual
6219 duplication is not performed.
6220 This method is the first step of DoubleNodeElemGroupsInRegion.
6221 \param theElems - list of groups of elements (edges or faces) to be replicated
6222 \param theNodesNot - list of groups of nodes not to replicated
6223 \param theShape - shape to detect affected elements (element which geometric center
6224 located on or inside shape).
6225 The replicated nodes should be associated to affected elements.
6226 \return groups of affected elements
6227 \sa DoubleNodeElemGroupsInRegion()
6229 //================================================================================
6230 SMESH::ListOfGroups*
6231 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6232 const SMESH::ListOfGroups& theNodesNot,
6233 GEOM::GEOM_Object_ptr theShape )
6234 throw (SALOME::SALOME_Exception)
6237 MESSAGE("AffectedElemGroupsInRegion");
6238 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6239 bool isEdgeGroup = false;
6240 bool isFaceGroup = false;
6241 bool isVolumeGroup = false;
6242 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6243 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6244 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6248 ::SMESH_MeshEditor aMeshEditor(myMesh);
6250 SMESHDS_Mesh* aMeshDS = getMeshDS();
6251 TIDSortedElemSet anElems, aNodes;
6252 listOfGroupToSet(theElems, aMeshDS, anElems, false);
6253 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6255 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6256 TIDSortedElemSet anAffected;
6257 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6260 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6265 int lg = anAffected.size();
6266 MESSAGE("lg="<< lg);
6267 SMESH::long_array_var volumeIds = new SMESH::long_array;
6268 volumeIds->length(lg);
6269 SMESH::long_array_var faceIds = new SMESH::long_array;
6270 faceIds->length(lg);
6271 SMESH::long_array_var edgeIds = new SMESH::long_array;
6272 edgeIds->length(lg);
6277 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6278 for (; eIt != anAffected.end(); ++eIt)
6280 const SMDS_MeshElement* anElem = *eIt;
6283 int elemId = anElem->GetID();
6284 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6285 volumeIds[ivol++] = elemId;
6286 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6287 faceIds[iface++] = elemId;
6288 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6289 edgeIds[iedge++] = elemId;
6291 volumeIds->length(ivol);
6292 faceIds->length(iface);
6293 edgeIds->length(iedge);
6295 aNewVolumeGroup->Add(volumeIds);
6296 aNewFaceGroup->Add(faceIds);
6297 aNewEdgeGroup->Add(edgeIds);
6298 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6299 isFaceGroup = (aNewFaceGroup->Size() > 0);
6300 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6304 if (isEdgeGroup) nbGroups++;
6305 if (isFaceGroup) nbGroups++;
6306 if (isVolumeGroup) nbGroups++;
6307 aListOfGroups->length(nbGroups);
6310 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6311 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6312 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6314 // Update Python script
6317 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6318 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6319 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6321 pyDump << this << ".AffectedElemGroupsInRegion( "
6322 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6324 return aListOfGroups._retn();
6326 SMESH_CATCH( SMESH::throwCorbaException );
6330 //================================================================================
6332 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6333 The created 2D mesh elements based on nodes of free faces of boundary volumes
6334 \return TRUE if operation has been completed successfully, FALSE otherwise
6336 //================================================================================
6338 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6339 throw (SALOME::SALOME_Exception)
6344 bool aResult = getEditor().Make2DMeshFrom3D();
6346 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6348 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6351 SMESH_CATCH( SMESH::throwCorbaException );
6355 //================================================================================
6357 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6358 * The list of groups must contain at least two groups. The groups have to be disjoint:
6359 * no common element into two different groups.
6360 * The nodes of the internal faces at the boundaries of the groups are doubled.
6361 * Optionally, the internal faces are replaced by flat elements.
6362 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6363 * The flat elements are stored in groups of volumes.
6364 * These groups are named according to the position of the group in the list:
6365 * 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.
6366 * 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.
6367 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6368 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6369 * \param theDomains - list of groups of volumes
6370 * \param createJointElems - if TRUE, create the elements
6371 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6372 * the boundary between \a theDomains and the rest mesh
6373 * \return TRUE if operation has been completed successfully, FALSE otherwise
6375 //================================================================================
6378 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6379 CORBA::Boolean createJointElems,
6380 CORBA::Boolean onAllBoundaries )
6381 throw (SALOME::SALOME_Exception)
6388 SMESHDS_Mesh* aMeshDS = getMeshDS();
6390 // MESSAGE("theDomains.length = "<<theDomains.length());
6391 if ( theDomains.length() <= 1 && !onAllBoundaries )
6392 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6394 vector<TIDSortedElemSet> domains;
6395 domains.resize( theDomains.length() );
6397 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6399 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6400 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6402 // if ( aGrp->GetType() != SMESH::VOLUME )
6403 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6404 SMESH::long_array_var anIDs = aGrp->GetIDs();
6405 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6409 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6410 // TODO publish the groups of flat elements in study
6412 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6414 // Update Python script
6415 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6416 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6418 SMESH_CATCH( SMESH::throwCorbaException );
6420 myMesh_i->CreateGroupServants(); // publish created groups if any
6425 //================================================================================
6427 * \brief Double nodes on some external faces and create flat elements.
6428 * Flat elements are mainly used by some types of mechanic calculations.
6430 * Each group of the list must be constituted of faces.
6431 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6432 * @param theGroupsOfFaces - list of groups of faces
6433 * @return TRUE if operation has been completed successfully, FALSE otherwise
6435 //================================================================================
6438 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6439 throw (SALOME::SALOME_Exception)
6444 SMESHDS_Mesh* aMeshDS = getMeshDS();
6446 vector<TIDSortedElemSet> faceGroups;
6449 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6451 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6452 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6454 TIDSortedElemSet faceGroup;
6456 faceGroups.push_back(faceGroup);
6457 SMESH::long_array_var anIDs = aGrp->GetIDs();
6458 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6462 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6463 // TODO publish the groups of flat elements in study
6465 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6467 // Update Python script
6468 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6471 SMESH_CATCH( SMESH::throwCorbaException );
6475 //================================================================================
6477 * \brief Identify all the elements around a geom shape, get the faces delimiting
6480 * Build groups of volume to remove, groups of faces to replace on the skin of the
6481 * object, groups of faces to remove inside the object, (idem edges).
6482 * Build ordered list of nodes at the border of each group of faces to replace
6483 * (to be used to build a geom subshape).
6485 //================================================================================
6487 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6488 GEOM::GEOM_Object_ptr theShape,
6489 const char* groupName,
6490 const SMESH::double_array& theNodesCoords,
6491 SMESH::array_of_long_array_out GroupsOfNodes)
6492 throw (SALOME::SALOME_Exception)
6497 std::vector<std::vector<int> > aListOfListOfNodes;
6498 ::SMESH_MeshEditor aMeshEditor( myMesh );
6500 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6501 if ( !theNodeSearcher )
6502 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6504 vector<double> nodesCoords;
6505 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6507 nodesCoords.push_back( theNodesCoords[i] );
6510 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6511 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6512 nodesCoords, aListOfListOfNodes);
6514 GroupsOfNodes = new SMESH::array_of_long_array;
6515 GroupsOfNodes->length( aListOfListOfNodes.size() );
6516 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6517 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6519 vector<int>& aListOfNodes = *llIt;
6520 vector<int>::iterator lIt = aListOfNodes.begin();;
6521 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6522 aGroup.length( aListOfNodes.size() );
6523 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6524 aGroup[ j ] = (*lIt);
6526 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6529 << ", '" << groupName << "', "
6530 << theNodesCoords << " )";
6532 SMESH_CATCH( SMESH::throwCorbaException );
6535 // issue 20749 ===================================================================
6537 * \brief Creates missing boundary elements
6538 * \param elements - elements whose boundary is to be checked
6539 * \param dimension - defines type of boundary elements to create
6540 * \param groupName - a name of group to store created boundary elements in,
6541 * "" means not to create the group
6542 * \param meshName - a name of new mesh to store created boundary elements in,
6543 * "" means not to create the new mesh
6544 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6545 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6546 * boundary elements will be copied into the new mesh
6547 * \param group - returns the create group, if any
6548 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6550 // ================================================================================
6552 SMESH::SMESH_Mesh_ptr
6553 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6554 SMESH::Bnd_Dimension dim,
6555 const char* groupName,
6556 const char* meshName,
6557 CORBA::Boolean toCopyElements,
6558 CORBA::Boolean toCopyExistingBondary,
6559 SMESH::SMESH_Group_out group)
6560 throw (SALOME::SALOME_Exception)
6565 if ( dim > SMESH::BND_1DFROM2D )
6566 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6568 SMESHDS_Mesh* aMeshDS = getMeshDS();
6570 SMESH::SMESH_Mesh_var mesh_var;
6571 SMESH::SMESH_Group_var group_var;
6575 TIDSortedElemSet elements;
6576 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6577 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6581 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6582 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6584 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6586 // group of new boundary elements
6587 SMESH_Group* smesh_group = 0;
6588 if ( strlen(groupName) )
6590 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6591 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6592 smesh_group = group_i->GetSmeshGroup();
6596 getEditor().MakeBoundaryMesh( elements,
6597 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6601 toCopyExistingBondary);
6604 smesh_mesh->GetMeshDS()->Modified();
6607 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6609 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6610 if ( mesh_var->_is_nil() )
6611 pyDump << myMesh_i->_this() << ", ";
6613 pyDump << mesh_var << ", ";
6614 if ( group_var->_is_nil() )
6615 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6617 pyDump << group_var << " = ";
6618 pyDump << this << ".MakeBoundaryMesh( "
6620 << "SMESH." << dimName[int(dim)] << ", "
6621 << "'" << groupName << "', "
6622 << "'" << meshName<< "', "
6623 << toCopyElements << ", "
6624 << toCopyExistingBondary << ")";
6626 group = group_var._retn();
6627 return mesh_var._retn();
6629 SMESH_CATCH( SMESH::throwCorbaException );
6630 return SMESH::SMESH_Mesh::_nil();
6633 //================================================================================
6635 * \brief Creates missing boundary elements
6636 * \param dimension - defines type of boundary elements to create
6637 * \param groupName - a name of group to store all boundary elements in,
6638 * "" means not to create the group
6639 * \param meshName - a name of a new mesh, which is a copy of the initial
6640 * mesh + created boundary elements; "" means not to create the new mesh
6641 * \param toCopyAll - if true, the whole initial mesh will be copied into
6642 * the new mesh else only boundary elements will be copied into the new mesh
6643 * \param groups - optional groups of elements to make boundary around
6644 * \param mesh - returns the mesh where elements were added to
6645 * \param group - returns the created group, if any
6646 * \retval long - number of added boundary elements
6648 //================================================================================
6650 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6651 const char* groupName,
6652 const char* meshName,
6653 CORBA::Boolean toCopyAll,
6654 const SMESH::ListOfIDSources& groups,
6655 SMESH::SMESH_Mesh_out mesh,
6656 SMESH::SMESH_Group_out group)
6657 throw (SALOME::SALOME_Exception)
6662 if ( dim > SMESH::BND_1DFROM2D )
6663 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6665 // separate groups belonging to this and other mesh
6666 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6667 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6668 groupsOfThisMesh ->length( groups.length() );
6669 groupsOfOtherMesh->length( groups.length() );
6670 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6671 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
6673 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6674 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6675 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6677 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6678 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6679 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6681 groupsOfThisMesh->length( nbGroups );
6682 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6687 if ( nbGroupsOfOtherMesh > 0 )
6689 // process groups belonging to another mesh
6690 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6691 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6692 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6693 groupsOfOtherMesh, mesh, group );
6696 SMESH::SMESH_Mesh_var mesh_var;
6697 SMESH::SMESH_Group_var group_var;
6700 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6701 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6705 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6707 /*toCopyGroups=*/false,
6708 /*toKeepIDs=*/true);
6710 mesh_var = makeMesh(meshName);
6712 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6713 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6716 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6717 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6719 // group of boundary elements
6720 SMESH_Group* smesh_group = 0;
6721 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6722 if ( strlen(groupName) )
6724 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6725 group_var = mesh_i->CreateGroup( groupType, groupName );
6726 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6727 smesh_group = group_i->GetSmeshGroup();
6730 TIDSortedElemSet elements;
6732 if ( groups.length() > 0 )
6734 for ( int i = 0; i < nbGroups; ++i )
6737 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6739 SMESH::Bnd_Dimension bdim =
6740 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6741 nbAdded += getEditor().MakeBoundaryMesh( elements,
6742 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6745 /*toCopyElements=*/false,
6746 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6747 /*toAddExistingBondary=*/true,
6748 /*aroundElements=*/true);
6754 nbAdded += getEditor().MakeBoundaryMesh( elements,
6755 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6758 /*toCopyElements=*/false,
6759 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6760 /*toAddExistingBondary=*/true);
6762 tgtMesh->GetMeshDS()->Modified();
6764 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6766 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6767 pyDump << "nbAdded, ";
6768 if ( mesh_var->_is_nil() )
6769 pyDump << myMesh_i->_this() << ", ";
6771 pyDump << mesh_var << ", ";
6772 if ( group_var->_is_nil() )
6773 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6775 pyDump << group_var << " = ";
6776 pyDump << this << ".MakeBoundaryElements( "
6777 << "SMESH." << dimName[int(dim)] << ", "
6778 << "'" << groupName << "', "
6779 << "'" << meshName<< "', "
6780 << toCopyAll << ", "
6783 mesh = mesh_var._retn();
6784 group = group_var._retn();
6787 SMESH_CATCH( SMESH::throwCorbaException );