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 LinearVariation = false,
2488 CORBA::Boolean ByAverageNormal = false,
2489 CORBA::Boolean UseInputElemsOnly = false,
2490 CORBA::Long Flags = 0,
2491 CORBA::Boolean MakeBoundary = true )
2493 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2494 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2495 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2496 if ( LinearVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2497 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2501 ExtrusionParams(const SMESH::DirStruct & theDir,
2502 CORBA::Long theNbOfSteps,
2503 const SMESH::double_array & theScaleFactors,
2504 CORBA::Boolean theLinearVariation,
2505 const SMESH::double_array & theBasePoint,
2506 CORBA::Boolean theMakeGroups):
2507 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2511 toList( theScaleFactors ),
2512 TBasePoint( theBasePoint ),
2513 makeFlags( theMakeGroups, theLinearVariation )),
2514 myIsExtrusionByNormal( false )
2518 ExtrusionParams(const SMESH::DirStruct & theDir,
2519 CORBA::Long theNbOfSteps,
2520 CORBA::Boolean theMakeGroups,
2521 CORBA::Long theExtrFlags,
2522 CORBA::Double theSewTolerance):
2523 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2527 std::list<double>(),
2529 makeFlags( theMakeGroups, false, false, false,
2530 theExtrFlags, false ),
2532 myIsExtrusionByNormal( false )
2535 // params for extrusion by normal
2536 ExtrusionParams(CORBA::Double theStepSize,
2537 CORBA::Long theNbOfSteps,
2538 CORBA::Short theDim,
2539 CORBA::Boolean theByAverageNormal,
2540 CORBA::Boolean theUseInputElemsOnly,
2541 CORBA::Boolean theMakeGroups ):
2542 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2544 makeFlags( theMakeGroups, false,
2545 theByAverageNormal, theUseInputElemsOnly ),
2547 myIsExtrusionByNormal( true )
2553 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2558 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2560 std::list<double> scales;
2561 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2562 scales.push_back( theScaleFactors[i] );
2566 // structure used to convert SMESH::double_array to gp_XYZ*
2570 TBasePoint( const SMESH::double_array & theBasePoint )
2573 if ( theBasePoint.length() == 3 )
2575 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2579 operator const gp_XYZ*() const { return pp; }
2584 //=======================================================================
2586 * \brief Generate dim+1 elements by extrusion of elements along vector
2587 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2588 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2589 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2590 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2591 * \param [in] nbOfSteps - number of elements to generate from one element
2592 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2593 * corresponding to groups the input elements included in.
2594 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2596 //=======================================================================
2598 SMESH::ListOfGroups*
2599 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2600 const SMESH::ListOfIDSources & theEdges,
2601 const SMESH::ListOfIDSources & theFaces,
2602 const SMESH::DirStruct & theStepVector,
2603 CORBA::Long theNbOfSteps,
2604 const SMESH::double_array & theScaleFactors,
2605 CORBA::Boolean theLinearVariation,
2606 const SMESH::double_array & theBasePoint,
2607 CORBA::Boolean theToMakeGroups)
2608 throw (SALOME::SALOME_Exception)
2613 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
2614 theLinearVariation, theBasePoint, theToMakeGroups );
2616 TIDSortedElemSet elemsNodes[2];
2617 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2618 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2619 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2621 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2622 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2623 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2624 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2626 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2627 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2628 if ( myIsPreviewMode )
2630 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2631 // previewType = SMDSAbs_Edge;
2633 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2634 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2635 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2636 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2637 workElements = & copyElements[0];
2639 params.SetNoGroups();
2641 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2643 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2644 ::SMESH_MeshEditor::PGroupIDs groupIds =
2645 getEditor().ExtrusionSweep( workElements, params, aHistory );
2647 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2649 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2651 if ( !myIsPreviewMode )
2653 dumpGroupsList( aPythonDump, aGroups );
2654 aPythonDump << this<< ".ExtrusionSweepObjects( "
2658 << theStepVector << ", "
2659 << TVar( theNbOfSteps ) << ", "
2660 << theToMakeGroups << " )";
2664 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2667 return aGroups ? aGroups : new SMESH::ListOfGroups;
2669 SMESH_CATCH( SMESH::throwCorbaException );
2673 //=======================================================================
2674 //function : ExtrusionByNormal
2676 //=======================================================================
2678 SMESH::ListOfGroups*
2679 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2680 CORBA::Double stepSize,
2681 CORBA::Long nbOfSteps,
2682 CORBA::Boolean byAverageNormal,
2683 CORBA::Boolean useInputElemsOnly,
2684 CORBA::Boolean makeGroups,
2686 throw (SALOME::SALOME_Exception)
2691 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2693 ExtrusionParams params( stepSize, nbOfSteps, dim,
2694 byAverageNormal, useInputElemsOnly, makeGroups );
2696 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2697 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2699 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2700 if (( elemTypes->length() == 1 ) &&
2701 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2702 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2705 TIDSortedElemSet elemsNodes[2];
2706 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2707 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2709 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2710 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2711 if ( myIsPreviewMode )
2713 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2714 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2715 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2716 workElements = & copyElements[0];
2718 params.SetNoGroups();
2721 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2722 ::SMESH_MeshEditor::PGroupIDs groupIds =
2723 getEditor().ExtrusionSweep( workElements, params, aHistory );
2725 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2727 if (!myIsPreviewMode) {
2728 dumpGroupsList(aPythonDump, aGroups);
2729 aPythonDump << this << ".ExtrusionByNormal( " << objects
2730 << ", " << TVar( stepSize )
2731 << ", " << TVar( nbOfSteps )
2732 << ", " << byAverageNormal
2733 << ", " << useInputElemsOnly
2734 << ", " << makeGroups
2740 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2743 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2745 return aGroups ? aGroups : new SMESH::ListOfGroups;
2747 SMESH_CATCH( SMESH::throwCorbaException );
2751 //=======================================================================
2752 //function : AdvancedExtrusion
2754 //=======================================================================
2756 SMESH::ListOfGroups*
2757 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2758 const SMESH::DirStruct & theStepVector,
2759 CORBA::Long theNbOfSteps,
2760 CORBA::Long theExtrFlags,
2761 CORBA::Double theSewTolerance,
2762 CORBA::Boolean theMakeGroups)
2763 throw (SALOME::SALOME_Exception)
2768 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2770 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2771 theExtrFlags, theSewTolerance );
2773 TIDSortedElemSet elemsNodes[2];
2774 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2776 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2777 ::SMESH_MeshEditor::PGroupIDs groupIds =
2778 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2780 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2782 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2784 if ( !myIsPreviewMode ) {
2785 dumpGroupsList(aPythonDump, aGroups);
2786 aPythonDump << this << ".AdvancedExtrusion( "
2787 << theIDsOfElements << ", "
2788 << theStepVector << ", "
2789 << theNbOfSteps << ", "
2790 << theExtrFlags << ", "
2791 << theSewTolerance << ", "
2792 << theMakeGroups << " )";
2796 getPreviewMesh()->Remove( SMDSAbs_Volume );
2799 return aGroups ? aGroups : new SMESH::ListOfGroups;
2801 SMESH_CATCH( SMESH::throwCorbaException );
2805 //================================================================================
2807 * \brief Convert extrusion error to IDL enum
2809 //================================================================================
2813 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2815 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2819 RETCASE( EXTR_NO_ELEMENTS );
2820 RETCASE( EXTR_PATH_NOT_EDGE );
2821 RETCASE( EXTR_BAD_PATH_SHAPE );
2822 RETCASE( EXTR_BAD_STARTING_NODE );
2823 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2824 RETCASE( EXTR_CANT_GET_TANGENT );
2826 return SMESH::SMESH_MeshEditor::EXTR_OK;
2830 //=======================================================================
2831 //function : extrusionAlongPath
2833 //=======================================================================
2834 SMESH::ListOfGroups*
2835 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2836 const SMESH::ListOfIDSources & theEdges,
2837 const SMESH::ListOfIDSources & theFaces,
2838 SMESH::SMESH_IDSource_ptr thePathMesh,
2839 GEOM::GEOM_Object_ptr thePathShape,
2840 CORBA::Long theNodeStart,
2841 CORBA::Boolean theHasAngles,
2842 const SMESH::double_array & theAngles,
2843 CORBA::Boolean theLinearVariation,
2844 CORBA::Boolean theHasRefPoint,
2845 const SMESH::PointStruct & theRefPoint,
2847 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2848 throw (SALOME::SALOME_Exception)
2853 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2855 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2856 if ( thePathMesh->_is_nil() )
2857 return aGroups._retn();
2860 SMESH_subMesh* aSubMesh = 0;
2861 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2862 if ( thePathShape->_is_nil() )
2864 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2865 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2867 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2868 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2869 if ( !aMeshImp ) return aGroups._retn();
2870 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2871 if ( !aSubMesh ) return aGroups._retn();
2873 else if ( !aMeshImp ||
2874 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2876 return aGroups._retn();
2881 if ( !aMeshImp ) return aGroups._retn();
2882 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2883 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2884 if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
2885 return aGroups._retn();
2888 SMDS_MeshNode* nodeStart =
2889 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2891 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2892 return aGroups._retn();
2895 TIDSortedElemSet elemsNodes[2];
2896 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2897 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2898 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2900 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2901 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2902 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2903 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2905 list<double> angles;
2906 for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) {
2907 angles.push_back( theAngles[i] );
2910 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2912 int nbOldGroups = myMesh->NbGroup();
2914 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2915 if ( myIsPreviewMode )
2917 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2918 TPreviewMesh * tmpMesh = getPreviewMesh();
2919 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2920 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2921 workElements = & copyElements[0];
2922 theMakeGroups = false;
2925 ::SMESH_MeshEditor::Extrusion_Error error;
2927 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2928 theHasAngles, angles, theLinearVariation,
2929 theHasRefPoint, refPnt, theMakeGroups );
2931 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2932 theHasAngles, angles, theLinearVariation,
2933 theHasRefPoint, refPnt, theMakeGroups );
2935 declareMeshModified( /*isReComputeSafe=*/true );
2936 theError = convExtrError( error );
2938 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2939 if ( theMakeGroups ) {
2940 list<int> groupIDs = myMesh->GetGroupIds();
2941 list<int>::iterator newBegin = groupIDs.begin();
2942 std::advance( newBegin, nbOldGroups ); // skip old groups
2943 groupIDs.erase( groupIDs.begin(), newBegin );
2944 aGroups = getGroups( & groupIDs );
2945 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2948 if ( !myIsPreviewMode ) {
2949 aPythonDump << "(" << aGroups << ", error) = "
2950 << this << ".ExtrusionAlongPathObjects( "
2954 << thePathMesh << ", "
2955 << thePathShape << ", "
2956 << theNodeStart << ", "
2957 << theHasAngles << ", "
2958 << TVar( theAngles ) << ", "
2959 << theLinearVariation << ", "
2960 << theHasRefPoint << ", "
2961 << "SMESH.PointStruct( "
2962 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2963 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2964 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2965 << theMakeGroups << " )";
2969 getPreviewMesh()->Remove( SMDSAbs_Volume );
2972 return aGroups._retn();
2974 SMESH_CATCH( SMESH::throwCorbaException );
2978 //================================================================================
2980 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2981 * of given angles along path steps
2982 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2983 * which proceeds the extrusion
2984 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2985 * is used to define the sub-mesh for the path
2987 //================================================================================
2989 SMESH::double_array*
2990 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2991 GEOM::GEOM_Object_ptr thePathShape,
2992 const SMESH::double_array & theAngles)
2994 SMESH::double_array_var aResult = new SMESH::double_array();
2995 int nbAngles = theAngles.length();
2996 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2998 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2999 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3000 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3001 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3002 return aResult._retn();
3003 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3004 if ( nbSteps == nbAngles )
3006 aResult.inout() = theAngles;
3010 aResult->length( nbSteps );
3011 double rAn2St = double( nbAngles ) / double( nbSteps );
3012 double angPrev = 0, angle;
3013 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3015 double angCur = rAn2St * ( iSt+1 );
3016 double angCurFloor = floor( angCur );
3017 double angPrevFloor = floor( angPrev );
3018 if ( angPrevFloor == angCurFloor )
3019 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3022 int iP = int( angPrevFloor );
3023 double angPrevCeil = ceil(angPrev);
3024 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3026 int iC = int( angCurFloor );
3027 if ( iC < nbAngles )
3028 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3030 iP = int( angPrevCeil );
3032 angle += theAngles[ iC ];
3034 aResult[ iSt ] = angle;
3039 // Update Python script
3040 TPythonDump() << "rotAngles = " << theAngles;
3041 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3042 << thePathMesh << ", "
3043 << thePathShape << ", "
3046 return aResult._retn();
3049 //=======================================================================
3052 //=======================================================================
3054 SMESH::ListOfGroups*
3055 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3056 const SMESH::AxisStruct & theAxis,
3057 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3058 CORBA::Boolean theCopy,
3060 ::SMESH_Mesh* theTargetMesh)
3061 throw (SALOME::SALOME_Exception)
3066 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3067 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3069 if ( theTargetMesh )
3073 switch ( theMirrorType ) {
3074 case SMESH::SMESH_MeshEditor::POINT:
3075 aTrsf.SetMirror( P );
3077 case SMESH::SMESH_MeshEditor::AXIS:
3078 aTrsf.SetMirror( gp_Ax1( P, V ));
3081 aTrsf.SetMirror( gp_Ax2( P, V ));
3084 TIDSortedElemSet copyElements;
3085 TIDSortedElemSet* workElements = & theElements;
3087 if ( myIsPreviewMode )
3089 TPreviewMesh * tmpMesh = getPreviewMesh();
3090 tmpMesh->Copy( theElements, copyElements);
3091 if ( !theCopy && !theTargetMesh )
3093 TIDSortedElemSet elemsAround, elemsAroundCopy;
3094 getElementsAround( theElements, getMeshDS(), elemsAround );
3095 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3097 workElements = & copyElements;
3098 theMakeGroups = false;
3101 ::SMESH_MeshEditor::PGroupIDs groupIds =
3102 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3104 if ( theCopy && !myIsPreviewMode)
3106 if ( theTargetMesh )
3108 theTargetMesh->GetMeshDS()->Modified();
3112 declareMeshModified( /*isReComputeSafe=*/false );
3115 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3117 SMESH_CATCH( SMESH::throwCorbaException );
3121 //=======================================================================
3124 //=======================================================================
3126 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3127 const SMESH::AxisStruct & theAxis,
3128 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3129 CORBA::Boolean theCopy)
3130 throw (SALOME::SALOME_Exception)
3132 if ( !myIsPreviewMode ) {
3133 TPythonDump() << this << ".Mirror( "
3134 << theIDsOfElements << ", "
3136 << mirrorTypeName(theMirrorType) << ", "
3139 if ( theIDsOfElements.length() > 0 )
3141 TIDSortedElemSet elements;
3142 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3143 mirror(elements, theAxis, theMirrorType, theCopy, false);
3148 //=======================================================================
3149 //function : MirrorObject
3151 //=======================================================================
3153 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3154 const SMESH::AxisStruct & theAxis,
3155 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3156 CORBA::Boolean theCopy)
3157 throw (SALOME::SALOME_Exception)
3159 if ( !myIsPreviewMode ) {
3160 TPythonDump() << this << ".MirrorObject( "
3161 << theObject << ", "
3163 << mirrorTypeName(theMirrorType) << ", "
3166 TIDSortedElemSet elements;
3168 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3170 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3171 mirror(elements, theAxis, theMirrorType, theCopy, false);
3174 //=======================================================================
3175 //function : MirrorMakeGroups
3177 //=======================================================================
3179 SMESH::ListOfGroups*
3180 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3181 const SMESH::AxisStruct& theMirror,
3182 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3183 throw (SALOME::SALOME_Exception)
3185 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3187 SMESH::ListOfGroups * aGroups = 0;
3188 if ( theIDsOfElements.length() > 0 )
3190 TIDSortedElemSet elements;
3191 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3192 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3194 if (!myIsPreviewMode) {
3195 dumpGroupsList(aPythonDump, aGroups);
3196 aPythonDump << this << ".MirrorMakeGroups( "
3197 << theIDsOfElements << ", "
3198 << theMirror << ", "
3199 << mirrorTypeName(theMirrorType) << " )";
3204 //=======================================================================
3205 //function : MirrorObjectMakeGroups
3207 //=======================================================================
3209 SMESH::ListOfGroups*
3210 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3211 const SMESH::AxisStruct& theMirror,
3212 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3213 throw (SALOME::SALOME_Exception)
3215 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3217 SMESH::ListOfGroups * aGroups = 0;
3218 TIDSortedElemSet elements;
3219 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3220 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3222 if (!myIsPreviewMode)
3224 dumpGroupsList(aPythonDump,aGroups);
3225 aPythonDump << this << ".MirrorObjectMakeGroups( "
3226 << theObject << ", "
3227 << theMirror << ", "
3228 << mirrorTypeName(theMirrorType) << " )";
3233 //=======================================================================
3234 //function : MirrorMakeMesh
3236 //=======================================================================
3238 SMESH::SMESH_Mesh_ptr
3239 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3240 const SMESH::AxisStruct& theMirror,
3241 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3242 CORBA::Boolean theCopyGroups,
3243 const char* theMeshName)
3244 throw (SALOME::SALOME_Exception)
3246 SMESH_Mesh_i* mesh_i;
3247 SMESH::SMESH_Mesh_var mesh;
3248 { // open new scope to dump "MakeMesh" command
3249 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3251 TPythonDump pydump; // to prevent dump at mesh creation
3253 mesh = makeMesh( theMeshName );
3254 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3255 if (mesh_i && theIDsOfElements.length() > 0 )
3257 TIDSortedElemSet elements;
3258 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3259 mirror(elements, theMirror, theMirrorType,
3260 false, theCopyGroups, & mesh_i->GetImpl());
3261 mesh_i->CreateGroupServants();
3264 if (!myIsPreviewMode) {
3265 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3266 << theIDsOfElements << ", "
3267 << theMirror << ", "
3268 << mirrorTypeName(theMirrorType) << ", "
3269 << theCopyGroups << ", '"
3270 << theMeshName << "' )";
3275 if (!myIsPreviewMode && mesh_i)
3276 mesh_i->GetGroups();
3278 return mesh._retn();
3281 //=======================================================================
3282 //function : MirrorObjectMakeMesh
3284 //=======================================================================
3286 SMESH::SMESH_Mesh_ptr
3287 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3288 const SMESH::AxisStruct& theMirror,
3289 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3290 CORBA::Boolean theCopyGroups,
3291 const char* theMeshName)
3292 throw (SALOME::SALOME_Exception)
3294 SMESH_Mesh_i* mesh_i;
3295 SMESH::SMESH_Mesh_var mesh;
3296 { // open new scope to dump "MakeMesh" command
3297 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3299 TPythonDump pydump; // to prevent dump at mesh creation
3301 mesh = makeMesh( theMeshName );
3302 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3303 TIDSortedElemSet elements;
3305 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3307 mirror(elements, theMirror, theMirrorType,
3308 false, theCopyGroups, & mesh_i->GetImpl());
3309 mesh_i->CreateGroupServants();
3311 if (!myIsPreviewMode) {
3312 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3313 << theObject << ", "
3314 << theMirror << ", "
3315 << mirrorTypeName(theMirrorType) << ", "
3316 << theCopyGroups << ", '"
3317 << theMeshName << "' )";
3322 if (!myIsPreviewMode && mesh_i)
3323 mesh_i->GetGroups();
3325 return mesh._retn();
3328 //=======================================================================
3329 //function : translate
3331 //=======================================================================
3333 SMESH::ListOfGroups*
3334 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3335 const SMESH::DirStruct & theVector,
3336 CORBA::Boolean theCopy,
3338 ::SMESH_Mesh* theTargetMesh)
3339 throw (SALOME::SALOME_Exception)
3344 if ( theTargetMesh )
3348 const SMESH::PointStruct * P = &theVector.PS;
3349 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3351 TIDSortedElemSet copyElements;
3352 TIDSortedElemSet* workElements = &theElements;
3354 if ( myIsPreviewMode )
3356 TPreviewMesh * tmpMesh = getPreviewMesh();
3357 tmpMesh->Copy( theElements, copyElements);
3358 if ( !theCopy && !theTargetMesh )
3360 TIDSortedElemSet elemsAround, elemsAroundCopy;
3361 getElementsAround( theElements, getMeshDS(), elemsAround );
3362 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3364 workElements = & copyElements;
3365 theMakeGroups = false;
3368 ::SMESH_MeshEditor::PGroupIDs groupIds =
3369 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3371 if ( theCopy && !myIsPreviewMode )
3373 if ( theTargetMesh )
3375 theTargetMesh->GetMeshDS()->Modified();
3379 declareMeshModified( /*isReComputeSafe=*/false );
3383 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3385 SMESH_CATCH( SMESH::throwCorbaException );
3389 //=======================================================================
3390 //function : Translate
3392 //=======================================================================
3394 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3395 const SMESH::DirStruct & theVector,
3396 CORBA::Boolean theCopy)
3397 throw (SALOME::SALOME_Exception)
3399 if (!myIsPreviewMode) {
3400 TPythonDump() << this << ".Translate( "
3401 << theIDsOfElements << ", "
3402 << theVector << ", "
3405 if (theIDsOfElements.length()) {
3406 TIDSortedElemSet elements;
3407 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3408 translate(elements, theVector, theCopy, false);
3412 //=======================================================================
3413 //function : TranslateObject
3415 //=======================================================================
3417 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3418 const SMESH::DirStruct & theVector,
3419 CORBA::Boolean theCopy)
3420 throw (SALOME::SALOME_Exception)
3422 if (!myIsPreviewMode) {
3423 TPythonDump() << this << ".TranslateObject( "
3424 << theObject << ", "
3425 << theVector << ", "
3428 TIDSortedElemSet elements;
3430 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3432 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3433 translate(elements, theVector, theCopy, false);
3436 //=======================================================================
3437 //function : TranslateMakeGroups
3439 //=======================================================================
3441 SMESH::ListOfGroups*
3442 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3443 const SMESH::DirStruct& theVector)
3444 throw (SALOME::SALOME_Exception)
3446 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3448 SMESH::ListOfGroups * aGroups = 0;
3449 if (theIDsOfElements.length()) {
3450 TIDSortedElemSet elements;
3451 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3452 aGroups = translate(elements,theVector,true,true);
3454 if (!myIsPreviewMode) {
3455 dumpGroupsList(aPythonDump, aGroups);
3456 aPythonDump << this << ".TranslateMakeGroups( "
3457 << theIDsOfElements << ", "
3458 << theVector << " )";
3463 //=======================================================================
3464 //function : TranslateObjectMakeGroups
3466 //=======================================================================
3468 SMESH::ListOfGroups*
3469 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3470 const SMESH::DirStruct& theVector)
3471 throw (SALOME::SALOME_Exception)
3473 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3475 SMESH::ListOfGroups * aGroups = 0;
3476 TIDSortedElemSet elements;
3477 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3478 aGroups = translate(elements, theVector, true, true);
3480 if (!myIsPreviewMode) {
3481 dumpGroupsList(aPythonDump, aGroups);
3482 aPythonDump << this << ".TranslateObjectMakeGroups( "
3483 << theObject << ", "
3484 << theVector << " )";
3489 //=======================================================================
3490 //function : TranslateMakeMesh
3492 //=======================================================================
3494 SMESH::SMESH_Mesh_ptr
3495 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3496 const SMESH::DirStruct& theVector,
3497 CORBA::Boolean theCopyGroups,
3498 const char* theMeshName)
3499 throw (SALOME::SALOME_Exception)
3501 SMESH_Mesh_i* mesh_i;
3502 SMESH::SMESH_Mesh_var mesh;
3504 { // open new scope to dump "MakeMesh" command
3505 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3507 TPythonDump pydump; // to prevent dump at mesh creation
3509 mesh = makeMesh( theMeshName );
3510 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3512 if ( mesh_i && theIDsOfElements.length() )
3514 TIDSortedElemSet elements;
3515 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3516 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3517 mesh_i->CreateGroupServants();
3520 if ( !myIsPreviewMode ) {
3521 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3522 << theIDsOfElements << ", "
3523 << theVector << ", "
3524 << theCopyGroups << ", '"
3525 << theMeshName << "' )";
3530 if (!myIsPreviewMode && mesh_i)
3531 mesh_i->GetGroups();
3533 return mesh._retn();
3536 //=======================================================================
3537 //function : TranslateObjectMakeMesh
3539 //=======================================================================
3541 SMESH::SMESH_Mesh_ptr
3542 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3543 const SMESH::DirStruct& theVector,
3544 CORBA::Boolean theCopyGroups,
3545 const char* theMeshName)
3546 throw (SALOME::SALOME_Exception)
3549 SMESH_Mesh_i* mesh_i;
3550 SMESH::SMESH_Mesh_var mesh;
3551 { // open new scope to dump "MakeMesh" command
3552 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3554 TPythonDump pydump; // to prevent dump at mesh creation
3555 mesh = makeMesh( theMeshName );
3556 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3558 TIDSortedElemSet elements;
3560 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3562 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3563 mesh_i->CreateGroupServants();
3565 if ( !myIsPreviewMode ) {
3566 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3567 << theObject << ", "
3568 << theVector << ", "
3569 << theCopyGroups << ", '"
3570 << theMeshName << "' )";
3575 if (!myIsPreviewMode && mesh_i)
3576 mesh_i->GetGroups();
3578 return mesh._retn();
3580 SMESH_CATCH( SMESH::throwCorbaException );
3584 //=======================================================================
3587 //=======================================================================
3589 SMESH::ListOfGroups*
3590 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3591 const SMESH::AxisStruct & theAxis,
3592 CORBA::Double theAngle,
3593 CORBA::Boolean theCopy,
3595 ::SMESH_Mesh* theTargetMesh)
3596 throw (SALOME::SALOME_Exception)
3601 if ( theTargetMesh )
3604 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3605 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3608 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3610 TIDSortedElemSet copyElements;
3611 TIDSortedElemSet* workElements = &theElements;
3612 if ( myIsPreviewMode ) {
3613 TPreviewMesh * tmpMesh = getPreviewMesh();
3614 tmpMesh->Copy( theElements, copyElements );
3615 if ( !theCopy && !theTargetMesh )
3617 TIDSortedElemSet elemsAround, elemsAroundCopy;
3618 getElementsAround( theElements, getMeshDS(), elemsAround );
3619 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3621 workElements = ©Elements;
3622 theMakeGroups = false;
3625 ::SMESH_MeshEditor::PGroupIDs groupIds =
3626 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3628 if ( theCopy && !myIsPreviewMode)
3630 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3631 else declareMeshModified( /*isReComputeSafe=*/false );
3634 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3636 SMESH_CATCH( SMESH::throwCorbaException );
3640 //=======================================================================
3643 //=======================================================================
3645 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3646 const SMESH::AxisStruct & theAxis,
3647 CORBA::Double theAngle,
3648 CORBA::Boolean theCopy)
3649 throw (SALOME::SALOME_Exception)
3651 if (!myIsPreviewMode) {
3652 TPythonDump() << this << ".Rotate( "
3653 << theIDsOfElements << ", "
3655 << TVar( theAngle ) << ", "
3658 if (theIDsOfElements.length() > 0)
3660 TIDSortedElemSet elements;
3661 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3662 rotate(elements,theAxis,theAngle,theCopy,false);
3666 //=======================================================================
3667 //function : RotateObject
3669 //=======================================================================
3671 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3672 const SMESH::AxisStruct & theAxis,
3673 CORBA::Double theAngle,
3674 CORBA::Boolean theCopy)
3675 throw (SALOME::SALOME_Exception)
3677 if ( !myIsPreviewMode ) {
3678 TPythonDump() << this << ".RotateObject( "
3679 << theObject << ", "
3681 << TVar( theAngle ) << ", "
3684 TIDSortedElemSet elements;
3685 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3686 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3687 rotate(elements,theAxis,theAngle,theCopy,false);
3690 //=======================================================================
3691 //function : RotateMakeGroups
3693 //=======================================================================
3695 SMESH::ListOfGroups*
3696 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3697 const SMESH::AxisStruct& theAxis,
3698 CORBA::Double theAngle)
3699 throw (SALOME::SALOME_Exception)
3701 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3703 SMESH::ListOfGroups * aGroups = 0;
3704 if (theIDsOfElements.length() > 0)
3706 TIDSortedElemSet elements;
3707 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3708 aGroups = rotate(elements,theAxis,theAngle,true,true);
3710 if (!myIsPreviewMode) {
3711 dumpGroupsList(aPythonDump, aGroups);
3712 aPythonDump << this << ".RotateMakeGroups( "
3713 << theIDsOfElements << ", "
3715 << TVar( theAngle ) << " )";
3720 //=======================================================================
3721 //function : RotateObjectMakeGroups
3723 //=======================================================================
3725 SMESH::ListOfGroups*
3726 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3727 const SMESH::AxisStruct& theAxis,
3728 CORBA::Double theAngle)
3729 throw (SALOME::SALOME_Exception)
3731 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3733 SMESH::ListOfGroups * aGroups = 0;
3734 TIDSortedElemSet elements;
3735 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3736 aGroups = rotate(elements, theAxis, theAngle, true, true);
3738 if (!myIsPreviewMode) {
3739 dumpGroupsList(aPythonDump, aGroups);
3740 aPythonDump << this << ".RotateObjectMakeGroups( "
3741 << theObject << ", "
3743 << TVar( theAngle ) << " )";
3748 //=======================================================================
3749 //function : RotateMakeMesh
3751 //=======================================================================
3753 SMESH::SMESH_Mesh_ptr
3754 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3755 const SMESH::AxisStruct& theAxis,
3756 CORBA::Double theAngleInRadians,
3757 CORBA::Boolean theCopyGroups,
3758 const char* theMeshName)
3759 throw (SALOME::SALOME_Exception)
3762 SMESH::SMESH_Mesh_var mesh;
3763 SMESH_Mesh_i* mesh_i;
3765 { // open new scope to dump "MakeMesh" command
3766 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3768 TPythonDump pydump; // to prevent dump at mesh creation
3770 mesh = makeMesh( theMeshName );
3771 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3773 if ( mesh_i && theIDsOfElements.length() > 0 )
3775 TIDSortedElemSet elements;
3776 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3777 rotate(elements, theAxis, theAngleInRadians,
3778 false, theCopyGroups, & mesh_i->GetImpl());
3779 mesh_i->CreateGroupServants();
3781 if ( !myIsPreviewMode ) {
3782 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3783 << theIDsOfElements << ", "
3785 << TVar( theAngleInRadians ) << ", "
3786 << theCopyGroups << ", '"
3787 << theMeshName << "' )";
3792 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3793 mesh_i->GetGroups();
3795 return mesh._retn();
3797 SMESH_CATCH( SMESH::throwCorbaException );
3801 //=======================================================================
3802 //function : RotateObjectMakeMesh
3804 //=======================================================================
3806 SMESH::SMESH_Mesh_ptr
3807 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3808 const SMESH::AxisStruct& theAxis,
3809 CORBA::Double theAngleInRadians,
3810 CORBA::Boolean theCopyGroups,
3811 const char* theMeshName)
3812 throw (SALOME::SALOME_Exception)
3815 SMESH::SMESH_Mesh_var mesh;
3816 SMESH_Mesh_i* mesh_i;
3818 {// open new scope to dump "MakeMesh" command
3819 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3821 TPythonDump pydump; // to prevent dump at mesh creation
3822 mesh = makeMesh( theMeshName );
3823 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3825 TIDSortedElemSet elements;
3827 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3829 rotate(elements, theAxis, theAngleInRadians,
3830 false, theCopyGroups, & mesh_i->GetImpl());
3831 mesh_i->CreateGroupServants();
3833 if ( !myIsPreviewMode ) {
3834 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3835 << theObject << ", "
3837 << TVar( theAngleInRadians ) << ", "
3838 << theCopyGroups << ", '"
3839 << theMeshName << "' )";
3844 if (!myIsPreviewMode && mesh_i)
3845 mesh_i->GetGroups();
3847 return mesh._retn();
3849 SMESH_CATCH( SMESH::throwCorbaException );
3853 //=======================================================================
3856 //=======================================================================
3858 SMESH::ListOfGroups*
3859 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3860 const SMESH::PointStruct& thePoint,
3861 const SMESH::double_array& theScaleFact,
3862 CORBA::Boolean theCopy,
3864 ::SMESH_Mesh* theTargetMesh)
3865 throw (SALOME::SALOME_Exception)
3869 if ( theScaleFact.length() < 1 )
3870 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3871 if ( theScaleFact.length() == 2 )
3872 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3874 if ( theTargetMesh )
3877 TIDSortedElemSet elements;
3878 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3879 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3884 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3885 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3889 #if OCC_VERSION_LARGE > 0x06070100
3890 // fight against orthogonalization
3891 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3892 // 0, S[1], 0, thePoint.y * (1-S[1]),
3893 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3894 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3895 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3896 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3897 loc.SetCoord( thePoint.x * (1-S[0]),
3898 thePoint.y * (1-S[1]),
3899 thePoint.z * (1-S[2]));
3900 M.SetDiagonal( S[0], S[1], S[2] );
3903 double tol = std::numeric_limits<double>::max();
3904 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3905 0, S[1], 0, thePoint.y * (1-S[1]),
3906 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3909 TIDSortedElemSet copyElements;
3910 TIDSortedElemSet* workElements = &elements;
3911 if ( myIsPreviewMode )
3913 TPreviewMesh * tmpMesh = getPreviewMesh();
3914 tmpMesh->Copy( elements, copyElements);
3915 if ( !theCopy && !theTargetMesh )
3917 TIDSortedElemSet elemsAround, elemsAroundCopy;
3918 getElementsAround( elements, getMeshDS(), elemsAround );
3919 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3921 workElements = & copyElements;
3922 theMakeGroups = false;
3925 ::SMESH_MeshEditor::PGroupIDs groupIds =
3926 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3928 if ( theCopy && !myIsPreviewMode )
3930 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3931 else declareMeshModified( /*isReComputeSafe=*/false );
3933 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3935 SMESH_CATCH( SMESH::throwCorbaException );
3939 //=======================================================================
3942 //=======================================================================
3944 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3945 const SMESH::PointStruct& thePoint,
3946 const SMESH::double_array& theScaleFact,
3947 CORBA::Boolean theCopy)
3948 throw (SALOME::SALOME_Exception)
3950 if ( !myIsPreviewMode ) {
3951 TPythonDump() << this << ".Scale( "
3952 << theObject << ", "
3954 << TVar( theScaleFact ) << ", "
3957 scale(theObject, thePoint, theScaleFact, theCopy, false);
3961 //=======================================================================
3962 //function : ScaleMakeGroups
3964 //=======================================================================
3966 SMESH::ListOfGroups*
3967 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3968 const SMESH::PointStruct& thePoint,
3969 const SMESH::double_array& theScaleFact)
3970 throw (SALOME::SALOME_Exception)
3972 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3974 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3975 if (!myIsPreviewMode) {
3976 dumpGroupsList(aPythonDump, aGroups);
3977 aPythonDump << this << ".Scale("
3980 << TVar( theScaleFact ) << ",True,True)";
3986 //=======================================================================
3987 //function : ScaleMakeMesh
3989 //=======================================================================
3991 SMESH::SMESH_Mesh_ptr
3992 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3993 const SMESH::PointStruct& thePoint,
3994 const SMESH::double_array& theScaleFact,
3995 CORBA::Boolean theCopyGroups,
3996 const char* theMeshName)
3997 throw (SALOME::SALOME_Exception)
3999 SMESH_Mesh_i* mesh_i;
4000 SMESH::SMESH_Mesh_var mesh;
4001 { // open new scope to dump "MakeMesh" command
4002 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4004 TPythonDump pydump; // to prevent dump at mesh creation
4005 mesh = makeMesh( theMeshName );
4006 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4010 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4011 mesh_i->CreateGroupServants();
4013 if ( !myIsPreviewMode )
4014 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4015 << theObject << ", "
4017 << TVar( theScaleFact ) << ", "
4018 << theCopyGroups << ", '"
4019 << theMeshName << "' )";
4023 if (!myIsPreviewMode && mesh_i)
4024 mesh_i->GetGroups();
4026 return mesh._retn();
4030 //=======================================================================
4031 //function : findCoincidentNodes
4033 //=======================================================================
4035 void SMESH_MeshEditor_i::
4036 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4037 CORBA::Double Tolerance,
4038 SMESH::array_of_long_array_out GroupsOfNodes,
4039 CORBA::Boolean SeparateCornersAndMedium)
4041 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4042 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4044 GroupsOfNodes = new SMESH::array_of_long_array;
4045 GroupsOfNodes->length( aListOfListOfNodes.size() );
4046 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4047 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4049 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4050 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4051 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4052 aGroup.length( aListOfNodes.size() );
4053 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4054 aGroup[ j ] = (*lIt)->GetID();
4058 //=======================================================================
4059 //function : FindCoincidentNodes
4061 //=======================================================================
4063 void SMESH_MeshEditor_i::
4064 FindCoincidentNodes (CORBA::Double Tolerance,
4065 SMESH::array_of_long_array_out GroupsOfNodes,
4066 CORBA::Boolean SeparateCornersAndMedium)
4067 throw (SALOME::SALOME_Exception)
4072 TIDSortedNodeSet nodes; // no input nodes
4073 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4075 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4076 << Tolerance << ", "
4077 << SeparateCornersAndMedium << " )";
4079 SMESH_CATCH( SMESH::throwCorbaException );
4082 //=======================================================================
4083 //function : FindCoincidentNodesOnPart
4085 //=======================================================================
4087 void SMESH_MeshEditor_i::
4088 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4089 CORBA::Double Tolerance,
4090 SMESH::array_of_long_array_out GroupsOfNodes,
4091 CORBA::Boolean SeparateCornersAndMedium)
4092 throw (SALOME::SALOME_Exception)
4097 TIDSortedNodeSet nodes;
4098 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4100 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4102 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4104 << Tolerance << ", "
4105 << SeparateCornersAndMedium << " )";
4107 SMESH_CATCH( SMESH::throwCorbaException );
4110 //================================================================================
4112 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4113 * ExceptSubMeshOrGroups
4115 //================================================================================
4117 void SMESH_MeshEditor_i::
4118 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4119 CORBA::Double theTolerance,
4120 SMESH::array_of_long_array_out theGroupsOfNodes,
4121 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4122 CORBA::Boolean theSeparateCornersAndMedium)
4123 throw (SALOME::SALOME_Exception)
4128 TIDSortedNodeSet nodes;
4129 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4131 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4133 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4135 while ( nodeIt->more() )
4136 nodes.erase( cast2Node( nodeIt->next() ));
4138 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4140 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4142 << theTolerance << ", "
4143 << theExceptSubMeshOrGroups << ", "
4144 << theSeparateCornersAndMedium << " )";
4146 SMESH_CATCH( SMESH::throwCorbaException );
4149 //=======================================================================
4150 //function : MergeNodes
4152 //=======================================================================
4154 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4155 const SMESH::ListOfIDSources& NodesToKeep)
4156 throw (SALOME::SALOME_Exception)
4161 SMESHDS_Mesh* aMesh = getMeshDS();
4163 TPythonDump aTPythonDump;
4164 aTPythonDump << this << ".MergeNodes([";
4166 TIDSortedNodeSet setOfNodesToKeep;
4167 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4169 prepareIdSource( NodesToKeep[i] );
4170 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
4171 while ( nodeIt->more() )
4172 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4175 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4176 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4178 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4179 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4180 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4181 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4183 CORBA::Long index = aNodeGroup[ j ];
4184 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4186 if ( setOfNodesToKeep.count( node ))
4187 aListOfNodes.push_front( node );
4189 aListOfNodes.push_back( node );
4192 if ( aListOfNodes.size() < 2 )
4193 aListOfListOfNodes.pop_back();
4195 if ( i > 0 ) aTPythonDump << ", ";
4196 aTPythonDump << aNodeGroup;
4199 getEditor().MergeNodes( aListOfListOfNodes );
4201 aTPythonDump << "], " << NodesToKeep << ")";
4203 declareMeshModified( /*isReComputeSafe=*/false );
4205 SMESH_CATCH( SMESH::throwCorbaException );
4208 //=======================================================================
4209 //function : FindEqualElements
4211 //=======================================================================
4213 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4214 SMESH::array_of_long_array_out GroupsOfElementsID)
4215 throw (SALOME::SALOME_Exception)
4220 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4221 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4223 TIDSortedElemSet elems;
4224 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4226 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4227 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4229 GroupsOfElementsID = new SMESH::array_of_long_array;
4230 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4232 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4233 aListOfListOfElementsID.begin();
4234 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4236 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4237 list<int>& listOfIDs = *arraysIt;
4238 aGroup.length( listOfIDs.size() );
4239 list<int>::iterator idIt = listOfIDs.begin();
4240 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4241 aGroup[ k ] = *idIt;
4244 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4248 SMESH_CATCH( SMESH::throwCorbaException );
4251 //=======================================================================
4252 //function : MergeElements
4254 //=======================================================================
4256 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4257 throw (SALOME::SALOME_Exception)
4262 TPythonDump aTPythonDump;
4263 aTPythonDump << this << ".MergeElements( [";
4265 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4267 for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) {
4268 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4269 aListOfListOfElementsID.push_back( list< int >() );
4270 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4271 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) {
4272 CORBA::Long id = anElemsIDGroup[ j ];
4273 aListOfElemsID.push_back( id );
4275 if ( aListOfElemsID.size() < 2 )
4276 aListOfListOfElementsID.pop_back();
4277 if ( i > 0 ) aTPythonDump << ", ";
4278 aTPythonDump << anElemsIDGroup;
4281 getEditor().MergeElements(aListOfListOfElementsID);
4283 declareMeshModified( /*isReComputeSafe=*/true );
4285 aTPythonDump << "] )";
4287 SMESH_CATCH( SMESH::throwCorbaException );
4290 //=======================================================================
4291 //function : MergeEqualElements
4293 //=======================================================================
4295 void SMESH_MeshEditor_i::MergeEqualElements()
4296 throw (SALOME::SALOME_Exception)
4301 getEditor().MergeEqualElements();
4303 declareMeshModified( /*isReComputeSafe=*/true );
4305 TPythonDump() << this << ".MergeEqualElements()";
4307 SMESH_CATCH( SMESH::throwCorbaException );
4310 //=============================================================================
4312 * Move the node to a given point
4314 //=============================================================================
4316 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4320 throw (SALOME::SALOME_Exception)
4323 initData(/*deleteSearchers=*/false);
4325 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4329 if ( theNodeSearcher )
4330 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4332 if ( myIsPreviewMode ) // make preview data
4334 // in a preview mesh, make edges linked to a node
4335 TPreviewMesh& tmpMesh = *getPreviewMesh();
4336 TIDSortedElemSet linkedNodes;
4337 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4338 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4339 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4340 for ( ; nIt != linkedNodes.end(); ++nIt )
4342 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4343 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4347 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4348 // fill preview data
4350 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4351 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4353 getMeshDS()->MoveNode(node, x, y, z);
4355 if ( !myIsPreviewMode )
4357 // Update Python script
4358 TPythonDump() << "isDone = " << this << ".MoveNode( "
4359 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4360 declareMeshModified( /*isReComputeSafe=*/false );
4363 SMESH_CATCH( SMESH::throwCorbaException );
4368 //================================================================================
4370 * \brief Return ID of node closest to a given point
4372 //================================================================================
4374 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4377 throw (SALOME::SALOME_Exception)
4380 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4382 if ( !theNodeSearcher ) {
4383 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4386 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4387 return node->GetID();
4389 SMESH_CATCH( SMESH::throwCorbaException );
4393 //================================================================================
4395 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4396 * move the node closest to the point to point's location and return ID of the node
4398 //================================================================================
4400 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4403 CORBA::Long theNodeID)
4404 throw (SALOME::SALOME_Exception)
4407 // We keep theNodeSearcher until any mesh modification:
4408 // 1) initData() deletes theNodeSearcher at any edition,
4409 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4411 initData(/*deleteSearchers=*/false);
4413 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4415 int nodeID = theNodeID;
4416 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4417 if ( !node ) // preview moving node
4419 if ( !theNodeSearcher ) {
4420 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4423 node = theNodeSearcher->FindClosestTo( p );
4426 nodeID = node->GetID();
4427 if ( myIsPreviewMode ) // make preview data
4429 // in a preview mesh, make edges linked to a node
4430 TPreviewMesh tmpMesh = *getPreviewMesh();
4431 TIDSortedElemSet linkedNodes;
4432 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4433 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4434 for ( ; nIt != linkedNodes.end(); ++nIt )
4436 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4437 tmpMesh.Copy( &edge );
4440 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4442 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4443 // fill preview data
4445 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4447 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4451 getMeshDS()->MoveNode(node, x, y, z);
4455 if ( !myIsPreviewMode )
4457 TPythonDump() << "nodeID = " << this
4458 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4459 << ", " << nodeID << " )";
4461 declareMeshModified( /*isReComputeSafe=*/false );
4466 SMESH_CATCH( SMESH::throwCorbaException );
4470 //=======================================================================
4472 * Return elements of given type where the given point is IN or ON.
4474 * 'ALL' type means elements of any type excluding nodes
4476 //=======================================================================
4478 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4481 SMESH::ElementType type)
4482 throw (SALOME::SALOME_Exception)
4485 SMESH::long_array_var res = new SMESH::long_array;
4486 vector< const SMDS_MeshElement* > foundElems;
4488 theSearchersDeleter.Set( myMesh );
4489 if ( !theElementSearcher ) {
4490 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4492 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4493 SMDSAbs_ElementType( type ),
4495 res->length( foundElems.size() );
4496 for ( size_t i = 0; i < foundElems.size(); ++i )
4497 res[i] = foundElems[i]->GetID();
4501 SMESH_CATCH( SMESH::throwCorbaException );
4505 //=======================================================================
4506 //function : FindAmongElementsByPoint
4507 //purpose : Searching among the given elements, return elements of given type
4508 // where the given point is IN or ON.
4509 // 'ALL' type means elements of any type excluding nodes
4510 //=======================================================================
4513 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4517 SMESH::ElementType type)
4518 throw (SALOME::SALOME_Exception)
4521 SMESH::long_array_var res = new SMESH::long_array;
4523 if ( type != SMESH::NODE )
4525 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4526 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4527 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4528 type != types[0] ) // but search of elements of dim > 0
4531 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4532 return FindElementsByPoint( x,y,z, type );
4534 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4536 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4537 if ( !theElementSearcher )
4539 // create a searcher from elementIDs
4540 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4541 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4543 if ( !idSourceToSet( elementIDs, meshDS, elements,
4544 ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ),
4545 /*emptyIfIsMesh=*/true))
4548 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4549 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4551 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4554 vector< const SMDS_MeshElement* > foundElems;
4556 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4557 SMDSAbs_ElementType( type ),
4559 res->length( foundElems.size() );
4560 for ( size_t i = 0; i < foundElems.size(); ++i )
4561 res[i] = foundElems[i]->GetID();
4565 SMESH_CATCH( SMESH::throwCorbaException );
4569 //=======================================================================
4570 //function : GetPointState
4571 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4572 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4573 //=======================================================================
4575 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4578 throw (SALOME::SALOME_Exception)
4581 theSearchersDeleter.Set( myMesh );
4582 if ( !theElementSearcher ) {
4583 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4585 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4587 SMESH_CATCH( SMESH::throwCorbaException );
4591 //=======================================================================
4592 //function : convError
4594 //=======================================================================
4596 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4598 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4602 RETCASE( SEW_BORDER1_NOT_FOUND );
4603 RETCASE( SEW_BORDER2_NOT_FOUND );
4604 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4605 RETCASE( SEW_BAD_SIDE_NODES );
4606 RETCASE( SEW_VOLUMES_TO_SPLIT );
4607 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4608 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4609 RETCASE( SEW_BAD_SIDE1_NODES );
4610 RETCASE( SEW_BAD_SIDE2_NODES );
4611 RETCASE( SEW_INTERNAL_ERROR );
4613 return SMESH::SMESH_MeshEditor::SEW_OK;
4616 //=======================================================================
4618 * Returns groups of FreeBorder's coincident within the given tolerance.
4619 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
4620 * to free borders being compared is used.
4622 //=======================================================================
4624 SMESH::CoincidentFreeBorders*
4625 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
4627 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
4631 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
4632 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
4634 // copy free borders
4635 aCFB->borders.length( cfb._borders.size() );
4636 for ( size_t i = 0; i < cfb._borders.size(); ++i )
4638 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
4639 SMESH::FreeBorder& aBRD = aCFB->borders[i];
4640 aBRD.nodeIDs.length( nodes.size() );
4641 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4642 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
4645 // copy coincident parts
4646 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
4647 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
4649 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
4650 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
4651 aGRP.length( grp.size() );
4652 for ( size_t iP = 0; iP < grp.size(); ++iP )
4654 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
4655 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4656 aPART.border = part._border;
4657 aPART.node1 = part._node1;
4658 aPART.node2 = part._node2;
4659 aPART.nodeLast = part._nodeLast;
4662 SMESH_CATCH( SMESH::doNothing );
4664 TPythonDump() << "CoincidentFreeBorders = "
4665 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
4667 return aCFB._retn();
4670 //=======================================================================
4672 * Sew FreeBorder's of each group
4674 //=======================================================================
4676 CORBA::Short SMESH_MeshEditor_i::
4677 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
4678 CORBA::Boolean createPolygons,
4679 CORBA::Boolean createPolyhedra)
4680 throw (SALOME::SALOME_Exception)
4682 CORBA::Short nbSewed = 0;
4684 SMESH_MeshAlgos::TFreeBorderVec groups;
4685 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
4687 // check the input and collect nodes
4688 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
4690 borderNodes.clear();
4691 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
4692 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
4694 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4695 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
4696 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
4698 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
4700 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
4701 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
4702 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
4703 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
4704 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
4705 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4707 // do not keep these nodes for further sewing as nodes can be removed by the sewing
4708 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
4709 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
4710 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
4712 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
4714 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
4716 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4718 borderNodes.push_back( n1 );
4719 borderNodes.push_back( n2 );
4720 borderNodes.push_back( n3 );
4722 groups.push_back( borderNodes );
4725 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
4726 // to get nodes that replace other nodes during merge we create 0D elements
4727 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
4730 vector< const SMDS_MeshElement* > tmp0Delems;
4731 for ( size_t i = 0; i < groups.size(); ++i )
4733 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4734 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4736 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
4738 tmp0Delems.push_back( it0D->next() );
4740 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
4744 // cout << endl << "INIT" << endl;
4745 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4747 // cout << i << " ";
4748 // if ( i % 3 == 0 ) cout << "^ ";
4749 // tmp0Delems[i]->GetNode(0)->Print( cout );
4754 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
4756 for ( size_t i = 0; i < groups.size(); ++i )
4758 bool isBordToBord = true;
4759 bool groupSewed = false;
4760 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4761 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
4763 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
4764 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
4765 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
4767 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
4768 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
4769 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
4771 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
4774 // TIDSortedElemSet emptySet, avoidSet;
4775 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
4777 // cout << "WRONG 2nd 1" << endl;
4778 // n0->Print( cout );
4779 // n1->Print( cout );
4781 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
4783 // cout << "WRONG 2nd 2" << endl;
4784 // n3->Print( cout );
4785 // n4->Print( cout );
4788 if ( !isBordToBord )
4790 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
4791 n2 = 0; // and n2 is not used
4793 // 1st border moves to 2nd
4794 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
4796 /*2ndIsFreeBorder=*/ isBordToBord,
4797 createPolygons, createPolyhedra);
4798 groupSewed = ( res == ok );
4800 isBordToBord = false;
4801 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
4802 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
4804 // cout << t << " ";
4805 // if ( t % 3 == 0 ) cout << "^ ";
4806 // tmp0Delems[t]->GetNode(0)->Print( cout );
4809 i0D += nodes.size();
4810 nbSewed += groupSewed;
4813 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
4814 << freeBorders << ", "
4815 << createPolygons << ", "
4816 << createPolyhedra << " )";
4818 SMESH_CATCH( SMESH::doNothing );
4820 declareMeshModified( /*isReComputeSafe=*/false );
4822 // remove tmp 0D elements
4824 set< const SMDS_MeshElement* > removed0D;
4825 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4827 if ( removed0D.insert( tmp0Delems[i] ).second )
4828 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
4830 SMESH_CATCH( SMESH::throwCorbaException );
4835 //=======================================================================
4836 //function : SewFreeBorders
4838 //=======================================================================
4840 SMESH::SMESH_MeshEditor::Sew_Error
4841 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4842 CORBA::Long SecondNodeID1,
4843 CORBA::Long LastNodeID1,
4844 CORBA::Long FirstNodeID2,
4845 CORBA::Long SecondNodeID2,
4846 CORBA::Long LastNodeID2,
4847 CORBA::Boolean CreatePolygons,
4848 CORBA::Boolean CreatePolyedrs)
4849 throw (SALOME::SALOME_Exception)
4854 SMESHDS_Mesh* aMesh = getMeshDS();
4856 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4857 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4858 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4859 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4860 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4861 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4863 if (!aBorderFirstNode ||
4864 !aBorderSecondNode||
4866 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4867 if (!aSide2FirstNode ||
4868 !aSide2SecondNode ||
4870 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4872 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4873 << FirstNodeID1 << ", "
4874 << SecondNodeID1 << ", "
4875 << LastNodeID1 << ", "
4876 << FirstNodeID2 << ", "
4877 << SecondNodeID2 << ", "
4878 << LastNodeID2 << ", "
4879 << CreatePolygons<< ", "
4880 << CreatePolyedrs<< " )";
4882 SMESH::SMESH_MeshEditor::Sew_Error error =
4883 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4894 declareMeshModified( /*isReComputeSafe=*/false );
4897 SMESH_CATCH( SMESH::throwCorbaException );
4898 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4902 //=======================================================================
4903 //function : SewConformFreeBorders
4905 //=======================================================================
4907 SMESH::SMESH_MeshEditor::Sew_Error
4908 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4909 CORBA::Long SecondNodeID1,
4910 CORBA::Long LastNodeID1,
4911 CORBA::Long FirstNodeID2,
4912 CORBA::Long SecondNodeID2)
4913 throw (SALOME::SALOME_Exception)
4918 SMESHDS_Mesh* aMesh = getMeshDS();
4920 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4921 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4922 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4923 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4924 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4925 const SMDS_MeshNode* aSide2ThirdNode = 0;
4927 if (!aBorderFirstNode ||
4928 !aBorderSecondNode||
4930 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4931 if (!aSide2FirstNode ||
4933 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4935 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4936 << FirstNodeID1 << ", "
4937 << SecondNodeID1 << ", "
4938 << LastNodeID1 << ", "
4939 << FirstNodeID2 << ", "
4940 << SecondNodeID2 << " )";
4942 SMESH::SMESH_MeshEditor::Sew_Error error =
4943 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4952 declareMeshModified( /*isReComputeSafe=*/false );
4955 SMESH_CATCH( SMESH::throwCorbaException );
4956 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4960 //=======================================================================
4961 //function : SewBorderToSide
4963 //=======================================================================
4965 SMESH::SMESH_MeshEditor::Sew_Error
4966 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4967 CORBA::Long SecondNodeIDOnFreeBorder,
4968 CORBA::Long LastNodeIDOnFreeBorder,
4969 CORBA::Long FirstNodeIDOnSide,
4970 CORBA::Long LastNodeIDOnSide,
4971 CORBA::Boolean CreatePolygons,
4972 CORBA::Boolean CreatePolyedrs)
4973 throw (SALOME::SALOME_Exception)
4978 SMESHDS_Mesh* aMesh = getMeshDS();
4980 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4981 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4982 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4983 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4984 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4985 const SMDS_MeshNode* aSide2ThirdNode = 0;
4987 if (!aBorderFirstNode ||
4988 !aBorderSecondNode||
4990 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4991 if (!aSide2FirstNode ||
4993 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4995 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4996 << FirstNodeIDOnFreeBorder << ", "
4997 << SecondNodeIDOnFreeBorder << ", "
4998 << LastNodeIDOnFreeBorder << ", "
4999 << FirstNodeIDOnSide << ", "
5000 << LastNodeIDOnSide << ", "
5001 << CreatePolygons << ", "
5002 << CreatePolyedrs << ") ";
5004 SMESH::SMESH_MeshEditor::Sew_Error error =
5005 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5015 declareMeshModified( /*isReComputeSafe=*/false );
5018 SMESH_CATCH( SMESH::throwCorbaException );
5019 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5023 //=======================================================================
5024 //function : SewSideElements
5026 //=======================================================================
5028 SMESH::SMESH_MeshEditor::Sew_Error
5029 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5030 const SMESH::long_array& IDsOfSide2Elements,
5031 CORBA::Long NodeID1OfSide1ToMerge,
5032 CORBA::Long NodeID1OfSide2ToMerge,
5033 CORBA::Long NodeID2OfSide1ToMerge,
5034 CORBA::Long NodeID2OfSide2ToMerge)
5035 throw (SALOME::SALOME_Exception)
5040 SMESHDS_Mesh* aMesh = getMeshDS();
5042 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5043 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5044 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5045 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5047 if (!aFirstNode1ToMerge ||
5048 !aFirstNode2ToMerge )
5049 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5050 if (!aSecondNode1ToMerge||
5051 !aSecondNode2ToMerge)
5052 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5054 TIDSortedElemSet aSide1Elems, aSide2Elems;
5055 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5056 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5058 TPythonDump() << "error = " << this << ".SewSideElements( "
5059 << IDsOfSide1Elements << ", "
5060 << IDsOfSide2Elements << ", "
5061 << NodeID1OfSide1ToMerge << ", "
5062 << NodeID1OfSide2ToMerge << ", "
5063 << NodeID2OfSide1ToMerge << ", "
5064 << NodeID2OfSide2ToMerge << ")";
5066 SMESH::SMESH_MeshEditor::Sew_Error error =
5067 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5070 aSecondNode1ToMerge,
5071 aSecondNode2ToMerge));
5073 declareMeshModified( /*isReComputeSafe=*/false );
5076 SMESH_CATCH( SMESH::throwCorbaException );
5077 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5080 //================================================================================
5082 * \brief Set new nodes for given element
5083 * \param ide - element id
5084 * \param newIDs - new node ids
5085 * \retval CORBA::Boolean - true if result is OK
5087 //================================================================================
5089 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5090 const SMESH::long_array& newIDs)
5091 throw (SALOME::SALOME_Exception)
5096 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5097 if(!elem) return false;
5099 int nbn = newIDs.length();
5101 vector<const SMDS_MeshNode*> aNodes(nbn);
5104 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5107 aNodes[nbn1] = aNode;
5110 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5111 << ide << ", " << newIDs << " )";
5113 MESSAGE("ChangeElementNodes");
5114 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5116 declareMeshModified( /*isReComputeSafe=*/ !res );
5120 SMESH_CATCH( SMESH::throwCorbaException );
5124 //=======================================================================
5126 * \brief Makes a part of the mesh quadratic or bi-quadratic
5128 //=======================================================================
5130 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5131 CORBA::Boolean theToBiQuad,
5132 SMESH::SMESH_IDSource_ptr theObject)
5133 throw (SALOME::SALOME_Exception)
5138 TIDSortedElemSet elems;
5140 if ( !( elemsOK = CORBA::is_nil( theObject )))
5142 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5143 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5147 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5148 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5150 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5151 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5153 declareMeshModified( /*isReComputeSafe=*/false );
5156 SMESH_CATCH( SMESH::throwCorbaException );
5159 //=======================================================================
5160 //function : ConvertFromQuadratic
5162 //=======================================================================
5164 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5165 throw (SALOME::SALOME_Exception)
5170 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5171 TPythonDump() << this << ".ConvertFromQuadratic()";
5172 declareMeshModified( /*isReComputeSafe=*/!isDone );
5175 SMESH_CATCH( SMESH::throwCorbaException );
5179 //=======================================================================
5180 //function : ConvertToQuadratic
5182 //=======================================================================
5184 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5185 throw (SALOME::SALOME_Exception)
5187 convertToQuadratic( theForce3d, false );
5188 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5191 //================================================================================
5193 * \brief Makes a part of the mesh quadratic
5195 //================================================================================
5197 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5198 SMESH::SMESH_IDSource_ptr theObject)
5199 throw (SALOME::SALOME_Exception)
5201 convertToQuadratic( theForce3d, false, theObject );
5202 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5205 //================================================================================
5207 * \brief Makes a part of the mesh bi-quadratic
5209 //================================================================================
5211 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5212 SMESH::SMESH_IDSource_ptr theObject)
5213 throw (SALOME::SALOME_Exception)
5215 convertToQuadratic( theForce3d, true, theObject );
5216 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5219 //================================================================================
5221 * \brief Makes a part of the mesh linear
5223 //================================================================================
5225 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5226 throw (SALOME::SALOME_Exception)
5233 TIDSortedElemSet elems;
5234 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5236 if ( elems.empty() )
5238 ConvertFromQuadratic();
5240 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5242 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5246 getEditor().ConvertFromQuadratic(elems);
5249 declareMeshModified( /*isReComputeSafe=*/false );
5251 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5253 SMESH_CATCH( SMESH::throwCorbaException );
5256 //=======================================================================
5257 //function : makeMesh
5258 //purpose : create a named imported mesh
5259 //=======================================================================
5261 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5263 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5264 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5265 SALOMEDS::Study_var study = gen->GetCurrentStudy();
5266 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5267 gen->SetName( meshSO, theMeshName, "Mesh" );
5268 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5270 return mesh._retn();
5273 //=======================================================================
5274 //function : dumpGroupsList
5276 //=======================================================================
5278 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5279 const SMESH::ListOfGroups * theGroupList)
5281 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5282 if ( isDumpGroupList )
5283 theDumpPython << theGroupList << " = ";
5286 //================================================================================
5288 \brief Generates the unique group name.
5289 \param thePrefix name prefix
5292 //================================================================================
5294 std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix)
5296 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5297 set<std::string> groupNames;
5299 // Get existing group names
5300 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5301 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5302 if (CORBA::is_nil(aGroup))
5305 CORBA::String_var name = aGroup->GetName();
5306 groupNames.insert( name.in() );
5310 std::string name = thePrefix;
5313 while (!groupNames.insert(name).second)
5314 name = SMESH_Comment( thePrefix ) << "_" << index++;
5319 //================================================================================
5321 * \brief Prepare SMESH_IDSource for work
5323 //================================================================================
5325 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5327 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5329 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5330 filter->SetMesh( mesh );
5333 //================================================================================
5335 * \brief Retrieve elements of given type from SMESH_IDSource
5337 //================================================================================
5339 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5340 const SMESHDS_Mesh* theMeshDS,
5341 TIDSortedElemSet& theElemSet,
5342 const SMDSAbs_ElementType theType,
5343 const bool emptyIfIsMesh,
5344 IDSource_Error* error)
5347 if ( error ) *error = IDSource_OK;
5349 if ( CORBA::is_nil( theIDSource ))
5351 if ( error ) *error = IDSource_INVALID;
5354 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5356 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5357 *error = IDSource_EMPTY;
5360 prepareIdSource( theIDSource );
5361 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5362 if ( anIDs->length() == 0 )
5364 if ( error ) *error = IDSource_EMPTY;
5367 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5368 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5370 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5372 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5376 if ( error ) *error = IDSource_INVALID;
5382 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5383 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5385 if ( error ) *error = IDSource_INVALID;
5392 //================================================================================
5394 * \brief Duplicates given elements, i.e. creates new elements based on the
5395 * same nodes as the given ones.
5396 * \param theElements - container of elements to duplicate.
5397 * \param theGroupName - a name of group to contain the generated elements.
5398 * If a group with such a name already exists, the new elements
5399 * are added to the existng group, else a new group is created.
5400 * If \a theGroupName is empty, new elements are not added
5402 * \return a group where the new elements are added. NULL if theGroupName == "".
5405 //================================================================================
5407 SMESH::SMESH_Group_ptr
5408 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5409 const char* theGroupName)
5410 throw (SALOME::SALOME_Exception)
5412 SMESH::SMESH_Group_var newGroup;
5419 TIDSortedElemSet elems;
5420 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5422 getEditor().DoubleElements( elems );
5424 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5427 SMESH::ElementType type =
5428 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5429 // find existing group
5430 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5431 for ( size_t i = 0; i < groups->length(); ++i )
5432 if ( groups[i]->GetType() == type )
5434 CORBA::String_var name = groups[i]->GetName();
5435 if ( strcmp( name, theGroupName ) == 0 ) {
5436 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5440 // create a new group
5441 if ( newGroup->_is_nil() )
5442 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5444 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5446 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5447 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5448 for ( int i = 1; i <= aSeq.Length(); i++ )
5449 groupDS->SMDSGroup().Add( aSeq(i) );
5454 if ( !newGroup->_is_nil() )
5455 pyDump << newGroup << " = ";
5456 pyDump << this << ".DoubleElements( "
5457 << theElements << ", " << "'" << theGroupName <<"')";
5459 SMESH_CATCH( SMESH::throwCorbaException );
5461 return newGroup._retn();
5464 //================================================================================
5466 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5467 \param theNodes - identifiers of nodes to be doubled
5468 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5469 nodes. If list of element identifiers is empty then nodes are doubled but
5470 they not assigned to elements
5471 \return TRUE if operation has been completed successfully, FALSE otherwise
5472 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5474 //================================================================================
5476 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5477 const SMESH::long_array& theModifiedElems )
5478 throw (SALOME::SALOME_Exception)
5483 list< int > aListOfNodes;
5485 for ( i = 0, n = theNodes.length(); i < n; i++ )
5486 aListOfNodes.push_back( theNodes[ i ] );
5488 list< int > aListOfElems;
5489 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5490 aListOfElems.push_back( theModifiedElems[ i ] );
5492 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5494 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5496 // Update Python script
5497 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5501 SMESH_CATCH( SMESH::throwCorbaException );
5505 //================================================================================
5507 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5508 This method provided for convenience works as DoubleNodes() described above.
5509 \param theNodeId - identifier of node to be doubled.
5510 \param theModifiedElems - identifiers of elements to be updated.
5511 \return TRUE if operation has been completed successfully, FALSE otherwise
5512 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5514 //================================================================================
5516 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5517 const SMESH::long_array& theModifiedElems )
5518 throw (SALOME::SALOME_Exception)
5521 SMESH::long_array_var aNodes = new SMESH::long_array;
5522 aNodes->length( 1 );
5523 aNodes[ 0 ] = theNodeId;
5525 TPythonDump pyDump; // suppress dump by the next line
5527 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5529 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5533 SMESH_CATCH( SMESH::throwCorbaException );
5537 //================================================================================
5539 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5540 This method provided for convenience works as DoubleNodes() described above.
5541 \param theNodes - group of nodes to be doubled.
5542 \param theModifiedElems - group of elements to be updated.
5543 \return TRUE if operation has been completed successfully, FALSE otherwise
5544 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5546 //================================================================================
5548 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5549 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5550 throw (SALOME::SALOME_Exception)
5553 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5556 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5557 SMESH::long_array_var aModifiedElems;
5558 if ( !CORBA::is_nil( theModifiedElems ) )
5559 aModifiedElems = theModifiedElems->GetListOfID();
5562 aModifiedElems = new SMESH::long_array;
5563 aModifiedElems->length( 0 );
5566 TPythonDump pyDump; // suppress dump by the next line
5568 bool done = DoubleNodes( aNodes, aModifiedElems );
5570 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5574 SMESH_CATCH( SMESH::throwCorbaException );
5578 //================================================================================
5580 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5581 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5582 * \param theNodes - group of nodes to be doubled.
5583 * \param theModifiedElems - group of elements to be updated.
5584 * \return a new group with newly created nodes
5585 * \sa DoubleNodeGroup()
5587 //================================================================================
5589 SMESH::SMESH_Group_ptr
5590 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5591 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5592 throw (SALOME::SALOME_Exception)
5595 SMESH::SMESH_Group_var aNewGroup;
5597 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5598 return aNewGroup._retn();
5601 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5602 SMESH::long_array_var aModifiedElems;
5603 if ( !CORBA::is_nil( theModifiedElems ) )
5604 aModifiedElems = theModifiedElems->GetListOfID();
5606 aModifiedElems = new SMESH::long_array;
5607 aModifiedElems->length( 0 );
5610 TPythonDump pyDump; // suppress dump by the next line
5612 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5615 // Create group with newly created nodes
5616 SMESH::long_array_var anIds = GetLastCreatedNodes();
5617 if (anIds->length() > 0) {
5618 std::string anUnindexedName (theNodes->GetName());
5619 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5620 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5621 aNewGroup->Add(anIds);
5622 pyDump << aNewGroup << " = ";
5626 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5627 << theModifiedElems << " )";
5629 return aNewGroup._retn();
5631 SMESH_CATCH( SMESH::throwCorbaException );
5635 //================================================================================
5637 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5638 This method provided for convenience works as DoubleNodes() described above.
5639 \param theNodes - list of groups of nodes to be doubled
5640 \param theModifiedElems - list of groups of elements to be updated.
5641 \return TRUE if operation has been completed successfully, FALSE otherwise
5642 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5644 //================================================================================
5646 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5647 const SMESH::ListOfGroups& theModifiedElems )
5648 throw (SALOME::SALOME_Exception)
5653 std::list< int > aNodes;
5655 for ( i = 0, n = theNodes.length(); i < n; i++ )
5657 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5658 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5660 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5661 for ( j = 0, m = aCurr->length(); j < m; j++ )
5662 aNodes.push_back( aCurr[ j ] );
5666 std::list< int > anElems;
5667 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5669 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5670 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5672 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5673 for ( j = 0, m = aCurr->length(); j < m; j++ )
5674 anElems.push_back( aCurr[ j ] );
5678 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5680 declareMeshModified( /*isReComputeSafe=*/false );
5682 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5686 SMESH_CATCH( SMESH::throwCorbaException );
5690 //================================================================================
5692 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5693 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5694 * \param theNodes - group of nodes to be doubled.
5695 * \param theModifiedElems - group of elements to be updated.
5696 * \return a new group with newly created nodes
5697 * \sa DoubleNodeGroups()
5699 //================================================================================
5701 SMESH::SMESH_Group_ptr
5702 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5703 const SMESH::ListOfGroups& theModifiedElems )
5704 throw (SALOME::SALOME_Exception)
5706 SMESH::SMESH_Group_var aNewGroup;
5708 TPythonDump pyDump; // suppress dump by the next line
5710 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5714 // Create group with newly created nodes
5715 SMESH::long_array_var anIds = GetLastCreatedNodes();
5716 if (anIds->length() > 0) {
5717 std::string anUnindexedName (theNodes[0]->GetName());
5718 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5719 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5720 aNewGroup->Add(anIds);
5721 pyDump << aNewGroup << " = ";
5725 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5726 << theModifiedElems << " )";
5728 return aNewGroup._retn();
5732 //================================================================================
5734 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5735 \param theElems - the list of elements (edges or faces) to be replicated
5736 The nodes for duplication could be found from these elements
5737 \param theNodesNot - list of nodes to NOT replicate
5738 \param theAffectedElems - the list of elements (cells and edges) to which the
5739 replicated nodes should be associated to.
5740 \return TRUE if operation has been completed successfully, FALSE otherwise
5741 \sa DoubleNodeGroup(), DoubleNodeGroups()
5743 //================================================================================
5745 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5746 const SMESH::long_array& theNodesNot,
5747 const SMESH::long_array& theAffectedElems )
5748 throw (SALOME::SALOME_Exception)
5753 SMESHDS_Mesh* aMeshDS = getMeshDS();
5754 TIDSortedElemSet anElems, aNodes, anAffected;
5755 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5756 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5757 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5759 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5761 // Update Python script
5762 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5763 << theNodesNot << ", " << theAffectedElems << " )";
5765 declareMeshModified( /*isReComputeSafe=*/false );
5768 SMESH_CATCH( SMESH::throwCorbaException );
5772 //================================================================================
5774 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5775 \param theElems - the list of elements (edges or faces) to be replicated
5776 The nodes for duplication could be found from these elements
5777 \param theNodesNot - list of nodes to NOT replicate
5778 \param theShape - shape to detect affected elements (element which geometric center
5779 located on or inside shape).
5780 The replicated nodes should be associated to affected elements.
5781 \return TRUE if operation has been completed successfully, FALSE otherwise
5782 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5784 //================================================================================
5786 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5787 const SMESH::long_array& theNodesNot,
5788 GEOM::GEOM_Object_ptr theShape )
5789 throw (SALOME::SALOME_Exception)
5795 SMESHDS_Mesh* aMeshDS = getMeshDS();
5796 TIDSortedElemSet anElems, aNodes;
5797 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5798 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5800 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5801 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5803 // Update Python script
5804 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5805 << theNodesNot << ", " << theShape << " )";
5807 declareMeshModified( /*isReComputeSafe=*/false );
5810 SMESH_CATCH( SMESH::throwCorbaException );
5814 //================================================================================
5816 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5817 \param theElems - group of of elements (edges or faces) to be replicated
5818 \param theNodesNot - group of nodes not to replicated
5819 \param theAffectedElems - group of elements to which the replicated nodes
5820 should be associated to.
5821 \return TRUE if operation has been completed successfully, FALSE otherwise
5822 \sa DoubleNodes(), DoubleNodeGroups()
5824 //================================================================================
5827 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5828 SMESH::SMESH_GroupBase_ptr theNodesNot,
5829 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5830 throw (SALOME::SALOME_Exception)
5833 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5839 SMESHDS_Mesh* aMeshDS = getMeshDS();
5840 TIDSortedElemSet anElems, aNodes, anAffected;
5841 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5842 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5843 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5845 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5847 // Update Python script
5848 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5849 << theNodesNot << ", " << theAffectedElems << " )";
5851 declareMeshModified( /*isReComputeSafe=*/false );
5854 SMESH_CATCH( SMESH::throwCorbaException );
5858 //================================================================================
5860 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5861 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5862 * \param theElems - group of of elements (edges or faces) to be replicated
5863 * \param theNodesNot - group of nodes not to replicated
5864 * \param theAffectedElems - group of elements to which the replicated nodes
5865 * should be associated to.
5866 * \return a new group with newly created elements
5867 * \sa DoubleNodeElemGroup()
5869 //================================================================================
5871 SMESH::SMESH_Group_ptr
5872 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5873 SMESH::SMESH_GroupBase_ptr theNodesNot,
5874 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5875 throw (SALOME::SALOME_Exception)
5878 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5882 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5883 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5885 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5887 << theNodesNot << ", "
5888 << theAffectedElems << " )";
5890 return elemGroup._retn();
5893 //================================================================================
5895 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5896 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5897 * \param theElems - group of of elements (edges or faces) to be replicated
5898 * \param theNodesNot - group of nodes not to replicated
5899 * \param theAffectedElems - group of elements to which the replicated nodes
5900 * should be associated to.
5901 * \return a new group with newly created elements
5902 * \sa DoubleNodeElemGroup()
5904 //================================================================================
5906 SMESH::ListOfGroups*
5907 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5908 SMESH::SMESH_GroupBase_ptr theNodesNot,
5909 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5910 CORBA::Boolean theElemGroupNeeded,
5911 CORBA::Boolean theNodeGroupNeeded)
5912 throw (SALOME::SALOME_Exception)
5915 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5916 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5917 aTwoGroups->length( 2 );
5919 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5920 return aTwoGroups._retn();
5925 SMESHDS_Mesh* aMeshDS = getMeshDS();
5926 TIDSortedElemSet anElems, aNodes, anAffected;
5927 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5928 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5929 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5932 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5934 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5940 // Create group with newly created elements
5941 CORBA::String_var elemGroupName = theElems->GetName();
5942 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
5943 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5945 SMESH::long_array_var anIds = GetLastCreatedElems();
5946 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5947 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5948 aNewElemGroup->Add(anIds);
5950 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5952 SMESH::long_array_var anIds = GetLastCreatedNodes();
5953 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5954 aNewNodeGroup->Add(anIds);
5958 // Update Python script
5961 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5962 else pyDump << aNewElemGroup << ", ";
5963 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5964 else pyDump << aNewNodeGroup << " ] = ";
5966 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5967 << theNodesNot << ", "
5968 << theAffectedElems << ", "
5969 << theElemGroupNeeded << ", "
5970 << theNodeGroupNeeded <<" )";
5972 aTwoGroups[0] = aNewElemGroup._retn();
5973 aTwoGroups[1] = aNewNodeGroup._retn();
5974 return aTwoGroups._retn();
5976 SMESH_CATCH( SMESH::throwCorbaException );
5980 //================================================================================
5982 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5983 \param theElems - group of of elements (edges or faces) to be replicated
5984 \param theNodesNot - group of nodes not to replicated
5985 \param theShape - shape to detect affected elements (element which geometric center
5986 located on or inside shape).
5987 The replicated nodes should be associated to affected elements.
5988 \return TRUE if operation has been completed successfully, FALSE otherwise
5989 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5991 //================================================================================
5994 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5995 SMESH::SMESH_GroupBase_ptr theNodesNot,
5996 GEOM::GEOM_Object_ptr theShape )
5997 throw (SALOME::SALOME_Exception)
6000 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6006 SMESHDS_Mesh* aMeshDS = getMeshDS();
6007 TIDSortedElemSet anElems, aNodes, anAffected;
6008 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6009 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6011 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6012 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6015 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6017 // Update Python script
6018 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6019 << theNodesNot << ", " << theShape << " )";
6022 SMESH_CATCH( SMESH::throwCorbaException );
6026 //================================================================================
6028 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6029 * \param [in] theGrpList - groups
6030 * \param [in] theMeshDS - mesh
6031 * \param [out] theElemSet - set of elements
6032 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6034 //================================================================================
6036 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6037 SMESHDS_Mesh* theMeshDS,
6038 TIDSortedElemSet& theElemSet,
6039 const bool theIsNodeGrp)
6041 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6043 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6044 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6045 : aGrp->GetType() != SMESH::NODE ) )
6047 SMESH::long_array_var anIDs = aGrp->GetIDs();
6048 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6053 //================================================================================
6055 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6056 This method provided for convenience works as DoubleNodes() described above.
6057 \param theElems - list of groups of elements (edges or faces) to be replicated
6058 \param theNodesNot - list of groups of nodes not to replicated
6059 \param theAffectedElems - group of elements to which the replicated nodes
6060 should be associated to.
6061 \return TRUE if operation has been completed successfully, FALSE otherwise
6062 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6064 //================================================================================
6067 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6068 const SMESH::ListOfGroups& theNodesNot,
6069 const SMESH::ListOfGroups& theAffectedElems)
6070 throw (SALOME::SALOME_Exception)
6076 SMESHDS_Mesh* aMeshDS = getMeshDS();
6077 TIDSortedElemSet anElems, aNodes, anAffected;
6078 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6079 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6080 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6082 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6084 // Update Python script
6085 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6086 << &theNodesNot << ", " << &theAffectedElems << " )";
6088 declareMeshModified( /*isReComputeSafe=*/false );
6091 SMESH_CATCH( SMESH::throwCorbaException );
6095 //================================================================================
6097 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6098 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6099 \param theElems - list of groups of elements (edges or faces) to be replicated
6100 \param theNodesNot - list of groups of nodes not to replicated
6101 \param theAffectedElems - group of elements to which the replicated nodes
6102 should be associated to.
6103 * \return a new group with newly created elements
6104 * \sa DoubleNodeElemGroups()
6106 //================================================================================
6108 SMESH::SMESH_Group_ptr
6109 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6110 const SMESH::ListOfGroups& theNodesNot,
6111 const SMESH::ListOfGroups& theAffectedElems)
6112 throw (SALOME::SALOME_Exception)
6115 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6119 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6120 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6122 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6124 << theNodesNot << ", "
6125 << theAffectedElems << " )";
6127 return elemGroup._retn();
6130 //================================================================================
6132 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6133 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6134 \param theElems - list of groups of elements (edges or faces) to be replicated
6135 \param theNodesNot - list of groups of nodes not to replicated
6136 \param theAffectedElems - group of elements to which the replicated nodes
6137 should be associated to.
6138 * \return a new group with newly created elements
6139 * \sa DoubleNodeElemGroups()
6141 //================================================================================
6143 SMESH::ListOfGroups*
6144 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6145 const SMESH::ListOfGroups& theNodesNot,
6146 const SMESH::ListOfGroups& theAffectedElems,
6147 CORBA::Boolean theElemGroupNeeded,
6148 CORBA::Boolean theNodeGroupNeeded)
6149 throw (SALOME::SALOME_Exception)
6152 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6153 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6154 aTwoGroups->length( 2 );
6159 SMESHDS_Mesh* aMeshDS = getMeshDS();
6160 TIDSortedElemSet anElems, aNodes, anAffected;
6161 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6162 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6163 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6165 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6167 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6172 // Create group with newly created elements
6173 CORBA::String_var elemGroupName = theElems[0]->GetName();
6174 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6175 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6177 SMESH::long_array_var anIds = GetLastCreatedElems();
6178 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6179 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6180 aNewElemGroup->Add(anIds);
6182 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6184 SMESH::long_array_var anIds = GetLastCreatedNodes();
6185 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6186 aNewNodeGroup->Add(anIds);
6190 // Update Python script
6193 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6194 else pyDump << aNewElemGroup << ", ";
6195 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6196 else pyDump << aNewNodeGroup << " ] = ";
6198 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6199 << &theNodesNot << ", "
6200 << &theAffectedElems << ", "
6201 << theElemGroupNeeded << ", "
6202 << theNodeGroupNeeded << " )";
6204 aTwoGroups[0] = aNewElemGroup._retn();
6205 aTwoGroups[1] = aNewNodeGroup._retn();
6206 return aTwoGroups._retn();
6208 SMESH_CATCH( SMESH::throwCorbaException );
6212 //================================================================================
6214 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6215 This method provided for convenience works as DoubleNodes() described above.
6216 \param theElems - list of groups of elements (edges or faces) to be replicated
6217 \param theNodesNot - list of groups of nodes not to replicated
6218 \param theShape - shape to detect affected elements (element which geometric center
6219 located on or inside shape).
6220 The replicated nodes should be associated to affected elements.
6221 \return TRUE if operation has been completed successfully, FALSE otherwise
6222 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6224 //================================================================================
6227 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6228 const SMESH::ListOfGroups& theNodesNot,
6229 GEOM::GEOM_Object_ptr theShape )
6230 throw (SALOME::SALOME_Exception)
6236 SMESHDS_Mesh* aMeshDS = getMeshDS();
6237 TIDSortedElemSet anElems, aNodes;
6238 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6239 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6241 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6242 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6244 // Update Python script
6245 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6246 << &theNodesNot << ", " << theShape << " )";
6248 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6251 SMESH_CATCH( SMESH::throwCorbaException );
6255 //================================================================================
6257 \brief Identify the elements that will be affected by node duplication (actual
6258 duplication is not performed.
6259 This method is the first step of DoubleNodeElemGroupsInRegion.
6260 \param theElems - list of groups of elements (edges or faces) to be replicated
6261 \param theNodesNot - list of groups of nodes not to replicated
6262 \param theShape - shape to detect affected elements (element which geometric center
6263 located on or inside shape).
6264 The replicated nodes should be associated to affected elements.
6265 \return groups of affected elements
6266 \sa DoubleNodeElemGroupsInRegion()
6268 //================================================================================
6269 SMESH::ListOfGroups*
6270 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6271 const SMESH::ListOfGroups& theNodesNot,
6272 GEOM::GEOM_Object_ptr theShape )
6273 throw (SALOME::SALOME_Exception)
6276 MESSAGE("AffectedElemGroupsInRegion");
6277 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6278 bool isEdgeGroup = false;
6279 bool isFaceGroup = false;
6280 bool isVolumeGroup = false;
6281 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6282 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6283 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6287 ::SMESH_MeshEditor aMeshEditor(myMesh);
6289 SMESHDS_Mesh* aMeshDS = getMeshDS();
6290 TIDSortedElemSet anElems, aNodes;
6291 listOfGroupToSet(theElems, aMeshDS, anElems, false);
6292 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6294 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6295 TIDSortedElemSet anAffected;
6296 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6299 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6304 int lg = anAffected.size();
6305 MESSAGE("lg="<< lg);
6306 SMESH::long_array_var volumeIds = new SMESH::long_array;
6307 volumeIds->length(lg);
6308 SMESH::long_array_var faceIds = new SMESH::long_array;
6309 faceIds->length(lg);
6310 SMESH::long_array_var edgeIds = new SMESH::long_array;
6311 edgeIds->length(lg);
6316 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6317 for (; eIt != anAffected.end(); ++eIt)
6319 const SMDS_MeshElement* anElem = *eIt;
6322 int elemId = anElem->GetID();
6323 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6324 volumeIds[ivol++] = elemId;
6325 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6326 faceIds[iface++] = elemId;
6327 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6328 edgeIds[iedge++] = elemId;
6330 volumeIds->length(ivol);
6331 faceIds->length(iface);
6332 edgeIds->length(iedge);
6334 aNewVolumeGroup->Add(volumeIds);
6335 aNewFaceGroup->Add(faceIds);
6336 aNewEdgeGroup->Add(edgeIds);
6337 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6338 isFaceGroup = (aNewFaceGroup->Size() > 0);
6339 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6343 if (isEdgeGroup) nbGroups++;
6344 if (isFaceGroup) nbGroups++;
6345 if (isVolumeGroup) nbGroups++;
6346 aListOfGroups->length(nbGroups);
6349 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6350 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6351 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6353 // Update Python script
6356 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6357 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6358 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6360 pyDump << this << ".AffectedElemGroupsInRegion( "
6361 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6363 return aListOfGroups._retn();
6365 SMESH_CATCH( SMESH::throwCorbaException );
6369 //================================================================================
6371 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6372 The created 2D mesh elements based on nodes of free faces of boundary volumes
6373 \return TRUE if operation has been completed successfully, FALSE otherwise
6375 //================================================================================
6377 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6378 throw (SALOME::SALOME_Exception)
6383 bool aResult = getEditor().Make2DMeshFrom3D();
6385 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6387 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6390 SMESH_CATCH( SMESH::throwCorbaException );
6394 //================================================================================
6396 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6397 * The list of groups must contain at least two groups. The groups have to be disjoint:
6398 * no common element into two different groups.
6399 * The nodes of the internal faces at the boundaries of the groups are doubled.
6400 * Optionally, the internal faces are replaced by flat elements.
6401 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6402 * The flat elements are stored in groups of volumes.
6403 * These groups are named according to the position of the group in the list:
6404 * 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.
6405 * 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.
6406 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6407 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6408 * \param theDomains - list of groups of volumes
6409 * \param createJointElems - if TRUE, create the elements
6410 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6411 * the boundary between \a theDomains and the rest mesh
6412 * \return TRUE if operation has been completed successfully, FALSE otherwise
6414 //================================================================================
6417 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6418 CORBA::Boolean createJointElems,
6419 CORBA::Boolean onAllBoundaries )
6420 throw (SALOME::SALOME_Exception)
6427 SMESHDS_Mesh* aMeshDS = getMeshDS();
6429 // MESSAGE("theDomains.length = "<<theDomains.length());
6430 if ( theDomains.length() <= 1 && !onAllBoundaries )
6431 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6433 vector<TIDSortedElemSet> domains;
6434 domains.resize( theDomains.length() );
6436 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6438 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6439 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6441 // if ( aGrp->GetType() != SMESH::VOLUME )
6442 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6443 SMESH::long_array_var anIDs = aGrp->GetIDs();
6444 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6448 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6449 // TODO publish the groups of flat elements in study
6451 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6453 // Update Python script
6454 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6455 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6457 SMESH_CATCH( SMESH::throwCorbaException );
6459 myMesh_i->CreateGroupServants(); // publish created groups if any
6464 //================================================================================
6466 * \brief Double nodes on some external faces and create flat elements.
6467 * Flat elements are mainly used by some types of mechanic calculations.
6469 * Each group of the list must be constituted of faces.
6470 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6471 * @param theGroupsOfFaces - list of groups of faces
6472 * @return TRUE if operation has been completed successfully, FALSE otherwise
6474 //================================================================================
6477 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6478 throw (SALOME::SALOME_Exception)
6483 SMESHDS_Mesh* aMeshDS = getMeshDS();
6485 vector<TIDSortedElemSet> faceGroups;
6488 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6490 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6491 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6493 TIDSortedElemSet faceGroup;
6495 faceGroups.push_back(faceGroup);
6496 SMESH::long_array_var anIDs = aGrp->GetIDs();
6497 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6501 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6502 // TODO publish the groups of flat elements in study
6504 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6506 // Update Python script
6507 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6510 SMESH_CATCH( SMESH::throwCorbaException );
6514 //================================================================================
6516 * \brief Identify all the elements around a geom shape, get the faces delimiting
6519 * Build groups of volume to remove, groups of faces to replace on the skin of the
6520 * object, groups of faces to remove inside the object, (idem edges).
6521 * Build ordered list of nodes at the border of each group of faces to replace
6522 * (to be used to build a geom subshape).
6524 //================================================================================
6526 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6527 GEOM::GEOM_Object_ptr theShape,
6528 const char* groupName,
6529 const SMESH::double_array& theNodesCoords,
6530 SMESH::array_of_long_array_out GroupsOfNodes)
6531 throw (SALOME::SALOME_Exception)
6536 std::vector<std::vector<int> > aListOfListOfNodes;
6537 ::SMESH_MeshEditor aMeshEditor( myMesh );
6539 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6540 if ( !theNodeSearcher )
6541 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6543 vector<double> nodesCoords;
6544 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6546 nodesCoords.push_back( theNodesCoords[i] );
6549 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6550 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6551 nodesCoords, aListOfListOfNodes);
6553 GroupsOfNodes = new SMESH::array_of_long_array;
6554 GroupsOfNodes->length( aListOfListOfNodes.size() );
6555 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6556 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6558 vector<int>& aListOfNodes = *llIt;
6559 vector<int>::iterator lIt = aListOfNodes.begin();;
6560 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6561 aGroup.length( aListOfNodes.size() );
6562 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6563 aGroup[ j ] = (*lIt);
6565 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6568 << ", '" << groupName << "', "
6569 << theNodesCoords << " )";
6571 SMESH_CATCH( SMESH::throwCorbaException );
6574 // issue 20749 ===================================================================
6576 * \brief Creates missing boundary elements
6577 * \param elements - elements whose boundary is to be checked
6578 * \param dimension - defines type of boundary elements to create
6579 * \param groupName - a name of group to store created boundary elements in,
6580 * "" means not to create the group
6581 * \param meshName - a name of new mesh to store created boundary elements in,
6582 * "" means not to create the new mesh
6583 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6584 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6585 * boundary elements will be copied into the new mesh
6586 * \param group - returns the create group, if any
6587 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6589 // ================================================================================
6591 SMESH::SMESH_Mesh_ptr
6592 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6593 SMESH::Bnd_Dimension dim,
6594 const char* groupName,
6595 const char* meshName,
6596 CORBA::Boolean toCopyElements,
6597 CORBA::Boolean toCopyExistingBondary,
6598 SMESH::SMESH_Group_out group)
6599 throw (SALOME::SALOME_Exception)
6604 if ( dim > SMESH::BND_1DFROM2D )
6605 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6607 SMESHDS_Mesh* aMeshDS = getMeshDS();
6609 SMESH::SMESH_Mesh_var mesh_var;
6610 SMESH::SMESH_Group_var group_var;
6614 TIDSortedElemSet elements;
6615 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6616 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6620 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6621 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6623 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6625 // group of new boundary elements
6626 SMESH_Group* smesh_group = 0;
6627 if ( strlen(groupName) )
6629 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6630 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6631 smesh_group = group_i->GetSmeshGroup();
6635 getEditor().MakeBoundaryMesh( elements,
6636 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6640 toCopyExistingBondary);
6643 smesh_mesh->GetMeshDS()->Modified();
6646 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6648 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6649 if ( mesh_var->_is_nil() )
6650 pyDump << myMesh_i->_this() << ", ";
6652 pyDump << mesh_var << ", ";
6653 if ( group_var->_is_nil() )
6654 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6656 pyDump << group_var << " = ";
6657 pyDump << this << ".MakeBoundaryMesh( "
6659 << "SMESH." << dimName[int(dim)] << ", "
6660 << "'" << groupName << "', "
6661 << "'" << meshName<< "', "
6662 << toCopyElements << ", "
6663 << toCopyExistingBondary << ")";
6665 group = group_var._retn();
6666 return mesh_var._retn();
6668 SMESH_CATCH( SMESH::throwCorbaException );
6669 return SMESH::SMESH_Mesh::_nil();
6672 //================================================================================
6674 * \brief Creates missing boundary elements
6675 * \param dimension - defines type of boundary elements to create
6676 * \param groupName - a name of group to store all boundary elements in,
6677 * "" means not to create the group
6678 * \param meshName - a name of a new mesh, which is a copy of the initial
6679 * mesh + created boundary elements; "" means not to create the new mesh
6680 * \param toCopyAll - if true, the whole initial mesh will be copied into
6681 * the new mesh else only boundary elements will be copied into the new mesh
6682 * \param groups - optional groups of elements to make boundary around
6683 * \param mesh - returns the mesh where elements were added to
6684 * \param group - returns the created group, if any
6685 * \retval long - number of added boundary elements
6687 //================================================================================
6689 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6690 const char* groupName,
6691 const char* meshName,
6692 CORBA::Boolean toCopyAll,
6693 const SMESH::ListOfIDSources& groups,
6694 SMESH::SMESH_Mesh_out mesh,
6695 SMESH::SMESH_Group_out group)
6696 throw (SALOME::SALOME_Exception)
6701 if ( dim > SMESH::BND_1DFROM2D )
6702 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6704 // separate groups belonging to this and other mesh
6705 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6706 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6707 groupsOfThisMesh ->length( groups.length() );
6708 groupsOfOtherMesh->length( groups.length() );
6709 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6710 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
6712 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6713 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6714 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6716 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6717 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6718 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6720 groupsOfThisMesh->length( nbGroups );
6721 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6726 if ( nbGroupsOfOtherMesh > 0 )
6728 // process groups belonging to another mesh
6729 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6730 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6731 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6732 groupsOfOtherMesh, mesh, group );
6735 SMESH::SMESH_Mesh_var mesh_var;
6736 SMESH::SMESH_Group_var group_var;
6739 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6740 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6744 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6746 /*toCopyGroups=*/false,
6747 /*toKeepIDs=*/true);
6749 mesh_var = makeMesh(meshName);
6751 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6752 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6755 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6756 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6758 // group of boundary elements
6759 SMESH_Group* smesh_group = 0;
6760 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6761 if ( strlen(groupName) )
6763 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6764 group_var = mesh_i->CreateGroup( groupType, groupName );
6765 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6766 smesh_group = group_i->GetSmeshGroup();
6769 TIDSortedElemSet elements;
6771 if ( groups.length() > 0 )
6773 for ( int i = 0; i < nbGroups; ++i )
6776 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6778 SMESH::Bnd_Dimension bdim =
6779 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6780 nbAdded += getEditor().MakeBoundaryMesh( elements,
6781 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6784 /*toCopyElements=*/false,
6785 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6786 /*toAddExistingBondary=*/true,
6787 /*aroundElements=*/true);
6793 nbAdded += getEditor().MakeBoundaryMesh( elements,
6794 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6797 /*toCopyElements=*/false,
6798 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6799 /*toAddExistingBondary=*/true);
6801 tgtMesh->GetMeshDS()->Modified();
6803 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6805 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6806 pyDump << "nbAdded, ";
6807 if ( mesh_var->_is_nil() )
6808 pyDump << myMesh_i->_this() << ", ";
6810 pyDump << mesh_var << ", ";
6811 if ( group_var->_is_nil() )
6812 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6814 pyDump << group_var << " = ";
6815 pyDump << this << ".MakeBoundaryElements( "
6816 << "SMESH." << dimName[int(dim)] << ", "
6817 << "'" << groupName << "', "
6818 << "'" << meshName<< "', "
6819 << toCopyAll << ", "
6822 mesh = mesh_var._retn();
6823 group = group_var._retn();
6826 SMESH_CATCH( SMESH::throwCorbaException );