1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
46 #include "SMDS_SetIterator.hxx"
47 #include "SMDS_VolumeTool.hxx"
48 #include "SMESHDS_Group.hxx"
49 #include "SMESHDS_GroupOnGeom.hxx"
50 #include "SMESH_ControlsDef.hxx"
51 #include "SMESH_Filter_i.hxx"
52 #include "SMESH_Gen_i.hxx"
53 #include "SMESH_Group.hxx"
54 #include "SMESH_Group_i.hxx"
55 #include "SMESH_MeshAlgos.hxx"
56 #include "SMESH_MeshPartDS.hxx"
57 #include "SMESH_MesherHelper.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMeshEventListener.hxx"
60 #include "SMESH_subMesh_i.hxx"
62 #include <utilities.h>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <Utils_CorbaException.hxx>
65 #include <SALOMEDS_wrap.hxx>
66 #include <SALOME_GenericObj_i.hh>
67 #include <Basics_OCCTVersion.hxx>
69 #include <BRepAdaptor_Surface.hxx>
70 #include <BRep_Tool.hxx>
71 #include <TopExp_Explorer.hxx>
73 #include <TopoDS_Edge.hxx>
74 #include <TopoDS_Face.hxx>
79 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
83 #include <Standard_Failure.hxx>
86 #include <Standard_ErrorHandler.hxx>
92 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
94 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
97 using SMESH::TPythonDump;
100 namespace MeshEditor_I {
102 //=============================================================================
104 * \brief Mesh to apply modifications for preview purposes
106 //=============================================================================
108 struct TPreviewMesh: public SMESH_Mesh
110 SMDSAbs_ElementType myPreviewType; // type to show
112 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
113 _isShapeToMesh = (_id =_studyId = 0);
114 _myMeshDS = new SMESHDS_Mesh( _id, true );
115 myPreviewType = previewElements;
117 //!< Copy a set of elements
118 void Copy(const TIDSortedElemSet & theElements,
119 TIDSortedElemSet& theCopyElements,
120 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
121 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
123 // loop on theIDsOfElements
124 TIDSortedElemSet::const_iterator eIt = theElements.begin();
125 for ( ; eIt != theElements.end(); ++eIt )
127 const SMDS_MeshElement* anElem = *eIt;
128 if ( !anElem ) continue;
129 SMDSAbs_ElementType type = anElem->GetType();
130 if ( type == theAvoidType ||
131 ( theSelectType != SMDSAbs_All && type != theSelectType ))
133 const SMDS_MeshElement* anElemCopy;
134 if ( type == SMDSAbs_Node)
135 anElemCopy = Copy( cast2Node(anElem) );
137 anElemCopy = Copy( anElem );
139 theCopyElements.insert( theCopyElements.end(), anElemCopy );
143 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
145 // copy element nodes
146 int anElemNbNodes = anElem->NbNodes();
147 vector< int > anElemNodesID( anElemNbNodes ) ;
148 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
149 for ( int i = 0; itElemNodes->more(); i++)
151 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
153 anElemNodesID[i] = anElemNode->GetID();
156 // creates a corresponding element on copied nodes
157 ::SMESH_MeshEditor::ElemFeatures elemType;
158 elemType.Init( anElem, /*basicOnly=*/false );
159 elemType.SetID( anElem->GetID() );
160 SMDS_MeshElement* anElemCopy =
161 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
165 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
167 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
168 anElemNode->GetID());
172 GetMeshDS()->ClearMesh();
174 void Remove( SMDSAbs_ElementType type )
176 SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator( type );
177 while ( eIt->more() )
178 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
180 };// struct TPreviewMesh
182 static SMESH_NodeSearcher * theNodeSearcher = 0;
183 static SMESH_ElementSearcher * theElementSearcher = 0;
185 //=============================================================================
187 * \brief Deleter of theNodeSearcher at any compute event occured
189 //=============================================================================
191 struct TSearchersDeleter : public SMESH_subMeshEventListener
194 string myMeshPartIOR;
196 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
197 "SMESH_MeshEditor_i::TSearchersDeleter"),
199 //!< Delete theNodeSearcher
202 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
203 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
205 typedef map < int, SMESH_subMesh * > TDependsOnMap;
206 //!< The meshod called by submesh: do my main job
207 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
208 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
210 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
212 Unset( sm->GetFather() );
215 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
216 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
218 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
225 myMeshPartIOR = meshPartIOR;
226 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
227 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
228 while ( smIt->more() )
231 sm->SetEventListener( this, 0, sm );
235 //!< delete self from all submeshes
236 void Unset(SMESH_Mesh* mesh)
238 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
239 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
240 while ( smIt->more() )
241 smIt->next()->DeleteEventListener( this );
246 } theSearchersDeleter;
248 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
250 TCollection_AsciiString typeStr;
251 switch ( theMirrorType ) {
252 case SMESH::SMESH_MeshEditor::POINT:
253 typeStr = "SMESH.SMESH_MeshEditor.POINT";
255 case SMESH::SMESH_MeshEditor::AXIS:
256 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
259 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
263 //================================================================================
265 * \brief function for conversion of long_array to TIDSortedElemSet
266 * \param IDs - array of IDs
267 * \param aMesh - mesh
268 * \param aMap - collection to fill
269 * \param aType - element type
271 //================================================================================
273 void arrayToSet(const SMESH::long_array & IDs,
274 const SMESHDS_Mesh* aMesh,
275 TIDSortedElemSet& aMap,
276 const SMDSAbs_ElementType aType = SMDSAbs_All,
277 SMDS_MeshElement::Filter* aFilter = NULL)
279 SMDS_MeshElement::NonNullFilter filter1;
280 SMDS_MeshElement::TypeFilter filter2( aType );
282 if ( aFilter == NULL )
283 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
285 SMDS_MeshElement::Filter & filter = *aFilter;
287 if ( aType == SMDSAbs_Node )
288 for (int i=0; i<IDs.length(); i++) {
289 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
291 aMap.insert( aMap.end(), elem );
294 for (int i=0; i<IDs.length(); i++) {
295 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
297 aMap.insert( aMap.end(), elem );
301 //================================================================================
303 * \brief Retrieve nodes from SMESH_IDSource
305 //================================================================================
307 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
308 const SMESHDS_Mesh* theMeshDS,
309 TIDSortedNodeSet& theNodeSet)
312 if ( CORBA::is_nil( theObject ) )
314 SMESH::array_of_ElementType_var types = theObject->GetTypes();
315 SMESH::long_array_var aElementsId = theObject->GetIDs();
316 if ( types->length() == 1 && types[0] == SMESH::NODE)
318 for(int i = 0; i < aElementsId->length(); i++)
319 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
320 theNodeSet.insert( theNodeSet.end(), n);
322 else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
324 SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
325 while ( nIt->more( ))
326 if( const SMDS_MeshElement * elem = nIt->next() )
327 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
331 for(int i = 0; i < aElementsId->length(); i++)
332 if( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
333 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
337 //================================================================================
339 * \brief Returns elements connected to the given elements
341 //================================================================================
343 void getElementsAround(const TIDSortedElemSet& theElements,
344 const SMESHDS_Mesh* theMeshDS,
345 TIDSortedElemSet& theElementsAround)
347 if ( theElements.empty() ) return;
349 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
350 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
352 theMeshDS->GetMeshInfo().NbElements( elemType ) == theElements.size() )
353 return; // all the elements are in theElements
356 elemType = SMDSAbs_All;
358 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
360 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
361 for ( ; elemIt != theElements.end(); ++elemIt )
363 const SMDS_MeshElement* e = *elemIt;
364 int i = e->NbCornerNodes();
367 const SMDS_MeshNode* n = e->GetNode( i );
368 if ( !isNodeChecked[ n->GetID() ])
370 isNodeChecked[ n->GetID() ] = true;
371 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
372 while ( invIt->more() )
374 const SMDS_MeshElement* elemAround = invIt->next();
375 if ( !theElements.count( elemAround ))
376 theElementsAround.insert( elemAround );
383 //================================================================================
385 * \brief Return a string used to detect change of mesh part on which theElementSearcher
386 * is going to be used
388 //================================================================================
390 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
392 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
393 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
394 // take into account passible group modification
395 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
396 partIOR += SMESH_Comment( type );
400 } // namespace MeshEditor_I
402 using namespace MeshEditor_I;
404 //=============================================================================
408 //=============================================================================
410 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
412 myMesh( &theMesh->GetImpl() ),
414 myIsPreviewMode ( isPreview ),
420 //================================================================================
424 //================================================================================
426 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
428 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
429 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
430 poa->deactivate_object(anObjectId.in());
432 //deleteAuxIDSources();
433 delete myPreviewMesh; myPreviewMesh = 0;
434 delete myPreviewEditor; myPreviewEditor = 0;
437 //================================================================================
439 * \brief Returns the mesh
441 //================================================================================
443 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
445 return myMesh_i->_this();
448 //================================================================================
450 * \brief Clear members
452 //================================================================================
454 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
456 if ( myIsPreviewMode ) {
457 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
460 if ( deleteSearchers )
461 TSearchersDeleter::Delete();
463 getEditor().GetError().reset();
464 getEditor().ClearLastCreated();
467 //================================================================================
469 * \brief Increment mesh modif time and optionally record that the performed
470 * modification may influence futher mesh re-compute.
471 * \param [in] isReComputeSafe - true if the modification does not influence
472 * futher mesh re-compute
474 //================================================================================
476 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
478 myMesh->GetMeshDS()->Modified();
479 if ( !isReComputeSafe )
480 myMesh->SetIsModified( true );
483 //================================================================================
485 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
486 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
488 //================================================================================
490 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
492 if ( myIsPreviewMode && !myPreviewEditor ) {
493 if ( !myPreviewMesh ) getPreviewMesh();
494 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
496 return myIsPreviewMode ? *myPreviewEditor : myEditor;
499 //================================================================================
501 * \brief Initialize and return myPreviewMesh
502 * \param previewElements - type of elements to show in preview
504 * WARNING: call it once par a method!
506 //================================================================================
508 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
510 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
512 delete myPreviewEditor;
514 delete myPreviewMesh;
515 myPreviewMesh = new TPreviewMesh( previewElements );
517 myPreviewMesh->Clear();
518 return myPreviewMesh;
521 //================================================================================
523 * Return data of mesh edition preview
525 //================================================================================
527 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
528 throw (SALOME::SALOME_Exception)
531 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
533 if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
535 list<int> aNodesConnectivity;
536 typedef map<int, int> TNodesMap;
539 SMESHDS_Mesh* aMeshDS;
540 std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
542 aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
543 aMeshDS = aMeshPartDS.get();
546 aMeshDS = getEditor().GetMeshDS();
548 myPreviewData = new SMESH::MeshPreviewStruct();
549 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
552 SMDSAbs_ElementType previewType = SMDSAbs_All;
554 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
555 previewType = aPreviewMesh->myPreviewType;
556 switch ( previewType ) {
557 case SMDSAbs_Edge : break;
558 case SMDSAbs_Face : break;
559 case SMDSAbs_Volume: break;
561 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
565 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
567 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
569 while ( itMeshElems->more() ) {
570 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
571 SMDS_NodeIteratorPtr itElemNodes =
572 (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
573 aMeshElem->interlacedNodesIterator() :
574 aMeshElem->nodeIterator() );
575 while ( itElemNodes->more() ) {
576 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
577 int aNodeID = aMeshNode->GetID();
578 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
579 if ( anIter == nodesMap.end() ) {
580 // filling the nodes coordinates
581 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
582 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
583 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
584 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
587 aNodesConnectivity.push_back(anIter->second);
590 // filling the elements types
591 SMDSAbs_ElementType aType = aMeshElem->GetType();
592 bool isPoly = aMeshElem->IsPoly();
593 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
594 myPreviewData->elementTypes[i].isPoly = isPoly;
595 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
598 myPreviewData->nodesXYZ.length( j );
600 // filling the elements connectivities
601 list<int>::iterator aConnIter = aNodesConnectivity.begin();
602 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
603 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
604 myPreviewData->elementConnectivities[i] = *aConnIter;
606 return myPreviewData._retn();
608 SMESH_CATCH( SMESH::throwCorbaException );
612 //================================================================================
614 * \brief Returns list of it's IDs of created nodes
615 * \retval SMESH::long_array* - list of node ID
617 //================================================================================
619 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
620 throw (SALOME::SALOME_Exception)
623 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
625 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
626 myLastCreatedNodes->length( aSeq.Length() );
627 for (int i = 1; i <= aSeq.Length(); i++)
628 myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID();
630 return myLastCreatedNodes._retn();
631 SMESH_CATCH( SMESH::throwCorbaException );
635 //================================================================================
637 * \brief Returns list of it's IDs of created elements
638 * \retval SMESH::long_array* - list of elements' ID
640 //================================================================================
642 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
643 throw (SALOME::SALOME_Exception)
646 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
648 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
649 myLastCreatedElems->length( aSeq.Length() );
650 for ( int i = 1; i <= aSeq.Length(); i++ )
651 myLastCreatedElems[i-1] = aSeq.Value(i)->GetID();
653 return myLastCreatedElems._retn();
654 SMESH_CATCH( SMESH::throwCorbaException );
658 //=======================================================================
659 //function : ClearLastCreated
660 //purpose : Clears sequences of last created elements and nodes
661 //=======================================================================
663 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
666 getEditor().ClearLastCreated();
667 SMESH_CATCH( SMESH::throwCorbaException );
670 //=======================================================================
672 * Returns description of an error/warning occured during the last operation
673 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
675 //=======================================================================
677 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
678 throw (SALOME::SALOME_Exception)
681 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
682 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
683 if ( errIn && !errIn->IsOK() )
685 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
686 errOut->comment = errIn->myComment.c_str();
687 errOut->subShapeID = -1;
688 errOut->hasBadMesh = !errIn->myBadElements.empty();
693 errOut->subShapeID = -1;
694 errOut->hasBadMesh = false;
697 return errOut._retn();
698 SMESH_CATCH( SMESH::throwCorbaException );
702 //=======================================================================
703 //function : MakeIDSource
704 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
705 // Call UnRegister() as you fininsh using it!!
706 //=======================================================================
708 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
709 public virtual SALOME::GenericObj_i
711 SMESH::long_array _ids;
712 SMESH::ElementType _type;
713 SMESH::SMESH_Mesh_ptr _mesh;
714 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
715 SMESH::long_array* GetMeshInfo() { return 0; }
716 SMESH::long_array* GetNbElementsByType()
718 SMESH::long_array_var aRes = new SMESH::long_array();
719 aRes->length(SMESH::NB_ELEMENT_TYPES);
720 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
721 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
724 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
725 bool IsMeshInfoCorrect() { return true; }
726 SMESH::array_of_ElementType* GetTypes()
728 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
729 if ( _ids.length() > 0 ) {
733 return types._retn();
735 SALOMEDS::TMPFile* GetVtkUgStream()
737 SALOMEDS::TMPFile_var SeqFile;
738 return SeqFile._retn();
742 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
743 SMESH::ElementType type)
745 _IDSource* idSrc = new _IDSource;
746 idSrc->_mesh = myMesh_i->_this();
749 if ( type == SMESH::ALL && ids.length() > 0 )
750 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
752 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
754 return anIDSourceVar._retn();
757 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
759 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
762 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
765 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
767 nbIds = (int) tmpIdSource->_ids.length();
768 return & tmpIdSource->_ids[0];
774 // void SMESH_MeshEditor_i::deleteAuxIDSources()
776 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
777 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
779 // myAuxIDSources.clear();
782 //=============================================================================
786 //=============================================================================
789 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
790 throw (SALOME::SALOME_Exception)
797 for (int i = 0; i < IDsOfElements.length(); i++)
798 IdList.push_back( IDsOfElements[i] );
800 // Update Python script
801 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
804 bool ret = getEditor().Remove( IdList, false );
806 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
809 SMESH_CATCH( SMESH::throwCorbaException );
813 //=============================================================================
817 //=============================================================================
819 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
820 throw (SALOME::SALOME_Exception)
826 for (int i = 0; i < IDsOfNodes.length(); i++)
827 IdList.push_back( IDsOfNodes[i] );
829 // Update Python script
830 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
832 bool ret = getEditor().Remove( IdList, true );
834 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
837 SMESH_CATCH( SMESH::throwCorbaException );
841 //=============================================================================
845 //=============================================================================
847 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
848 throw (SALOME::SALOME_Exception)
853 // Update Python script
854 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
856 // Create filter to find all orphan nodes
857 SMESH::Controls::Filter::TIdSequence seq;
858 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
859 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
861 // remove orphan nodes (if there are any)
863 for ( int i = 0; i < seq.size(); i++ )
864 IdList.push_back( seq[i] );
866 int nbNodesBefore = myMesh->NbNodes();
867 getEditor().Remove( IdList, true );
868 int nbNodesAfter = myMesh->NbNodes();
870 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
871 return nbNodesBefore - nbNodesAfter;
873 SMESH_CATCH( SMESH::throwCorbaException );
877 //=============================================================================
881 //=============================================================================
883 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
884 throw (SALOME::SALOME_Exception)
889 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
891 // Update Python script
892 TPythonDump() << "nodeID = " << this << ".AddNode( "
893 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
895 declareMeshModified( /*isReComputeSafe=*/false );
898 SMESH_CATCH( SMESH::throwCorbaException );
902 //=============================================================================
904 * Create 0D element on the given node.
906 //=============================================================================
908 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
909 throw (SALOME::SALOME_Exception)
914 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
915 SMDS_MeshElement* elem = getMeshDS()->Add0DElement(aNode);
917 // Update Python script
918 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
920 declareMeshModified( /*isReComputeSafe=*/false );
922 return elem ? elem->GetID() : 0;
924 SMESH_CATCH( SMESH::throwCorbaException );
928 //=============================================================================
930 * Create a ball element on the given node.
932 //=============================================================================
934 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
935 throw (SALOME::SALOME_Exception)
940 if ( diameter < std::numeric_limits<double>::min() )
941 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
943 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
944 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
946 // Update Python script
947 TPythonDump() << "ballElem = "
948 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
950 declareMeshModified( /*isReComputeSafe=*/false );
951 return elem ? elem->GetID() : 0;
953 SMESH_CATCH( SMESH::throwCorbaException );
957 //=============================================================================
959 * Create an edge, either linear and quadratic (this is determed
960 * by number of given nodes, two or three)
962 //=============================================================================
964 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
965 throw (SALOME::SALOME_Exception)
970 int NbNodes = IDsOfNodes.length();
971 SMDS_MeshElement* elem = 0;
974 CORBA::Long index1 = IDsOfNodes[0];
975 CORBA::Long index2 = IDsOfNodes[1];
976 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
977 getMeshDS()->FindNode(index2));
979 // Update Python script
980 TPythonDump() << "edge = " << this << ".AddEdge([ "
981 << index1 << ", " << index2 <<" ])";
984 CORBA::Long n1 = IDsOfNodes[0];
985 CORBA::Long n2 = IDsOfNodes[1];
986 CORBA::Long n12 = IDsOfNodes[2];
987 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
988 getMeshDS()->FindNode(n2),
989 getMeshDS()->FindNode(n12));
990 // Update Python script
991 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
992 <<n1<<", "<<n2<<", "<<n12<<" ])";
995 declareMeshModified( /*isReComputeSafe=*/false );
996 return elem ? elem->GetID() : 0;
998 SMESH_CATCH( SMESH::throwCorbaException );
1002 //=============================================================================
1006 //=============================================================================
1008 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1009 throw (SALOME::SALOME_Exception)
1014 int NbNodes = IDsOfNodes.length();
1020 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1021 for (int i = 0; i < NbNodes; i++)
1022 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1024 SMDS_MeshElement* elem = 0;
1026 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1027 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1028 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1029 nodes[4], nodes[5]); break;
1030 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1031 nodes[4], nodes[5], nodes[6]); break;
1032 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1033 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1034 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1035 nodes[4], nodes[5], nodes[6], nodes[7],
1037 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1040 // Update Python script
1041 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1043 declareMeshModified( /*isReComputeSafe=*/false );
1045 return elem ? elem->GetID() : 0;
1047 SMESH_CATCH( SMESH::throwCorbaException );
1051 //=============================================================================
1055 //=============================================================================
1057 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1058 throw (SALOME::SALOME_Exception)
1063 int NbNodes = IDsOfNodes.length();
1064 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1065 for (int i = 0; i < NbNodes; i++)
1066 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1068 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1070 // Update Python script
1071 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1073 declareMeshModified( /*isReComputeSafe=*/false );
1074 return elem ? elem->GetID() : 0;
1076 SMESH_CATCH( SMESH::throwCorbaException );
1080 //=============================================================================
1082 * AddQuadPolygonalFace
1084 //=============================================================================
1086 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1087 throw (SALOME::SALOME_Exception)
1092 int NbNodes = IDsOfNodes.length();
1093 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1094 for (int i = 0; i < NbNodes; i++)
1095 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1097 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1099 // Update Python script
1100 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1102 declareMeshModified( /*isReComputeSafe=*/false );
1103 return elem ? elem->GetID() : 0;
1105 SMESH_CATCH( SMESH::throwCorbaException );
1109 //=============================================================================
1111 * Create volume, either linear and quadratic (this is determed
1112 * by number of given nodes)
1114 //=============================================================================
1116 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1117 throw (SALOME::SALOME_Exception)
1122 int NbNodes = IDsOfNodes.length();
1123 vector< const SMDS_MeshNode*> n(NbNodes);
1124 for(int i=0;i<NbNodes;i++)
1125 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1127 SMDS_MeshElement* elem = 0;
1130 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1131 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1132 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1133 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1134 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1135 n[6],n[7],n[8],n[9]);
1137 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1138 n[6],n[7],n[8],n[9],n[10],n[11]);
1140 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1141 n[7],n[8],n[9],n[10],n[11],n[12]);
1143 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1144 n[9],n[10],n[11],n[12],n[13],n[14]);
1146 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1147 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1148 n[15],n[16],n[17],n[18],n[19]);
1150 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1151 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1152 n[15],n[16],n[17],n[18],n[19],
1153 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1157 // Update Python script
1158 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1160 declareMeshModified( /*isReComputeSafe=*/false );
1161 return elem ? elem->GetID() : 0;
1163 SMESH_CATCH( SMESH::throwCorbaException );
1167 //=============================================================================
1169 * AddPolyhedralVolume
1171 //=============================================================================
1172 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1173 const SMESH::long_array & Quantities)
1174 throw (SALOME::SALOME_Exception)
1179 int NbNodes = IDsOfNodes.length();
1180 std::vector<const SMDS_MeshNode*> n (NbNodes);
1181 for (int i = 0; i < NbNodes; i++)
1183 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1184 if (!aNode) return 0;
1188 int NbFaces = Quantities.length();
1189 std::vector<int> q (NbFaces);
1190 for (int j = 0; j < NbFaces; j++)
1191 q[j] = Quantities[j];
1193 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1195 // Update Python script
1196 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1197 << IDsOfNodes << ", " << Quantities << " )";
1199 declareMeshModified( /*isReComputeSafe=*/false );
1200 return elem ? elem->GetID() : 0;
1202 SMESH_CATCH( SMESH::throwCorbaException );
1206 //=============================================================================
1208 * AddPolyhedralVolumeByFaces
1210 //=============================================================================
1212 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1213 throw (SALOME::SALOME_Exception)
1218 int NbFaces = IdsOfFaces.length();
1219 std::vector<const SMDS_MeshNode*> poly_nodes;
1220 std::vector<int> quantities (NbFaces);
1222 for (int i = 0; i < NbFaces; i++) {
1223 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1224 quantities[i] = aFace->NbNodes();
1226 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1227 while (It->more()) {
1228 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1232 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1234 // Update Python script
1235 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1236 << IdsOfFaces << " )";
1238 declareMeshModified( /*isReComputeSafe=*/false );
1239 return elem ? elem->GetID() : 0;
1241 SMESH_CATCH( SMESH::throwCorbaException );
1245 //=============================================================================
1247 // \brief Create 0D elements on all nodes of the given object except those
1248 // nodes on which a 0D element already exists.
1249 // \param theObject object on whose nodes 0D elements will be created.
1250 // \param theGroupName optional name of a group to add 0D elements created
1251 // and/or found on nodes of \a theObject.
1252 // \return an object (a new group or a temporary SMESH_IDSource) holding
1253 // ids of new and/or found 0D elements.
1255 //=============================================================================
1257 SMESH::SMESH_IDSource_ptr
1258 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1259 const char* theGroupName)
1260 throw (SALOME::SALOME_Exception)
1265 SMESH::SMESH_IDSource_var result;
1268 TIDSortedElemSet elements, elems0D;
1269 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1270 getEditor().Create0DElementsOnAllNodes( elements, elems0D );
1272 SMESH::long_array_var newElems = new SMESH::long_array;
1273 newElems->length( elems0D.size() );
1274 TIDSortedElemSet::iterator eIt = elems0D.begin();
1275 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1276 newElems[ i ] = (*eIt)->GetID();
1278 SMESH::SMESH_GroupBase_var groupToFill;
1279 if ( theGroupName && strlen( theGroupName ))
1281 // Get existing group named theGroupName
1282 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1283 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1284 SMESH::SMESH_GroupBase_var group = groups[i];
1285 if ( !group->_is_nil() ) {
1286 CORBA::String_var name = group->GetName();
1287 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1288 groupToFill = group;
1293 if ( groupToFill->_is_nil() )
1294 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1295 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1296 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1299 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1301 group_i->Add( newElems );
1302 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1303 pyDump << groupToFill;
1307 result = MakeIDSource( newElems, SMESH::ELEM0D );
1308 pyDump << "elem0DIDs";
1311 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1312 << theObject << ", '" << theGroupName << "' )";
1314 return result._retn();
1316 SMESH_CATCH( SMESH::throwCorbaException );
1320 //=============================================================================
1322 * \brief Bind a node to a vertex
1323 * \param NodeID - node ID
1324 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1325 * \retval boolean - false if NodeID or VertexID is invalid
1327 //=============================================================================
1329 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1330 throw (SALOME::SALOME_Exception)
1334 SMESHDS_Mesh * mesh = getMeshDS();
1335 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1337 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1339 if ( mesh->MaxShapeIndex() < VertexID )
1340 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1342 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1343 if ( shape.ShapeType() != TopAbs_VERTEX )
1344 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1346 mesh->SetNodeOnVertex( node, VertexID );
1348 myMesh->SetIsModified( true );
1350 SMESH_CATCH( SMESH::throwCorbaException );
1353 //=============================================================================
1355 * \brief Store node position on an edge
1356 * \param NodeID - node ID
1357 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1358 * \param paramOnEdge - parameter on edge where the node is located
1359 * \retval boolean - false if any parameter is invalid
1361 //=============================================================================
1363 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1364 CORBA::Double paramOnEdge)
1365 throw (SALOME::SALOME_Exception)
1369 SMESHDS_Mesh * mesh = getMeshDS();
1370 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1372 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1374 if ( mesh->MaxShapeIndex() < EdgeID )
1375 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1377 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1378 if ( shape.ShapeType() != TopAbs_EDGE )
1379 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1382 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1383 if ( paramOnEdge < f || paramOnEdge > l )
1384 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1386 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1388 myMesh->SetIsModified( true );
1390 SMESH_CATCH( SMESH::throwCorbaException );
1393 //=============================================================================
1395 * \brief Store node position on a face
1396 * \param NodeID - node ID
1397 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1398 * \param u - U parameter on face where the node is located
1399 * \param v - V parameter on face where the node is located
1400 * \retval boolean - false if any parameter is invalid
1402 //=============================================================================
1404 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1405 CORBA::Double u, CORBA::Double v)
1406 throw (SALOME::SALOME_Exception)
1409 SMESHDS_Mesh * mesh = getMeshDS();
1410 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1412 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1414 if ( mesh->MaxShapeIndex() < FaceID )
1415 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1417 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1418 if ( shape.ShapeType() != TopAbs_FACE )
1419 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1421 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1422 bool isOut = ( u < surf.FirstUParameter() ||
1423 u > surf.LastUParameter() ||
1424 v < surf.FirstVParameter() ||
1425 v > surf.LastVParameter() );
1429 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1430 << " u( " << surf.FirstUParameter()
1431 << "," << surf.LastUParameter()
1432 << ") v( " << surf.FirstVParameter()
1433 << "," << surf.LastVParameter() << ")" );
1435 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1438 mesh->SetNodeOnFace( node, FaceID, u, v );
1439 myMesh->SetIsModified( true );
1441 SMESH_CATCH( SMESH::throwCorbaException );
1444 //=============================================================================
1446 * \brief Bind a node to a solid
1447 * \param NodeID - node ID
1448 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1449 * \retval boolean - false if NodeID or SolidID is invalid
1451 //=============================================================================
1453 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1454 throw (SALOME::SALOME_Exception)
1457 SMESHDS_Mesh * mesh = getMeshDS();
1458 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1460 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1462 if ( mesh->MaxShapeIndex() < SolidID )
1463 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1465 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1466 if ( shape.ShapeType() != TopAbs_SOLID &&
1467 shape.ShapeType() != TopAbs_SHELL)
1468 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1470 mesh->SetNodeInVolume( node, SolidID );
1472 SMESH_CATCH( SMESH::throwCorbaException );
1475 //=============================================================================
1477 * \brief Bind an element to a shape
1478 * \param ElementID - element ID
1479 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1481 //=============================================================================
1483 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1484 CORBA::Long ShapeID)
1485 throw (SALOME::SALOME_Exception)
1488 SMESHDS_Mesh * mesh = getMeshDS();
1489 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1491 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1493 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1494 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1496 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1497 if ( shape.ShapeType() != TopAbs_EDGE &&
1498 shape.ShapeType() != TopAbs_FACE &&
1499 shape.ShapeType() != TopAbs_SOLID &&
1500 shape.ShapeType() != TopAbs_SHELL )
1501 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1503 mesh->SetMeshElementOnShape( elem, ShapeID );
1505 myMesh->SetIsModified( true );
1507 SMESH_CATCH( SMESH::throwCorbaException );
1510 //=============================================================================
1514 //=============================================================================
1516 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1517 CORBA::Long NodeID2)
1518 throw (SALOME::SALOME_Exception)
1523 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1524 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1528 // Update Python script
1529 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1530 << NodeID1 << ", " << NodeID2 << " )";
1532 int ret = getEditor().InverseDiag ( n1, n2 );
1534 declareMeshModified( /*isReComputeSafe=*/false );
1537 SMESH_CATCH( SMESH::throwCorbaException );
1541 //=============================================================================
1545 //=============================================================================
1547 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1548 CORBA::Long NodeID2)
1549 throw (SALOME::SALOME_Exception)
1554 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1555 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1559 // Update Python script
1560 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1561 << NodeID1 << ", " << NodeID2 << " )";
1564 bool stat = getEditor().DeleteDiag ( n1, n2 );
1566 declareMeshModified( /*isReComputeSafe=*/!stat );
1570 SMESH_CATCH( SMESH::throwCorbaException );
1574 //=============================================================================
1578 //=============================================================================
1580 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1581 throw (SALOME::SALOME_Exception)
1586 for (int i = 0; i < IDsOfElements.length(); i++)
1588 CORBA::Long index = IDsOfElements[i];
1589 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1591 getEditor().Reorient( elem );
1593 // Update Python script
1594 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1596 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1599 SMESH_CATCH( SMESH::throwCorbaException );
1603 //=============================================================================
1607 //=============================================================================
1609 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1610 throw (SALOME::SALOME_Exception)
1615 TPythonDump aTPythonDump; // suppress dump in Reorient()
1617 prepareIdSource( theObject );
1619 SMESH::long_array_var anElementsId = theObject->GetIDs();
1620 CORBA::Boolean isDone = Reorient(anElementsId);
1622 // Update Python script
1623 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1625 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1628 SMESH_CATCH( SMESH::throwCorbaException );
1632 //=======================================================================
1633 //function : Reorient2D
1634 //purpose : Reorient faces contained in \a the2Dgroup.
1635 // the2Dgroup - the mesh or its part to reorient
1636 // theDirection - desired direction of normal of \a theFace
1637 // theFace - ID of face whose orientation is checked.
1638 // It can be < 1 then \a thePoint is used to find a face.
1639 // thePoint - is used to find a face if \a theFace < 1.
1640 // return number of reoriented elements.
1641 //=======================================================================
1643 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1644 const SMESH::DirStruct& theDirection,
1645 CORBA::Long theFace,
1646 const SMESH::PointStruct& thePoint)
1647 throw (SALOME::SALOME_Exception)
1650 initData(/*deleteSearchers=*/false);
1652 TIDSortedElemSet elements;
1653 IDSource_Error error;
1654 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1655 if ( error == IDSource_EMPTY )
1657 if ( error == IDSource_INVALID )
1658 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1661 const SMDS_MeshElement* face = 0;
1664 face = getMeshDS()->FindElement( theFace );
1666 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1667 if ( face->GetType() != SMDSAbs_Face )
1668 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1672 // create theElementSearcher if needed
1673 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1674 if ( !theElementSearcher )
1676 if ( elements.empty() ) // search in the whole mesh
1678 if ( myMesh->NbFaces() == 0 )
1679 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1681 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1685 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1686 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1688 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1692 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1693 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1696 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1697 if ( !elements.empty() && !elements.count( face ))
1698 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1701 const SMESH::PointStruct * P = &theDirection.PS;
1702 gp_Vec dirVec( P->x, P->y, P->z );
1703 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1704 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1706 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1709 declareMeshModified( /*isReComputeSafe=*/false );
1711 TPythonDump() << this << ".Reorient2D( "
1712 << the2Dgroup << ", "
1713 << theDirection << ", "
1715 << thePoint << " )";
1719 SMESH_CATCH( SMESH::throwCorbaException );
1723 //=======================================================================
1724 //function : Reorient2DBy3D
1725 //purpose : Reorient faces basing on orientation of adjacent volumes.
1726 //=======================================================================
1728 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1729 SMESH::SMESH_IDSource_ptr volumeGroup,
1730 CORBA::Boolean outsideNormal)
1731 throw (SALOME::SALOME_Exception)
1736 TIDSortedElemSet volumes;
1737 IDSource_Error volsError;
1738 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1741 for ( size_t i = 0; i < faceGroups.length(); ++i )
1743 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1745 TIDSortedElemSet faces;
1746 IDSource_Error error;
1747 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1748 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1749 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1750 if ( error == IDSource_OK && volsError != IDSource_OK )
1751 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1753 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1755 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1760 declareMeshModified( /*isReComputeSafe=*/false );
1762 TPythonDump() << this << ".Reorient2DBy3D( "
1763 << faceGroups << ", "
1764 << volumeGroup << ", "
1765 << outsideNormal << " )";
1769 SMESH_CATCH( SMESH::throwCorbaException );
1773 //=============================================================================
1775 * \brief Fuse neighbour triangles into quadrangles.
1777 //=============================================================================
1779 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1780 SMESH::NumericalFunctor_ptr Criterion,
1781 CORBA::Double MaxAngle)
1782 throw (SALOME::SALOME_Exception)
1787 SMESHDS_Mesh* aMesh = getMeshDS();
1788 TIDSortedElemSet faces,copyFaces;
1789 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1790 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1791 TIDSortedElemSet* workElements = & faces;
1793 if ( myIsPreviewMode ) {
1794 SMDSAbs_ElementType select = SMDSAbs_Face;
1795 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1796 workElements = & copyFaces;
1799 SMESH::NumericalFunctor_i* aNumericalFunctor =
1800 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1801 SMESH::Controls::NumericalFunctorPtr aCrit;
1802 if ( !aNumericalFunctor )
1803 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1805 aCrit = aNumericalFunctor->GetNumericalFunctor();
1807 if ( !myIsPreviewMode ) {
1808 // Update Python script
1809 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1810 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1813 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1815 declareMeshModified( /*isReComputeSafe=*/!stat );
1818 SMESH_CATCH( SMESH::throwCorbaException );
1822 //=============================================================================
1824 * \brief Fuse neighbour triangles into quadrangles.
1826 //=============================================================================
1828 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1829 SMESH::NumericalFunctor_ptr Criterion,
1830 CORBA::Double MaxAngle)
1831 throw (SALOME::SALOME_Exception)
1836 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1838 prepareIdSource( theObject );
1839 SMESH::long_array_var anElementsId = theObject->GetIDs();
1840 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1842 if ( !myIsPreviewMode ) {
1843 SMESH::NumericalFunctor_i* aNumericalFunctor =
1844 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1846 // Update Python script
1847 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1848 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1853 SMESH_CATCH( SMESH::throwCorbaException );
1857 //=============================================================================
1859 * \brief Split quadrangles into triangles.
1861 //=============================================================================
1863 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1864 SMESH::NumericalFunctor_ptr Criterion)
1865 throw (SALOME::SALOME_Exception)
1870 SMESHDS_Mesh* aMesh = getMeshDS();
1871 TIDSortedElemSet faces;
1872 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1874 SMESH::NumericalFunctor_i* aNumericalFunctor =
1875 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1876 SMESH::Controls::NumericalFunctorPtr aCrit;
1877 if ( !aNumericalFunctor )
1878 aCrit.reset( new SMESH::Controls::AspectRatio() );
1880 aCrit = aNumericalFunctor->GetNumericalFunctor();
1883 // Update Python script
1884 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1886 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1888 declareMeshModified( /*isReComputeSafe=*/false );
1891 SMESH_CATCH( SMESH::throwCorbaException );
1895 //=============================================================================
1897 * \brief Split quadrangles into triangles.
1899 //=============================================================================
1901 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1902 SMESH::NumericalFunctor_ptr Criterion)
1903 throw (SALOME::SALOME_Exception)
1908 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1910 prepareIdSource( theObject );
1911 SMESH::long_array_var anElementsId = theObject->GetIDs();
1912 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1914 SMESH::NumericalFunctor_i* aNumericalFunctor =
1915 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1917 // Update Python script
1918 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1920 declareMeshModified( /*isReComputeSafe=*/false );
1923 SMESH_CATCH( SMESH::throwCorbaException );
1927 //================================================================================
1929 * \brief Split each of quadrangles into 4 triangles.
1930 * \param [in] theObject - theQuads Container of quadrangles to split.
1932 //================================================================================
1934 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1935 throw (SALOME::SALOME_Exception)
1940 TIDSortedElemSet faces;
1941 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1943 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1945 getEditor().QuadTo4Tri( faces );
1946 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1948 SMESH_CATCH( SMESH::throwCorbaException );
1951 //=============================================================================
1953 * \brief Split quadrangles into triangles.
1955 //=============================================================================
1957 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1958 CORBA::Boolean Diag13)
1959 throw (SALOME::SALOME_Exception)
1964 SMESHDS_Mesh* aMesh = getMeshDS();
1965 TIDSortedElemSet faces;
1966 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1968 // Update Python script
1969 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1970 << IDsOfElements << ", " << Diag13 << " )";
1972 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1974 declareMeshModified( /*isReComputeSafe=*/ !stat );
1977 SMESH_CATCH( SMESH::throwCorbaException );
1981 //=============================================================================
1983 * \brief Split quadrangles into triangles.
1985 //=============================================================================
1987 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1988 CORBA::Boolean Diag13)
1989 throw (SALOME::SALOME_Exception)
1994 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
1996 prepareIdSource( theObject );
1997 SMESH::long_array_var anElementsId = theObject->GetIDs();
1998 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2000 // Update Python script
2001 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2002 << theObject << ", " << Diag13 << " )";
2004 declareMeshModified( /*isReComputeSafe=*/!isDone );
2007 SMESH_CATCH( SMESH::throwCorbaException );
2012 //=============================================================================
2014 * Find better splitting of the given quadrangle.
2015 * \param IDOfQuad ID of the quadrangle to be splitted.
2016 * \param Criterion A criterion to choose a diagonal for splitting.
2017 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2018 * diagonal is better, 0 if error occurs.
2020 //=============================================================================
2022 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2023 SMESH::NumericalFunctor_ptr Criterion)
2024 throw (SALOME::SALOME_Exception)
2029 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2030 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2032 SMESH::NumericalFunctor_i* aNumericalFunctor =
2033 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2034 SMESH::Controls::NumericalFunctorPtr aCrit;
2035 if (aNumericalFunctor)
2036 aCrit = aNumericalFunctor->GetNumericalFunctor();
2038 aCrit.reset(new SMESH::Controls::AspectRatio());
2040 int id = getEditor().BestSplit(quad, aCrit);
2041 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2045 SMESH_CATCH( SMESH::throwCorbaException );
2049 //================================================================================
2051 * \brief Split volumic elements into tetrahedrons
2053 //================================================================================
2055 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2056 CORBA::Short methodFlags)
2057 throw (SALOME::SALOME_Exception)
2062 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2063 const int noneFacet = -1;
2064 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2065 while( volIt->more() )
2066 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2068 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2069 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2071 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2072 << elems << ", " << methodFlags << " )";
2074 SMESH_CATCH( SMESH::throwCorbaException );
2077 //================================================================================
2079 * \brief Split hexahedra into triangular prisms
2080 * \param elems - elements to split
2081 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2082 * to split into triangles
2083 * \param methodFlags - flags passing splitting method:
2084 * 1 - split the hexahedron into 2 prisms
2085 * 2 - split the hexahedron into 4 prisms
2087 //================================================================================
2089 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2090 const SMESH::PointStruct & startHexPoint,
2091 const SMESH::DirStruct& facetToSplitNormal,
2092 CORBA::Short methodFlags,
2093 CORBA::Boolean allDomains)
2094 throw (SALOME::SALOME_Exception)
2098 prepareIdSource( elems );
2100 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2103 gp_Dir( facetToSplitNormal.PS.x,
2104 facetToSplitNormal.PS.y,
2105 facetToSplitNormal.PS.z ));
2106 TIDSortedElemSet elemSet;
2107 SMESH::long_array_var anElementsId = elems->GetIDs();
2108 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2109 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2111 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2112 while ( !elemSet.empty() )
2114 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2118 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2119 for ( ; ef != elemFacets.end(); ++ef )
2120 elemSet.erase( ef->first );
2123 if ( methodFlags == 2 )
2124 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2126 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2128 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2129 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2131 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2133 << startHexPoint << ", "
2134 << facetToSplitNormal<< ", "
2135 << methodFlags<< ", "
2136 << allDomains << " )";
2138 SMESH_CATCH( SMESH::throwCorbaException );
2141 //================================================================================
2143 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2144 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2145 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2146 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2147 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2148 * will be split in order to keep the mesh conformal.
2149 * \param elems - elements to split
2151 //================================================================================
2153 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2154 throw (SALOME::SALOME_Exception)
2159 TIDSortedElemSet elemSet;
2160 for ( size_t i = 0; i < theElems.length(); ++i )
2162 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2163 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2164 if ( mesh->GetId() != myMesh_i->GetId() )
2165 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2167 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2169 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2171 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2173 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2174 << theElems << " )";
2176 SMESH_CATCH( SMESH::throwCorbaException );
2179 //=======================================================================
2182 //=======================================================================
2185 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2186 const SMESH::long_array & IDsOfFixedNodes,
2187 CORBA::Long MaxNbOfIterations,
2188 CORBA::Double MaxAspectRatio,
2189 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2190 throw (SALOME::SALOME_Exception)
2192 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2193 MaxAspectRatio, Method, false );
2197 //=======================================================================
2198 //function : SmoothParametric
2200 //=======================================================================
2203 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2204 const SMESH::long_array & IDsOfFixedNodes,
2205 CORBA::Long MaxNbOfIterations,
2206 CORBA::Double MaxAspectRatio,
2207 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2208 throw (SALOME::SALOME_Exception)
2210 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2211 MaxAspectRatio, Method, true );
2215 //=======================================================================
2216 //function : SmoothObject
2218 //=======================================================================
2221 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2222 const SMESH::long_array & IDsOfFixedNodes,
2223 CORBA::Long MaxNbOfIterations,
2224 CORBA::Double MaxAspectRatio,
2225 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2226 throw (SALOME::SALOME_Exception)
2228 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2229 MaxAspectRatio, Method, false);
2233 //=======================================================================
2234 //function : SmoothParametricObject
2236 //=======================================================================
2239 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2240 const SMESH::long_array & IDsOfFixedNodes,
2241 CORBA::Long MaxNbOfIterations,
2242 CORBA::Double MaxAspectRatio,
2243 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2244 throw (SALOME::SALOME_Exception)
2246 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2247 MaxAspectRatio, Method, true);
2251 //=============================================================================
2255 //=============================================================================
2258 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2259 const SMESH::long_array & IDsOfFixedNodes,
2260 CORBA::Long MaxNbOfIterations,
2261 CORBA::Double MaxAspectRatio,
2262 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2264 throw (SALOME::SALOME_Exception)
2269 SMESHDS_Mesh* aMesh = getMeshDS();
2271 TIDSortedElemSet elements;
2272 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2274 set<const SMDS_MeshNode*> fixedNodes;
2275 for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
2276 CORBA::Long index = IDsOfFixedNodes[i];
2277 const SMDS_MeshNode * node = aMesh->FindNode(index);
2279 fixedNodes.insert( node );
2281 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2282 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2283 method = ::SMESH_MeshEditor::CENTROIDAL;
2285 getEditor().Smooth(elements, fixedNodes, method,
2286 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2288 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2290 // Update Python script
2291 TPythonDump() << "isDone = " << this << "."
2292 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2293 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2294 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2295 << "SMESH.SMESH_MeshEditor."
2296 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2297 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2301 SMESH_CATCH( SMESH::throwCorbaException );
2305 //=============================================================================
2309 //=============================================================================
2312 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2313 const SMESH::long_array & IDsOfFixedNodes,
2314 CORBA::Long MaxNbOfIterations,
2315 CORBA::Double MaxAspectRatio,
2316 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2318 throw (SALOME::SALOME_Exception)
2323 TPythonDump aTPythonDump; // suppress dump in smooth()
2325 prepareIdSource( theObject );
2326 SMESH::long_array_var anElementsId = theObject->GetIDs();
2327 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2328 MaxAspectRatio, Method, IsParametric);
2330 // Update Python script
2331 aTPythonDump << "isDone = " << this << "."
2332 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2333 << theObject << ", " << IDsOfFixedNodes << ", "
2334 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2335 << "SMESH.SMESH_MeshEditor."
2336 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2337 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2341 SMESH_CATCH( SMESH::throwCorbaException );
2345 //=============================================================================
2349 //=============================================================================
2351 void SMESH_MeshEditor_i::RenumberNodes()
2352 throw (SALOME::SALOME_Exception)
2355 // Update Python script
2356 TPythonDump() << this << ".RenumberNodes()";
2358 getMeshDS()->Renumber( true );
2360 SMESH_CATCH( SMESH::throwCorbaException );
2363 //=============================================================================
2367 //=============================================================================
2369 void SMESH_MeshEditor_i::RenumberElements()
2370 throw (SALOME::SALOME_Exception)
2373 // Update Python script
2374 TPythonDump() << this << ".RenumberElements()";
2376 getMeshDS()->Renumber( false );
2378 SMESH_CATCH( SMESH::throwCorbaException );
2381 //=======================================================================
2383 * \brief Return groups by their IDs
2385 //=======================================================================
2387 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2388 throw (SALOME::SALOME_Exception)
2393 myMesh_i->CreateGroupServants();
2394 return myMesh_i->GetGroups( *groupIDs );
2396 SMESH_CATCH( SMESH::throwCorbaException );
2400 //=======================================================================
2401 //function : RotationSweepObjects
2403 //=======================================================================
2405 SMESH::ListOfGroups*
2406 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2407 const SMESH::ListOfIDSources & theEdges,
2408 const SMESH::ListOfIDSources & theFaces,
2409 const SMESH::AxisStruct & theAxis,
2410 CORBA::Double theAngleInRadians,
2411 CORBA::Long theNbOfSteps,
2412 CORBA::Double theTolerance,
2413 const bool theMakeGroups)
2414 throw (SALOME::SALOME_Exception)
2419 TIDSortedElemSet elemsNodes[2];
2420 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2421 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2422 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2424 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2425 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2426 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2427 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2429 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2430 bool makeWalls=true;
2431 if ( myIsPreviewMode )
2433 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2434 TPreviewMesh * tmpMesh = getPreviewMesh();
2435 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2436 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2437 workElements = & copyElements[0];
2438 //makeWalls = false; -- faces are needed for preview
2441 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2443 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2444 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2446 ::SMESH_MeshEditor::PGroupIDs groupIds =
2447 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2448 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2450 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2452 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2454 if ( !myIsPreviewMode )
2456 dumpGroupsList( aPythonDump, aGroups );
2457 aPythonDump << this<< ".RotationSweepObjects( "
2462 << TVar( theAngleInRadians ) << ", "
2463 << TVar( theNbOfSteps ) << ", "
2464 << TVar( theTolerance ) << ", "
2465 << theMakeGroups << " )";
2469 getPreviewMesh()->Remove( SMDSAbs_Volume );
2472 return aGroups ? aGroups : new SMESH::ListOfGroups;
2474 SMESH_CATCH( SMESH::throwCorbaException );
2478 namespace MeshEditor_I
2481 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2483 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2485 bool myIsExtrusionByNormal;
2487 static int makeFlags( CORBA::Boolean MakeGroups,
2488 CORBA::Boolean ByAverageNormal = false,
2489 CORBA::Boolean UseInputElemsOnly = false,
2490 CORBA::Long Flags = 0,
2491 CORBA::Boolean MakeBoundary = true )
2493 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2494 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2495 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2496 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2500 ExtrusionParams(const SMESH::DirStruct & theDir,
2501 CORBA::Long theNbOfSteps,
2502 CORBA::Boolean theMakeGroups):
2503 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2507 makeFlags( theMakeGroups )),
2508 myIsExtrusionByNormal( false )
2512 ExtrusionParams(const SMESH::DirStruct & theDir,
2513 CORBA::Long theNbOfSteps,
2514 CORBA::Boolean theMakeGroups,
2515 CORBA::Long theExtrFlags,
2516 CORBA::Double theSewTolerance):
2517 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2521 makeFlags( theMakeGroups, false, false,
2522 theExtrFlags, false ),
2524 myIsExtrusionByNormal( false )
2527 // params for extrusion by normal
2528 ExtrusionParams(CORBA::Double theStepSize,
2529 CORBA::Long theNbOfSteps,
2530 CORBA::Short theDim,
2531 CORBA::Boolean theByAverageNormal,
2532 CORBA::Boolean theUseInputElemsOnly,
2533 CORBA::Boolean theMakeGroups ):
2534 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2536 makeFlags( theMakeGroups,
2537 theByAverageNormal, theUseInputElemsOnly ),
2539 myIsExtrusionByNormal( true )
2545 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2550 //=======================================================================
2552 * \brief Generate dim+1 elements by extrusion of elements along vector
2553 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2554 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2555 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2556 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2557 * \param [in] nbOfSteps - number of elements to generate from one element
2558 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2559 * corresponding to groups the input elements included in.
2560 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2562 //=======================================================================
2564 SMESH::ListOfGroups*
2565 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2566 const SMESH::ListOfIDSources & theEdges,
2567 const SMESH::ListOfIDSources & theFaces,
2568 const SMESH::DirStruct & theStepVector,
2569 CORBA::Long theNbOfSteps,
2570 CORBA::Boolean theToMakeGroups)
2571 throw (SALOME::SALOME_Exception)
2576 ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
2578 TIDSortedElemSet elemsNodes[2];
2579 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2580 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2581 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2583 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2584 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2585 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2586 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2588 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2589 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2590 if ( myIsPreviewMode )
2592 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2593 // previewType = SMDSAbs_Edge;
2595 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2596 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2597 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2598 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2599 workElements = & copyElements[0];
2601 params.SetNoGroups();
2603 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2605 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2606 ::SMESH_MeshEditor::PGroupIDs groupIds =
2607 getEditor().ExtrusionSweep( workElements, params, aHistory );
2609 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2611 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2613 if ( !myIsPreviewMode )
2615 dumpGroupsList( aPythonDump, aGroups );
2616 aPythonDump << this<< ".ExtrusionSweepObjects( "
2620 << theStepVector << ", "
2621 << TVar( theNbOfSteps ) << ", "
2622 << theToMakeGroups << " )";
2626 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2629 return aGroups ? aGroups : new SMESH::ListOfGroups;
2631 SMESH_CATCH( SMESH::throwCorbaException );
2635 //=======================================================================
2636 //function : ExtrusionByNormal
2638 //=======================================================================
2640 SMESH::ListOfGroups*
2641 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2642 CORBA::Double stepSize,
2643 CORBA::Long nbOfSteps,
2644 CORBA::Boolean byAverageNormal,
2645 CORBA::Boolean useInputElemsOnly,
2646 CORBA::Boolean makeGroups,
2648 throw (SALOME::SALOME_Exception)
2653 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2655 ExtrusionParams params( stepSize, nbOfSteps, dim,
2656 byAverageNormal, useInputElemsOnly, makeGroups );
2658 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2659 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2661 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2662 if (( elemTypes->length() == 1 ) &&
2663 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2664 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2667 TIDSortedElemSet elemsNodes[2];
2668 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2669 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2671 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2672 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2673 if ( myIsPreviewMode )
2675 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2676 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2677 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2678 workElements = & copyElements[0];
2680 params.SetNoGroups();
2683 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2684 ::SMESH_MeshEditor::PGroupIDs groupIds =
2685 getEditor().ExtrusionSweep( workElements, params, aHistory );
2687 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2689 if (!myIsPreviewMode) {
2690 dumpGroupsList(aPythonDump, aGroups);
2691 aPythonDump << this << ".ExtrusionByNormal( " << objects
2692 << ", " << TVar( stepSize )
2693 << ", " << TVar( nbOfSteps )
2694 << ", " << byAverageNormal
2695 << ", " << useInputElemsOnly
2696 << ", " << makeGroups
2702 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2705 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2707 return aGroups ? aGroups : new SMESH::ListOfGroups;
2709 SMESH_CATCH( SMESH::throwCorbaException );
2713 //=======================================================================
2714 //function : AdvancedExtrusion
2716 //=======================================================================
2718 SMESH::ListOfGroups*
2719 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2720 const SMESH::DirStruct & theStepVector,
2721 CORBA::Long theNbOfSteps,
2722 CORBA::Long theExtrFlags,
2723 CORBA::Double theSewTolerance,
2724 CORBA::Boolean theMakeGroups)
2725 throw (SALOME::SALOME_Exception)
2730 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2732 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2733 theExtrFlags, theSewTolerance );
2735 TIDSortedElemSet elemsNodes[2];
2736 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2738 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2739 ::SMESH_MeshEditor::PGroupIDs groupIds =
2740 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2742 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2744 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2746 if ( !myIsPreviewMode ) {
2747 dumpGroupsList(aPythonDump, aGroups);
2748 aPythonDump << this << ".AdvancedExtrusion( "
2749 << theIDsOfElements << ", "
2750 << theStepVector << ", "
2751 << theNbOfSteps << ", "
2752 << theExtrFlags << ", "
2753 << theSewTolerance << ", "
2754 << theMakeGroups << " )";
2758 getPreviewMesh()->Remove( SMDSAbs_Volume );
2761 return aGroups ? aGroups : new SMESH::ListOfGroups;
2763 SMESH_CATCH( SMESH::throwCorbaException );
2767 //================================================================================
2769 * \brief Convert extrusion error to IDL enum
2771 //================================================================================
2775 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2777 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2781 RETCASE( EXTR_NO_ELEMENTS );
2782 RETCASE( EXTR_PATH_NOT_EDGE );
2783 RETCASE( EXTR_BAD_PATH_SHAPE );
2784 RETCASE( EXTR_BAD_STARTING_NODE );
2785 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2786 RETCASE( EXTR_CANT_GET_TANGENT );
2788 return SMESH::SMESH_MeshEditor::EXTR_OK;
2792 //=======================================================================
2793 //function : extrusionAlongPath
2795 //=======================================================================
2796 SMESH::ListOfGroups*
2797 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2798 const SMESH::ListOfIDSources & theEdges,
2799 const SMESH::ListOfIDSources & theFaces,
2800 SMESH::SMESH_IDSource_ptr thePathMesh,
2801 GEOM::GEOM_Object_ptr thePathShape,
2802 CORBA::Long theNodeStart,
2803 CORBA::Boolean theHasAngles,
2804 const SMESH::double_array & theAngles,
2805 CORBA::Boolean theLinearVariation,
2806 CORBA::Boolean theHasRefPoint,
2807 const SMESH::PointStruct & theRefPoint,
2809 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2810 throw (SALOME::SALOME_Exception)
2815 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2817 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2818 if ( thePathMesh->_is_nil() )
2819 return aGroups._retn();
2822 SMESH_subMesh* aSubMesh = 0;
2823 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2824 if ( thePathShape->_is_nil() )
2826 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2827 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2829 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2830 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2831 if ( !aMeshImp ) return aGroups._retn();
2832 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2833 if ( !aSubMesh ) return aGroups._retn();
2835 else if ( !aMeshImp ||
2836 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2838 return aGroups._retn();
2843 if ( !aMeshImp ) return aGroups._retn();
2844 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2845 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2846 if ( !aSubMesh || !aSubMesh->GetSubMeshDS() )
2847 return aGroups._retn();
2850 SMDS_MeshNode* nodeStart =
2851 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2853 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2854 return aGroups._retn();
2857 TIDSortedElemSet elemsNodes[2];
2858 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2859 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2860 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2862 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2863 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2864 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2865 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2867 list<double> angles;
2868 for (int i = 0; i < theAngles.length(); i++) {
2869 angles.push_back( theAngles[i] );
2872 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2874 int nbOldGroups = myMesh->NbGroup();
2876 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2877 if ( myIsPreviewMode )
2879 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2880 TPreviewMesh * tmpMesh = getPreviewMesh();
2881 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2882 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2883 workElements = & copyElements[0];
2884 theMakeGroups = false;
2887 ::SMESH_MeshEditor::Extrusion_Error error;
2889 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2890 theHasAngles, angles, theLinearVariation,
2891 theHasRefPoint, refPnt, theMakeGroups );
2893 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2894 theHasAngles, angles, theLinearVariation,
2895 theHasRefPoint, refPnt, theMakeGroups );
2897 declareMeshModified( /*isReComputeSafe=*/true );
2898 theError = convExtrError( error );
2900 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2901 if ( theMakeGroups ) {
2902 list<int> groupIDs = myMesh->GetGroupIds();
2903 list<int>::iterator newBegin = groupIDs.begin();
2904 std::advance( newBegin, nbOldGroups ); // skip old groups
2905 groupIDs.erase( groupIDs.begin(), newBegin );
2906 aGroups = getGroups( & groupIDs );
2907 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2910 if ( !myIsPreviewMode ) {
2911 aPythonDump << "(" << aGroups << ", error) = "
2912 << this << ".ExtrusionAlongPathObjects( "
2916 << thePathMesh << ", "
2917 << thePathShape << ", "
2918 << theNodeStart << ", "
2919 << theHasAngles << ", "
2920 << theAngles << ", "
2921 << theLinearVariation << ", "
2922 << theHasRefPoint << ", "
2923 << "SMESH.PointStruct( "
2924 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2925 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2926 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2927 << theMakeGroups << " )";
2931 getPreviewMesh()->Remove( SMDSAbs_Volume );
2934 return aGroups._retn();
2936 SMESH_CATCH( SMESH::throwCorbaException );
2940 //================================================================================
2942 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2943 * of given angles along path steps
2944 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2945 * which proceeds the extrusion
2946 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2947 * is used to define the sub-mesh for the path
2949 //================================================================================
2951 SMESH::double_array*
2952 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2953 GEOM::GEOM_Object_ptr thePathShape,
2954 const SMESH::double_array & theAngles)
2956 SMESH::double_array_var aResult = new SMESH::double_array();
2957 int nbAngles = theAngles.length();
2958 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2960 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2961 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2962 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2963 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2964 return aResult._retn();
2965 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2966 if ( nbSteps == nbAngles )
2968 aResult.inout() = theAngles;
2972 aResult->length( nbSteps );
2973 double rAn2St = double( nbAngles ) / double( nbSteps );
2974 double angPrev = 0, angle;
2975 for ( int iSt = 0; iSt < nbSteps; ++iSt )
2977 double angCur = rAn2St * ( iSt+1 );
2978 double angCurFloor = floor( angCur );
2979 double angPrevFloor = floor( angPrev );
2980 if ( angPrevFloor == angCurFloor )
2981 angle = rAn2St * theAngles[ int( angCurFloor ) ];
2984 int iP = int( angPrevFloor );
2985 double angPrevCeil = ceil(angPrev);
2986 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2988 int iC = int( angCurFloor );
2989 if ( iC < nbAngles )
2990 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2992 iP = int( angPrevCeil );
2994 angle += theAngles[ iC ];
2996 aResult[ iSt ] = angle;
3001 // Update Python script
3002 TPythonDump() << "rotAngles = " << theAngles;
3003 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3004 << thePathMesh << ", "
3005 << thePathShape << ", "
3008 return aResult._retn();
3011 //=======================================================================
3014 //=======================================================================
3016 SMESH::ListOfGroups*
3017 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3018 const SMESH::AxisStruct & theAxis,
3019 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3020 CORBA::Boolean theCopy,
3022 ::SMESH_Mesh* theTargetMesh)
3023 throw (SALOME::SALOME_Exception)
3028 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3029 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3031 if ( theTargetMesh )
3035 switch ( theMirrorType ) {
3036 case SMESH::SMESH_MeshEditor::POINT:
3037 aTrsf.SetMirror( P );
3039 case SMESH::SMESH_MeshEditor::AXIS:
3040 aTrsf.SetMirror( gp_Ax1( P, V ));
3043 aTrsf.SetMirror( gp_Ax2( P, V ));
3046 TIDSortedElemSet copyElements;
3047 TIDSortedElemSet* workElements = & theElements;
3049 if ( myIsPreviewMode )
3051 TPreviewMesh * tmpMesh = getPreviewMesh();
3052 tmpMesh->Copy( theElements, copyElements);
3053 if ( !theCopy && !theTargetMesh )
3055 TIDSortedElemSet elemsAround, elemsAroundCopy;
3056 getElementsAround( theElements, getMeshDS(), elemsAround );
3057 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3059 workElements = & copyElements;
3060 theMakeGroups = false;
3063 ::SMESH_MeshEditor::PGroupIDs groupIds =
3064 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3066 if ( theCopy && !myIsPreviewMode)
3068 if ( theTargetMesh )
3070 theTargetMesh->GetMeshDS()->Modified();
3074 declareMeshModified( /*isReComputeSafe=*/false );
3077 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3079 SMESH_CATCH( SMESH::throwCorbaException );
3083 //=======================================================================
3086 //=======================================================================
3088 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3089 const SMESH::AxisStruct & theAxis,
3090 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3091 CORBA::Boolean theCopy)
3092 throw (SALOME::SALOME_Exception)
3094 if ( !myIsPreviewMode ) {
3095 TPythonDump() << this << ".Mirror( "
3096 << theIDsOfElements << ", "
3098 << mirrorTypeName(theMirrorType) << ", "
3101 if ( theIDsOfElements.length() > 0 )
3103 TIDSortedElemSet elements;
3104 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3105 mirror(elements, theAxis, theMirrorType, theCopy, false);
3110 //=======================================================================
3111 //function : MirrorObject
3113 //=======================================================================
3115 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3116 const SMESH::AxisStruct & theAxis,
3117 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3118 CORBA::Boolean theCopy)
3119 throw (SALOME::SALOME_Exception)
3121 if ( !myIsPreviewMode ) {
3122 TPythonDump() << this << ".MirrorObject( "
3123 << theObject << ", "
3125 << mirrorTypeName(theMirrorType) << ", "
3128 TIDSortedElemSet elements;
3130 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3132 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3133 mirror(elements, theAxis, theMirrorType, theCopy, false);
3136 //=======================================================================
3137 //function : MirrorMakeGroups
3139 //=======================================================================
3141 SMESH::ListOfGroups*
3142 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3143 const SMESH::AxisStruct& theMirror,
3144 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3145 throw (SALOME::SALOME_Exception)
3147 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3149 SMESH::ListOfGroups * aGroups = 0;
3150 if ( theIDsOfElements.length() > 0 )
3152 TIDSortedElemSet elements;
3153 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3154 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3156 if (!myIsPreviewMode) {
3157 dumpGroupsList(aPythonDump, aGroups);
3158 aPythonDump << this << ".MirrorMakeGroups( "
3159 << theIDsOfElements << ", "
3160 << theMirror << ", "
3161 << mirrorTypeName(theMirrorType) << " )";
3166 //=======================================================================
3167 //function : MirrorObjectMakeGroups
3169 //=======================================================================
3171 SMESH::ListOfGroups*
3172 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3173 const SMESH::AxisStruct& theMirror,
3174 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3175 throw (SALOME::SALOME_Exception)
3177 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3179 SMESH::ListOfGroups * aGroups = 0;
3180 TIDSortedElemSet elements;
3181 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3182 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3184 if (!myIsPreviewMode)
3186 dumpGroupsList(aPythonDump,aGroups);
3187 aPythonDump << this << ".MirrorObjectMakeGroups( "
3188 << theObject << ", "
3189 << theMirror << ", "
3190 << mirrorTypeName(theMirrorType) << " )";
3195 //=======================================================================
3196 //function : MirrorMakeMesh
3198 //=======================================================================
3200 SMESH::SMESH_Mesh_ptr
3201 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3202 const SMESH::AxisStruct& theMirror,
3203 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3204 CORBA::Boolean theCopyGroups,
3205 const char* theMeshName)
3206 throw (SALOME::SALOME_Exception)
3208 SMESH_Mesh_i* mesh_i;
3209 SMESH::SMESH_Mesh_var mesh;
3210 { // open new scope to dump "MakeMesh" command
3211 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3213 TPythonDump pydump; // to prevent dump at mesh creation
3215 mesh = makeMesh( theMeshName );
3216 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3217 if (mesh_i && theIDsOfElements.length() > 0 )
3219 TIDSortedElemSet elements;
3220 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3221 mirror(elements, theMirror, theMirrorType,
3222 false, theCopyGroups, & mesh_i->GetImpl());
3223 mesh_i->CreateGroupServants();
3226 if (!myIsPreviewMode) {
3227 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3228 << theIDsOfElements << ", "
3229 << theMirror << ", "
3230 << mirrorTypeName(theMirrorType) << ", "
3231 << theCopyGroups << ", '"
3232 << theMeshName << "' )";
3237 if (!myIsPreviewMode && mesh_i)
3238 mesh_i->GetGroups();
3240 return mesh._retn();
3243 //=======================================================================
3244 //function : MirrorObjectMakeMesh
3246 //=======================================================================
3248 SMESH::SMESH_Mesh_ptr
3249 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3250 const SMESH::AxisStruct& theMirror,
3251 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3252 CORBA::Boolean theCopyGroups,
3253 const char* theMeshName)
3254 throw (SALOME::SALOME_Exception)
3256 SMESH_Mesh_i* mesh_i;
3257 SMESH::SMESH_Mesh_var mesh;
3258 { // open new scope to dump "MakeMesh" command
3259 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3261 TPythonDump pydump; // to prevent dump at mesh creation
3263 mesh = makeMesh( theMeshName );
3264 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3265 TIDSortedElemSet elements;
3267 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3269 mirror(elements, theMirror, theMirrorType,
3270 false, theCopyGroups, & mesh_i->GetImpl());
3271 mesh_i->CreateGroupServants();
3273 if (!myIsPreviewMode) {
3274 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3275 << theObject << ", "
3276 << theMirror << ", "
3277 << mirrorTypeName(theMirrorType) << ", "
3278 << theCopyGroups << ", '"
3279 << theMeshName << "' )";
3284 if (!myIsPreviewMode && mesh_i)
3285 mesh_i->GetGroups();
3287 return mesh._retn();
3290 //=======================================================================
3291 //function : translate
3293 //=======================================================================
3295 SMESH::ListOfGroups*
3296 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3297 const SMESH::DirStruct & theVector,
3298 CORBA::Boolean theCopy,
3300 ::SMESH_Mesh* theTargetMesh)
3301 throw (SALOME::SALOME_Exception)
3306 if ( theTargetMesh )
3310 const SMESH::PointStruct * P = &theVector.PS;
3311 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3313 TIDSortedElemSet copyElements;
3314 TIDSortedElemSet* workElements = &theElements;
3316 if ( myIsPreviewMode )
3318 TPreviewMesh * tmpMesh = getPreviewMesh();
3319 tmpMesh->Copy( theElements, copyElements);
3320 if ( !theCopy && !theTargetMesh )
3322 TIDSortedElemSet elemsAround, elemsAroundCopy;
3323 getElementsAround( theElements, getMeshDS(), elemsAround );
3324 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3326 workElements = & copyElements;
3327 theMakeGroups = false;
3330 ::SMESH_MeshEditor::PGroupIDs groupIds =
3331 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3333 if ( theCopy && !myIsPreviewMode )
3335 if ( theTargetMesh )
3337 theTargetMesh->GetMeshDS()->Modified();
3341 declareMeshModified( /*isReComputeSafe=*/false );
3345 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3347 SMESH_CATCH( SMESH::throwCorbaException );
3351 //=======================================================================
3352 //function : Translate
3354 //=======================================================================
3356 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3357 const SMESH::DirStruct & theVector,
3358 CORBA::Boolean theCopy)
3359 throw (SALOME::SALOME_Exception)
3361 if (!myIsPreviewMode) {
3362 TPythonDump() << this << ".Translate( "
3363 << theIDsOfElements << ", "
3364 << theVector << ", "
3367 if (theIDsOfElements.length()) {
3368 TIDSortedElemSet elements;
3369 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3370 translate(elements, theVector, theCopy, false);
3374 //=======================================================================
3375 //function : TranslateObject
3377 //=======================================================================
3379 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3380 const SMESH::DirStruct & theVector,
3381 CORBA::Boolean theCopy)
3382 throw (SALOME::SALOME_Exception)
3384 if (!myIsPreviewMode) {
3385 TPythonDump() << this << ".TranslateObject( "
3386 << theObject << ", "
3387 << theVector << ", "
3390 TIDSortedElemSet elements;
3392 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3394 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3395 translate(elements, theVector, theCopy, false);
3398 //=======================================================================
3399 //function : TranslateMakeGroups
3401 //=======================================================================
3403 SMESH::ListOfGroups*
3404 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3405 const SMESH::DirStruct& theVector)
3406 throw (SALOME::SALOME_Exception)
3408 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3410 SMESH::ListOfGroups * aGroups = 0;
3411 if (theIDsOfElements.length()) {
3412 TIDSortedElemSet elements;
3413 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3414 aGroups = translate(elements,theVector,true,true);
3416 if (!myIsPreviewMode) {
3417 dumpGroupsList(aPythonDump, aGroups);
3418 aPythonDump << this << ".TranslateMakeGroups( "
3419 << theIDsOfElements << ", "
3420 << theVector << " )";
3425 //=======================================================================
3426 //function : TranslateObjectMakeGroups
3428 //=======================================================================
3430 SMESH::ListOfGroups*
3431 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3432 const SMESH::DirStruct& theVector)
3433 throw (SALOME::SALOME_Exception)
3435 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3437 SMESH::ListOfGroups * aGroups = 0;
3438 TIDSortedElemSet elements;
3439 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3440 aGroups = translate(elements, theVector, true, true);
3442 if (!myIsPreviewMode) {
3443 dumpGroupsList(aPythonDump, aGroups);
3444 aPythonDump << this << ".TranslateObjectMakeGroups( "
3445 << theObject << ", "
3446 << theVector << " )";
3451 //=======================================================================
3452 //function : TranslateMakeMesh
3454 //=======================================================================
3456 SMESH::SMESH_Mesh_ptr
3457 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3458 const SMESH::DirStruct& theVector,
3459 CORBA::Boolean theCopyGroups,
3460 const char* theMeshName)
3461 throw (SALOME::SALOME_Exception)
3463 SMESH_Mesh_i* mesh_i;
3464 SMESH::SMESH_Mesh_var mesh;
3466 { // open new scope to dump "MakeMesh" command
3467 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3469 TPythonDump pydump; // to prevent dump at mesh creation
3471 mesh = makeMesh( theMeshName );
3472 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3474 if ( mesh_i && theIDsOfElements.length() )
3476 TIDSortedElemSet elements;
3477 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3478 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3479 mesh_i->CreateGroupServants();
3482 if ( !myIsPreviewMode ) {
3483 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3484 << theIDsOfElements << ", "
3485 << theVector << ", "
3486 << theCopyGroups << ", '"
3487 << theMeshName << "' )";
3492 if (!myIsPreviewMode && mesh_i)
3493 mesh_i->GetGroups();
3495 return mesh._retn();
3498 //=======================================================================
3499 //function : TranslateObjectMakeMesh
3501 //=======================================================================
3503 SMESH::SMESH_Mesh_ptr
3504 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3505 const SMESH::DirStruct& theVector,
3506 CORBA::Boolean theCopyGroups,
3507 const char* theMeshName)
3508 throw (SALOME::SALOME_Exception)
3511 SMESH_Mesh_i* mesh_i;
3512 SMESH::SMESH_Mesh_var mesh;
3513 { // open new scope to dump "MakeMesh" command
3514 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3516 TPythonDump pydump; // to prevent dump at mesh creation
3517 mesh = makeMesh( theMeshName );
3518 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3520 TIDSortedElemSet elements;
3522 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3524 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3525 mesh_i->CreateGroupServants();
3527 if ( !myIsPreviewMode ) {
3528 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3529 << theObject << ", "
3530 << theVector << ", "
3531 << theCopyGroups << ", '"
3532 << theMeshName << "' )";
3537 if (!myIsPreviewMode && mesh_i)
3538 mesh_i->GetGroups();
3540 return mesh._retn();
3542 SMESH_CATCH( SMESH::throwCorbaException );
3546 //=======================================================================
3549 //=======================================================================
3551 SMESH::ListOfGroups*
3552 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3553 const SMESH::AxisStruct & theAxis,
3554 CORBA::Double theAngle,
3555 CORBA::Boolean theCopy,
3557 ::SMESH_Mesh* theTargetMesh)
3558 throw (SALOME::SALOME_Exception)
3563 if ( theTargetMesh )
3566 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3567 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3570 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3572 TIDSortedElemSet copyElements;
3573 TIDSortedElemSet* workElements = &theElements;
3574 if ( myIsPreviewMode ) {
3575 TPreviewMesh * tmpMesh = getPreviewMesh();
3576 tmpMesh->Copy( theElements, copyElements );
3577 if ( !theCopy && !theTargetMesh )
3579 TIDSortedElemSet elemsAround, elemsAroundCopy;
3580 getElementsAround( theElements, getMeshDS(), elemsAround );
3581 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3583 workElements = ©Elements;
3584 theMakeGroups = false;
3587 ::SMESH_MeshEditor::PGroupIDs groupIds =
3588 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3590 if ( theCopy && !myIsPreviewMode)
3592 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3593 else declareMeshModified( /*isReComputeSafe=*/false );
3596 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3598 SMESH_CATCH( SMESH::throwCorbaException );
3602 //=======================================================================
3605 //=======================================================================
3607 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3608 const SMESH::AxisStruct & theAxis,
3609 CORBA::Double theAngle,
3610 CORBA::Boolean theCopy)
3611 throw (SALOME::SALOME_Exception)
3613 if (!myIsPreviewMode) {
3614 TPythonDump() << this << ".Rotate( "
3615 << theIDsOfElements << ", "
3617 << TVar( theAngle ) << ", "
3620 if (theIDsOfElements.length() > 0)
3622 TIDSortedElemSet elements;
3623 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3624 rotate(elements,theAxis,theAngle,theCopy,false);
3628 //=======================================================================
3629 //function : RotateObject
3631 //=======================================================================
3633 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3634 const SMESH::AxisStruct & theAxis,
3635 CORBA::Double theAngle,
3636 CORBA::Boolean theCopy)
3637 throw (SALOME::SALOME_Exception)
3639 if ( !myIsPreviewMode ) {
3640 TPythonDump() << this << ".RotateObject( "
3641 << theObject << ", "
3643 << TVar( theAngle ) << ", "
3646 TIDSortedElemSet elements;
3647 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3648 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3649 rotate(elements,theAxis,theAngle,theCopy,false);
3652 //=======================================================================
3653 //function : RotateMakeGroups
3655 //=======================================================================
3657 SMESH::ListOfGroups*
3658 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3659 const SMESH::AxisStruct& theAxis,
3660 CORBA::Double theAngle)
3661 throw (SALOME::SALOME_Exception)
3663 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3665 SMESH::ListOfGroups * aGroups = 0;
3666 if (theIDsOfElements.length() > 0)
3668 TIDSortedElemSet elements;
3669 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3670 aGroups = rotate(elements,theAxis,theAngle,true,true);
3672 if (!myIsPreviewMode) {
3673 dumpGroupsList(aPythonDump, aGroups);
3674 aPythonDump << this << ".RotateMakeGroups( "
3675 << theIDsOfElements << ", "
3677 << TVar( theAngle ) << " )";
3682 //=======================================================================
3683 //function : RotateObjectMakeGroups
3685 //=======================================================================
3687 SMESH::ListOfGroups*
3688 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3689 const SMESH::AxisStruct& theAxis,
3690 CORBA::Double theAngle)
3691 throw (SALOME::SALOME_Exception)
3693 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3695 SMESH::ListOfGroups * aGroups = 0;
3696 TIDSortedElemSet elements;
3697 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3698 aGroups = rotate(elements, theAxis, theAngle, true, true);
3700 if (!myIsPreviewMode) {
3701 dumpGroupsList(aPythonDump, aGroups);
3702 aPythonDump << this << ".RotateObjectMakeGroups( "
3703 << theObject << ", "
3705 << TVar( theAngle ) << " )";
3710 //=======================================================================
3711 //function : RotateMakeMesh
3713 //=======================================================================
3715 SMESH::SMESH_Mesh_ptr
3716 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3717 const SMESH::AxisStruct& theAxis,
3718 CORBA::Double theAngleInRadians,
3719 CORBA::Boolean theCopyGroups,
3720 const char* theMeshName)
3721 throw (SALOME::SALOME_Exception)
3724 SMESH::SMESH_Mesh_var mesh;
3725 SMESH_Mesh_i* mesh_i;
3727 { // open new scope to dump "MakeMesh" command
3728 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3730 TPythonDump pydump; // to prevent dump at mesh creation
3732 mesh = makeMesh( theMeshName );
3733 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3735 if ( mesh_i && theIDsOfElements.length() > 0 )
3737 TIDSortedElemSet elements;
3738 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3739 rotate(elements, theAxis, theAngleInRadians,
3740 false, theCopyGroups, & mesh_i->GetImpl());
3741 mesh_i->CreateGroupServants();
3743 if ( !myIsPreviewMode ) {
3744 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3745 << theIDsOfElements << ", "
3747 << TVar( theAngleInRadians ) << ", "
3748 << theCopyGroups << ", '"
3749 << theMeshName << "' )";
3754 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3755 mesh_i->GetGroups();
3757 return mesh._retn();
3759 SMESH_CATCH( SMESH::throwCorbaException );
3763 //=======================================================================
3764 //function : RotateObjectMakeMesh
3766 //=======================================================================
3768 SMESH::SMESH_Mesh_ptr
3769 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3770 const SMESH::AxisStruct& theAxis,
3771 CORBA::Double theAngleInRadians,
3772 CORBA::Boolean theCopyGroups,
3773 const char* theMeshName)
3774 throw (SALOME::SALOME_Exception)
3777 SMESH::SMESH_Mesh_var mesh;
3778 SMESH_Mesh_i* mesh_i;
3780 {// open new scope to dump "MakeMesh" command
3781 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3783 TPythonDump pydump; // to prevent dump at mesh creation
3784 mesh = makeMesh( theMeshName );
3785 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3787 TIDSortedElemSet elements;
3789 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3791 rotate(elements, theAxis, theAngleInRadians,
3792 false, theCopyGroups, & mesh_i->GetImpl());
3793 mesh_i->CreateGroupServants();
3795 if ( !myIsPreviewMode ) {
3796 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3797 << theObject << ", "
3799 << TVar( theAngleInRadians ) << ", "
3800 << theCopyGroups << ", '"
3801 << theMeshName << "' )";
3806 if (!myIsPreviewMode && mesh_i)
3807 mesh_i->GetGroups();
3809 return mesh._retn();
3811 SMESH_CATCH( SMESH::throwCorbaException );
3815 //=======================================================================
3818 //=======================================================================
3820 SMESH::ListOfGroups*
3821 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3822 const SMESH::PointStruct& thePoint,
3823 const SMESH::double_array& theScaleFact,
3824 CORBA::Boolean theCopy,
3826 ::SMESH_Mesh* theTargetMesh)
3827 throw (SALOME::SALOME_Exception)
3831 if ( theScaleFact.length() < 1 )
3832 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3833 if ( theScaleFact.length() == 2 )
3834 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3836 if ( theTargetMesh )
3839 TIDSortedElemSet elements;
3840 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3841 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3846 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3847 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3851 #if OCC_VERSION_LARGE > 0x06070100
3852 // fight against orthogonalization
3853 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3854 // 0, S[1], 0, thePoint.y * (1-S[1]),
3855 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3856 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3857 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3858 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3859 loc.SetCoord( thePoint.x * (1-S[0]),
3860 thePoint.y * (1-S[1]),
3861 thePoint.z * (1-S[2]));
3862 M.SetDiagonal( S[0], S[1], S[2] );
3865 double tol = std::numeric_limits<double>::max();
3866 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3867 0, S[1], 0, thePoint.y * (1-S[1]),
3868 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3871 TIDSortedElemSet copyElements;
3872 TIDSortedElemSet* workElements = &elements;
3873 if ( myIsPreviewMode )
3875 TPreviewMesh * tmpMesh = getPreviewMesh();
3876 tmpMesh->Copy( elements, copyElements);
3877 if ( !theCopy && !theTargetMesh )
3879 TIDSortedElemSet elemsAround, elemsAroundCopy;
3880 getElementsAround( elements, getMeshDS(), elemsAround );
3881 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3883 workElements = & copyElements;
3884 theMakeGroups = false;
3887 ::SMESH_MeshEditor::PGroupIDs groupIds =
3888 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3890 if ( theCopy && !myIsPreviewMode )
3892 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3893 else declareMeshModified( /*isReComputeSafe=*/false );
3895 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3897 SMESH_CATCH( SMESH::throwCorbaException );
3901 //=======================================================================
3904 //=======================================================================
3906 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3907 const SMESH::PointStruct& thePoint,
3908 const SMESH::double_array& theScaleFact,
3909 CORBA::Boolean theCopy)
3910 throw (SALOME::SALOME_Exception)
3912 if ( !myIsPreviewMode ) {
3913 TPythonDump() << this << ".Scale( "
3914 << theObject << ", "
3916 << TVar( theScaleFact ) << ", "
3919 scale(theObject, thePoint, theScaleFact, theCopy, false);
3923 //=======================================================================
3924 //function : ScaleMakeGroups
3926 //=======================================================================
3928 SMESH::ListOfGroups*
3929 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3930 const SMESH::PointStruct& thePoint,
3931 const SMESH::double_array& theScaleFact)
3932 throw (SALOME::SALOME_Exception)
3934 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3936 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3937 if (!myIsPreviewMode) {
3938 dumpGroupsList(aPythonDump, aGroups);
3939 aPythonDump << this << ".Scale("
3942 << TVar( theScaleFact ) << ",True,True)";
3948 //=======================================================================
3949 //function : ScaleMakeMesh
3951 //=======================================================================
3953 SMESH::SMESH_Mesh_ptr
3954 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3955 const SMESH::PointStruct& thePoint,
3956 const SMESH::double_array& theScaleFact,
3957 CORBA::Boolean theCopyGroups,
3958 const char* theMeshName)
3959 throw (SALOME::SALOME_Exception)
3961 SMESH_Mesh_i* mesh_i;
3962 SMESH::SMESH_Mesh_var mesh;
3963 { // open new scope to dump "MakeMesh" command
3964 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3966 TPythonDump pydump; // to prevent dump at mesh creation
3967 mesh = makeMesh( theMeshName );
3968 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3972 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3973 mesh_i->CreateGroupServants();
3975 if ( !myIsPreviewMode )
3976 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3977 << theObject << ", "
3979 << TVar( theScaleFact ) << ", "
3980 << theCopyGroups << ", '"
3981 << theMeshName << "' )";
3985 if (!myIsPreviewMode && mesh_i)
3986 mesh_i->GetGroups();
3988 return mesh._retn();
3992 //=======================================================================
3993 //function : findCoincidentNodes
3995 //=======================================================================
3997 void SMESH_MeshEditor_i::
3998 findCoincidentNodes (TIDSortedNodeSet & Nodes,
3999 CORBA::Double Tolerance,
4000 SMESH::array_of_long_array_out GroupsOfNodes,
4001 CORBA::Boolean SeparateCornersAndMedium)
4003 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4004 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4006 GroupsOfNodes = new SMESH::array_of_long_array;
4007 GroupsOfNodes->length( aListOfListOfNodes.size() );
4008 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4009 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4011 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4012 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4013 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4014 aGroup.length( aListOfNodes.size() );
4015 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4016 aGroup[ j ] = (*lIt)->GetID();
4020 //=======================================================================
4021 //function : FindCoincidentNodes
4023 //=======================================================================
4025 void SMESH_MeshEditor_i::
4026 FindCoincidentNodes (CORBA::Double Tolerance,
4027 SMESH::array_of_long_array_out GroupsOfNodes,
4028 CORBA::Boolean SeparateCornersAndMedium)
4029 throw (SALOME::SALOME_Exception)
4034 TIDSortedNodeSet nodes; // no input nodes
4035 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4037 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4038 << Tolerance << ", "
4039 << SeparateCornersAndMedium << " )";
4041 SMESH_CATCH( SMESH::throwCorbaException );
4044 //=======================================================================
4045 //function : FindCoincidentNodesOnPart
4047 //=======================================================================
4049 void SMESH_MeshEditor_i::
4050 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4051 CORBA::Double Tolerance,
4052 SMESH::array_of_long_array_out GroupsOfNodes,
4053 CORBA::Boolean SeparateCornersAndMedium)
4054 throw (SALOME::SALOME_Exception)
4059 TIDSortedNodeSet nodes;
4060 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4062 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4064 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4066 << Tolerance << ", "
4067 << SeparateCornersAndMedium << " )";
4069 SMESH_CATCH( SMESH::throwCorbaException );
4072 //================================================================================
4074 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4075 * ExceptSubMeshOrGroups
4077 //================================================================================
4079 void SMESH_MeshEditor_i::
4080 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4081 CORBA::Double theTolerance,
4082 SMESH::array_of_long_array_out theGroupsOfNodes,
4083 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4084 CORBA::Boolean theSeparateCornersAndMedium)
4085 throw (SALOME::SALOME_Exception)
4090 TIDSortedNodeSet nodes;
4091 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4093 for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4095 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4097 while ( nodeIt->more() )
4098 nodes.erase( cast2Node( nodeIt->next() ));
4100 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4102 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4104 << theTolerance << ", "
4105 << theExceptSubMeshOrGroups << ", "
4106 << theSeparateCornersAndMedium << " )";
4108 SMESH_CATCH( SMESH::throwCorbaException );
4111 //=======================================================================
4112 //function : MergeNodes
4114 //=======================================================================
4116 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4117 const SMESH::ListOfIDSources& NodesToKeep)
4118 throw (SALOME::SALOME_Exception)
4123 SMESHDS_Mesh* aMesh = getMeshDS();
4125 TPythonDump aTPythonDump;
4126 aTPythonDump << this << ".MergeNodes([";
4128 TIDSortedNodeSet setOfNodesToKeep;
4129 for ( int i = 0; i < NodesToKeep.length(); ++i )
4131 prepareIdSource( NodesToKeep[i] );
4132 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
4133 while ( nodeIt->more() )
4134 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4137 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4138 for (int i = 0; i < GroupsOfNodes.length(); i++)
4140 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4141 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4142 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4143 for ( int j = 0; j < aNodeGroup.length(); j++ )
4145 CORBA::Long index = aNodeGroup[ j ];
4146 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4148 if ( setOfNodesToKeep.count( node ))
4149 aListOfNodes.push_front( node );
4151 aListOfNodes.push_back( node );
4154 if ( aListOfNodes.size() < 2 )
4155 aListOfListOfNodes.pop_back();
4157 if ( i > 0 ) aTPythonDump << ", ";
4158 aTPythonDump << aNodeGroup;
4161 getEditor().MergeNodes( aListOfListOfNodes );
4163 aTPythonDump << "], " << NodesToKeep << ")";
4165 declareMeshModified( /*isReComputeSafe=*/false );
4167 SMESH_CATCH( SMESH::throwCorbaException );
4170 //=======================================================================
4171 //function : FindEqualElements
4173 //=======================================================================
4175 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4176 SMESH::array_of_long_array_out GroupsOfElementsID)
4177 throw (SALOME::SALOME_Exception)
4182 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4183 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4185 TIDSortedElemSet elems;
4186 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4188 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4189 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4191 GroupsOfElementsID = new SMESH::array_of_long_array;
4192 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4194 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4195 aListOfListOfElementsID.begin();
4196 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4198 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4199 list<int>& listOfIDs = *arraysIt;
4200 aGroup.length( listOfIDs.size() );
4201 list<int>::iterator idIt = listOfIDs.begin();
4202 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4203 aGroup[ k ] = *idIt;
4206 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4210 SMESH_CATCH( SMESH::throwCorbaException );
4213 //=======================================================================
4214 //function : MergeElements
4216 //=======================================================================
4218 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4219 throw (SALOME::SALOME_Exception)
4224 TPythonDump aTPythonDump;
4225 aTPythonDump << this << ".MergeElements( [";
4227 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4229 for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4230 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4231 aListOfListOfElementsID.push_back( list< int >() );
4232 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4233 for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4234 CORBA::Long id = anElemsIDGroup[ j ];
4235 aListOfElemsID.push_back( id );
4237 if ( aListOfElemsID.size() < 2 )
4238 aListOfListOfElementsID.pop_back();
4239 if ( i > 0 ) aTPythonDump << ", ";
4240 aTPythonDump << anElemsIDGroup;
4243 getEditor().MergeElements(aListOfListOfElementsID);
4245 declareMeshModified( /*isReComputeSafe=*/true );
4247 aTPythonDump << "] )";
4249 SMESH_CATCH( SMESH::throwCorbaException );
4252 //=======================================================================
4253 //function : MergeEqualElements
4255 //=======================================================================
4257 void SMESH_MeshEditor_i::MergeEqualElements()
4258 throw (SALOME::SALOME_Exception)
4263 getEditor().MergeEqualElements();
4265 declareMeshModified( /*isReComputeSafe=*/true );
4267 TPythonDump() << this << ".MergeEqualElements()";
4269 SMESH_CATCH( SMESH::throwCorbaException );
4272 //=============================================================================
4274 * Move the node to a given point
4276 //=============================================================================
4278 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4282 throw (SALOME::SALOME_Exception)
4285 initData(/*deleteSearchers=*/false);
4287 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4291 if ( theNodeSearcher )
4292 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4294 if ( myIsPreviewMode ) // make preview data
4296 // in a preview mesh, make edges linked to a node
4297 TPreviewMesh& tmpMesh = *getPreviewMesh();
4298 TIDSortedElemSet linkedNodes;
4299 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4300 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4301 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4302 for ( ; nIt != linkedNodes.end(); ++nIt )
4304 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4305 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4309 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4310 // fill preview data
4312 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4313 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4315 getMeshDS()->MoveNode(node, x, y, z);
4317 if ( !myIsPreviewMode )
4319 // Update Python script
4320 TPythonDump() << "isDone = " << this << ".MoveNode( "
4321 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4322 declareMeshModified( /*isReComputeSafe=*/false );
4325 SMESH_CATCH( SMESH::throwCorbaException );
4330 //================================================================================
4332 * \brief Return ID of node closest to a given point
4334 //================================================================================
4336 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4339 throw (SALOME::SALOME_Exception)
4342 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4344 if ( !theNodeSearcher ) {
4345 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4348 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4349 return node->GetID();
4351 SMESH_CATCH( SMESH::throwCorbaException );
4355 //================================================================================
4357 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4358 * move the node closest to the point to point's location and return ID of the node
4360 //================================================================================
4362 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4365 CORBA::Long theNodeID)
4366 throw (SALOME::SALOME_Exception)
4369 // We keep theNodeSearcher until any mesh modification:
4370 // 1) initData() deletes theNodeSearcher at any edition,
4371 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4373 initData(/*deleteSearchers=*/false);
4375 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4377 int nodeID = theNodeID;
4378 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4379 if ( !node ) // preview moving node
4381 if ( !theNodeSearcher ) {
4382 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4385 node = theNodeSearcher->FindClosestTo( p );
4388 nodeID = node->GetID();
4389 if ( myIsPreviewMode ) // make preview data
4391 // in a preview mesh, make edges linked to a node
4392 TPreviewMesh tmpMesh = *getPreviewMesh();
4393 TIDSortedElemSet linkedNodes;
4394 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4395 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4396 for ( ; nIt != linkedNodes.end(); ++nIt )
4398 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4399 tmpMesh.Copy( &edge );
4402 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4404 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4405 // fill preview data
4407 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4409 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4413 getMeshDS()->MoveNode(node, x, y, z);
4417 if ( !myIsPreviewMode )
4419 TPythonDump() << "nodeID = " << this
4420 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4421 << ", " << nodeID << " )";
4423 declareMeshModified( /*isReComputeSafe=*/false );
4428 SMESH_CATCH( SMESH::throwCorbaException );
4432 //=======================================================================
4434 * Return elements of given type where the given point is IN or ON.
4436 * 'ALL' type means elements of any type excluding nodes
4438 //=======================================================================
4440 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4443 SMESH::ElementType type)
4444 throw (SALOME::SALOME_Exception)
4447 SMESH::long_array_var res = new SMESH::long_array;
4448 vector< const SMDS_MeshElement* > foundElems;
4450 theSearchersDeleter.Set( myMesh );
4451 if ( !theElementSearcher ) {
4452 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4454 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4455 SMDSAbs_ElementType( type ),
4457 res->length( foundElems.size() );
4458 for ( int i = 0; i < foundElems.size(); ++i )
4459 res[i] = foundElems[i]->GetID();
4463 SMESH_CATCH( SMESH::throwCorbaException );
4467 //=======================================================================
4468 //function : FindAmongElementsByPoint
4469 //purpose : Searching among the given elements, return elements of given type
4470 // where the given point is IN or ON.
4471 // 'ALL' type means elements of any type excluding nodes
4472 //=======================================================================
4475 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4479 SMESH::ElementType type)
4480 throw (SALOME::SALOME_Exception)
4483 SMESH::long_array_var res = new SMESH::long_array;
4485 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4486 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4487 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4488 type != types[0] ) // but search of elements of dim > 0
4491 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4492 return FindElementsByPoint( x,y,z, type );
4494 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4496 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4497 if ( !theElementSearcher )
4499 // create a searcher from elementIDs
4500 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4501 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4503 if ( !idSourceToSet( elementIDs, meshDS, elements,
4504 SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4507 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4508 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4510 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4513 vector< const SMDS_MeshElement* > foundElems;
4515 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4516 SMDSAbs_ElementType( type ),
4518 res->length( foundElems.size() );
4519 for ( int i = 0; i < foundElems.size(); ++i )
4520 res[i] = foundElems[i]->GetID();
4524 SMESH_CATCH( SMESH::throwCorbaException );
4528 //=======================================================================
4529 //function : GetPointState
4530 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4531 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4532 //=======================================================================
4534 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4537 throw (SALOME::SALOME_Exception)
4540 theSearchersDeleter.Set( myMesh );
4541 if ( !theElementSearcher ) {
4542 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4544 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4546 SMESH_CATCH( SMESH::throwCorbaException );
4550 //=======================================================================
4551 //function : convError
4553 //=======================================================================
4555 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4557 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4561 RETCASE( SEW_BORDER1_NOT_FOUND );
4562 RETCASE( SEW_BORDER2_NOT_FOUND );
4563 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4564 RETCASE( SEW_BAD_SIDE_NODES );
4565 RETCASE( SEW_VOLUMES_TO_SPLIT );
4566 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4567 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4568 RETCASE( SEW_BAD_SIDE1_NODES );
4569 RETCASE( SEW_BAD_SIDE2_NODES );
4571 return SMESH::SMESH_MeshEditor::SEW_OK;
4574 //=======================================================================
4575 //function : SewFreeBorders
4577 //=======================================================================
4579 SMESH::SMESH_MeshEditor::Sew_Error
4580 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4581 CORBA::Long SecondNodeID1,
4582 CORBA::Long LastNodeID1,
4583 CORBA::Long FirstNodeID2,
4584 CORBA::Long SecondNodeID2,
4585 CORBA::Long LastNodeID2,
4586 CORBA::Boolean CreatePolygons,
4587 CORBA::Boolean CreatePolyedrs)
4588 throw (SALOME::SALOME_Exception)
4593 SMESHDS_Mesh* aMesh = getMeshDS();
4595 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4596 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4597 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4598 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4599 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4600 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4602 if (!aBorderFirstNode ||
4603 !aBorderSecondNode||
4605 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4606 if (!aSide2FirstNode ||
4607 !aSide2SecondNode ||
4609 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4611 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4612 << FirstNodeID1 << ", "
4613 << SecondNodeID1 << ", "
4614 << LastNodeID1 << ", "
4615 << FirstNodeID2 << ", "
4616 << SecondNodeID2 << ", "
4617 << LastNodeID2 << ", "
4618 << CreatePolygons<< ", "
4619 << CreatePolyedrs<< " )";
4621 SMESH::SMESH_MeshEditor::Sew_Error error =
4622 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4633 declareMeshModified( /*isReComputeSafe=*/false );
4636 SMESH_CATCH( SMESH::throwCorbaException );
4637 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4641 //=======================================================================
4642 //function : SewConformFreeBorders
4644 //=======================================================================
4646 SMESH::SMESH_MeshEditor::Sew_Error
4647 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4648 CORBA::Long SecondNodeID1,
4649 CORBA::Long LastNodeID1,
4650 CORBA::Long FirstNodeID2,
4651 CORBA::Long SecondNodeID2)
4652 throw (SALOME::SALOME_Exception)
4657 SMESHDS_Mesh* aMesh = getMeshDS();
4659 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4660 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4661 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4662 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4663 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4664 const SMDS_MeshNode* aSide2ThirdNode = 0;
4666 if (!aBorderFirstNode ||
4667 !aBorderSecondNode||
4669 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4670 if (!aSide2FirstNode ||
4672 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4674 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4675 << FirstNodeID1 << ", "
4676 << SecondNodeID1 << ", "
4677 << LastNodeID1 << ", "
4678 << FirstNodeID2 << ", "
4679 << SecondNodeID2 << " )";
4681 SMESH::SMESH_MeshEditor::Sew_Error error =
4682 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4691 declareMeshModified( /*isReComputeSafe=*/false );
4694 SMESH_CATCH( SMESH::throwCorbaException );
4695 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4699 //=======================================================================
4700 //function : SewBorderToSide
4702 //=======================================================================
4704 SMESH::SMESH_MeshEditor::Sew_Error
4705 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4706 CORBA::Long SecondNodeIDOnFreeBorder,
4707 CORBA::Long LastNodeIDOnFreeBorder,
4708 CORBA::Long FirstNodeIDOnSide,
4709 CORBA::Long LastNodeIDOnSide,
4710 CORBA::Boolean CreatePolygons,
4711 CORBA::Boolean CreatePolyedrs)
4712 throw (SALOME::SALOME_Exception)
4717 SMESHDS_Mesh* aMesh = getMeshDS();
4719 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4720 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4721 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4722 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4723 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4724 const SMDS_MeshNode* aSide2ThirdNode = 0;
4726 if (!aBorderFirstNode ||
4727 !aBorderSecondNode||
4729 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4730 if (!aSide2FirstNode ||
4732 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4734 TPythonDump() << "error = " << this << ".SewBorderToSide( "
4735 << FirstNodeIDOnFreeBorder << ", "
4736 << SecondNodeIDOnFreeBorder << ", "
4737 << LastNodeIDOnFreeBorder << ", "
4738 << FirstNodeIDOnSide << ", "
4739 << LastNodeIDOnSide << ", "
4740 << CreatePolygons << ", "
4741 << CreatePolyedrs << ") ";
4743 SMESH::SMESH_MeshEditor::Sew_Error error =
4744 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4754 declareMeshModified( /*isReComputeSafe=*/false );
4757 SMESH_CATCH( SMESH::throwCorbaException );
4758 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4762 //=======================================================================
4763 //function : SewSideElements
4765 //=======================================================================
4767 SMESH::SMESH_MeshEditor::Sew_Error
4768 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4769 const SMESH::long_array& IDsOfSide2Elements,
4770 CORBA::Long NodeID1OfSide1ToMerge,
4771 CORBA::Long NodeID1OfSide2ToMerge,
4772 CORBA::Long NodeID2OfSide1ToMerge,
4773 CORBA::Long NodeID2OfSide2ToMerge)
4774 throw (SALOME::SALOME_Exception)
4779 SMESHDS_Mesh* aMesh = getMeshDS();
4781 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
4782 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
4783 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4784 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4786 if (!aFirstNode1ToMerge ||
4787 !aFirstNode2ToMerge )
4788 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4789 if (!aSecondNode1ToMerge||
4790 !aSecondNode2ToMerge)
4791 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4793 TIDSortedElemSet aSide1Elems, aSide2Elems;
4794 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4795 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4797 TPythonDump() << "error = " << this << ".SewSideElements( "
4798 << IDsOfSide1Elements << ", "
4799 << IDsOfSide2Elements << ", "
4800 << NodeID1OfSide1ToMerge << ", "
4801 << NodeID1OfSide2ToMerge << ", "
4802 << NodeID2OfSide1ToMerge << ", "
4803 << NodeID2OfSide2ToMerge << ")";
4805 SMESH::SMESH_MeshEditor::Sew_Error error =
4806 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
4809 aSecondNode1ToMerge,
4810 aSecondNode2ToMerge));
4812 declareMeshModified( /*isReComputeSafe=*/false );
4815 SMESH_CATCH( SMESH::throwCorbaException );
4816 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4819 //================================================================================
4821 * \brief Set new nodes for given element
4822 * \param ide - element id
4823 * \param newIDs - new node ids
4824 * \retval CORBA::Boolean - true if result is OK
4826 //================================================================================
4828 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4829 const SMESH::long_array& newIDs)
4830 throw (SALOME::SALOME_Exception)
4835 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
4836 if(!elem) return false;
4838 int nbn = newIDs.length();
4840 vector<const SMDS_MeshNode*> aNodes(nbn);
4843 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
4846 aNodes[nbn1] = aNode;
4849 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4850 << ide << ", " << newIDs << " )";
4852 MESSAGE("ChangeElementNodes");
4853 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4855 declareMeshModified( /*isReComputeSafe=*/ !res );
4859 SMESH_CATCH( SMESH::throwCorbaException );
4863 //=======================================================================
4865 * \brief Makes a part of the mesh quadratic or bi-quadratic
4867 //=======================================================================
4869 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
4870 CORBA::Boolean theToBiQuad,
4871 SMESH::SMESH_IDSource_ptr theObject)
4872 throw (SALOME::SALOME_Exception)
4877 TIDSortedElemSet elems;
4879 if ( !( elemsOK = CORBA::is_nil( theObject )))
4881 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
4882 SMDSAbs_All, /*emptyIfIsMesh=*/true );
4886 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
4887 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4889 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
4890 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
4892 declareMeshModified( /*isReComputeSafe=*/false );
4895 SMESH_CATCH( SMESH::throwCorbaException );
4898 //=======================================================================
4899 //function : ConvertFromQuadratic
4901 //=======================================================================
4903 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4904 throw (SALOME::SALOME_Exception)
4909 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
4910 TPythonDump() << this << ".ConvertFromQuadratic()";
4911 declareMeshModified( /*isReComputeSafe=*/!isDone );
4914 SMESH_CATCH( SMESH::throwCorbaException );
4918 //=======================================================================
4919 //function : ConvertToQuadratic
4921 //=======================================================================
4923 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4924 throw (SALOME::SALOME_Exception)
4926 convertToQuadratic( theForce3d, false );
4927 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
4930 //================================================================================
4932 * \brief Makes a part of the mesh quadratic
4934 //================================================================================
4936 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
4937 SMESH::SMESH_IDSource_ptr theObject)
4938 throw (SALOME::SALOME_Exception)
4940 convertToQuadratic( theForce3d, false, theObject );
4941 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
4944 //================================================================================
4946 * \brief Makes a part of the mesh bi-quadratic
4948 //================================================================================
4950 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
4951 SMESH::SMESH_IDSource_ptr theObject)
4952 throw (SALOME::SALOME_Exception)
4954 convertToQuadratic( theForce3d, true, theObject );
4955 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
4958 //================================================================================
4960 * \brief Makes a part of the mesh linear
4962 //================================================================================
4964 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
4965 throw (SALOME::SALOME_Exception)
4972 TIDSortedElemSet elems;
4973 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
4975 if ( elems.empty() )
4977 ConvertFromQuadratic();
4979 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
4981 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
4985 getEditor().ConvertFromQuadratic(elems);
4988 declareMeshModified( /*isReComputeSafe=*/false );
4990 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
4992 SMESH_CATCH( SMESH::throwCorbaException );
4995 //=======================================================================
4996 //function : makeMesh
4997 //purpose : create a named imported mesh
4998 //=======================================================================
5000 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5002 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5003 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5004 SALOMEDS::Study_var study = gen->GetCurrentStudy();
5005 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5006 gen->SetName( meshSO, theMeshName, "Mesh" );
5007 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5009 return mesh._retn();
5012 //=======================================================================
5013 //function : dumpGroupsList
5015 //=======================================================================
5017 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5018 const SMESH::ListOfGroups * theGroupList)
5020 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5021 if ( isDumpGroupList )
5022 theDumpPython << theGroupList << " = ";
5025 //================================================================================
5027 \brief Generates the unique group name.
5028 \param thePrefix name prefix
5031 //================================================================================
5033 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
5035 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5036 set<string> groupNames;
5038 // Get existing group names
5039 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5040 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5041 if (CORBA::is_nil(aGroup))
5044 CORBA::String_var name = aGroup->GetName();
5045 groupNames.insert( name.in() );
5049 string name = thePrefix;
5052 while (!groupNames.insert(name).second)
5053 name = SMESH_Comment( thePrefix ) << "_" << index++;
5058 //================================================================================
5060 * \brief Prepare SMESH_IDSource for work
5062 //================================================================================
5064 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5066 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5068 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5069 filter->SetMesh( mesh );
5072 //================================================================================
5074 * \brief Retrieve elements of given type from SMESH_IDSource
5076 //================================================================================
5078 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5079 const SMESHDS_Mesh* theMeshDS,
5080 TIDSortedElemSet& theElemSet,
5081 const SMDSAbs_ElementType theType,
5082 const bool emptyIfIsMesh,
5083 IDSource_Error* error)
5086 if ( error ) *error = IDSource_OK;
5088 if ( CORBA::is_nil( theIDSource ) )
5090 if ( error ) *error = IDSource_INVALID;
5093 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5095 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5096 *error = IDSource_EMPTY;
5099 prepareIdSource( theIDSource );
5100 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5101 if ( anIDs->length() == 0 )
5103 if ( error ) *error = IDSource_EMPTY;
5106 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5107 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5109 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5111 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5115 if ( error ) *error = IDSource_INVALID;
5121 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5122 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5124 if ( error ) *error = IDSource_INVALID;
5131 //================================================================================
5133 * \brief Duplicates given elements, i.e. creates new elements based on the
5134 * same nodes as the given ones.
5135 * \param theElements - container of elements to duplicate.
5136 * \param theGroupName - a name of group to contain the generated elements.
5137 * If a group with such a name already exists, the new elements
5138 * are added to the existng group, else a new group is created.
5139 * If \a theGroupName is empty, new elements are not added
5141 * \return a group where the new elements are added. NULL if theGroupName == "".
5144 //================================================================================
5146 SMESH::SMESH_Group_ptr
5147 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5148 const char* theGroupName)
5149 throw (SALOME::SALOME_Exception)
5151 SMESH::SMESH_Group_var newGroup;
5158 TIDSortedElemSet elems;
5159 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5161 getEditor().DoubleElements( elems );
5163 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5166 SMESH::ElementType type =
5167 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5168 // find existing group
5169 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5170 for ( size_t i = 0; i < groups->length(); ++i )
5171 if ( groups[i]->GetType() == type )
5173 CORBA::String_var name = groups[i]->GetName();
5174 if ( strcmp( name, theGroupName ) == 0 ) {
5175 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5179 // create a new group
5180 if ( newGroup->_is_nil() )
5181 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5183 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5185 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5186 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5187 for ( int i = 1; i <= aSeq.Length(); i++ )
5188 groupDS->SMDSGroup().Add( aSeq(i) );
5193 if ( !newGroup->_is_nil() )
5194 pyDump << newGroup << " = ";
5195 pyDump << this << ".DoubleElements( "
5196 << theElements << ", " << "'" << theGroupName <<"')";
5198 SMESH_CATCH( SMESH::throwCorbaException );
5200 return newGroup._retn();
5203 //================================================================================
5205 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5206 \param theNodes - identifiers of nodes to be doubled
5207 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5208 nodes. If list of element identifiers is empty then nodes are doubled but
5209 they not assigned to elements
5210 \return TRUE if operation has been completed successfully, FALSE otherwise
5211 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5213 //================================================================================
5215 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5216 const SMESH::long_array& theModifiedElems )
5217 throw (SALOME::SALOME_Exception)
5222 list< int > aListOfNodes;
5224 for ( i = 0, n = theNodes.length(); i < n; i++ )
5225 aListOfNodes.push_back( theNodes[ i ] );
5227 list< int > aListOfElems;
5228 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5229 aListOfElems.push_back( theModifiedElems[ i ] );
5231 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5233 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5235 // Update Python script
5236 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5240 SMESH_CATCH( SMESH::throwCorbaException );
5244 //================================================================================
5246 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5247 This method provided for convenience works as DoubleNodes() described above.
5248 \param theNodeId - identifier of node to be doubled.
5249 \param theModifiedElems - identifiers of elements to be updated.
5250 \return TRUE if operation has been completed successfully, FALSE otherwise
5251 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5253 //================================================================================
5255 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5256 const SMESH::long_array& theModifiedElems )
5257 throw (SALOME::SALOME_Exception)
5260 SMESH::long_array_var aNodes = new SMESH::long_array;
5261 aNodes->length( 1 );
5262 aNodes[ 0 ] = theNodeId;
5264 TPythonDump pyDump; // suppress dump by the next line
5266 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5268 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5272 SMESH_CATCH( SMESH::throwCorbaException );
5276 //================================================================================
5278 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5279 This method provided for convenience works as DoubleNodes() described above.
5280 \param theNodes - group of nodes to be doubled.
5281 \param theModifiedElems - group of elements to be updated.
5282 \return TRUE if operation has been completed successfully, FALSE otherwise
5283 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5285 //================================================================================
5287 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5288 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5289 throw (SALOME::SALOME_Exception)
5292 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5295 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5296 SMESH::long_array_var aModifiedElems;
5297 if ( !CORBA::is_nil( theModifiedElems ) )
5298 aModifiedElems = theModifiedElems->GetListOfID();
5301 aModifiedElems = new SMESH::long_array;
5302 aModifiedElems->length( 0 );
5305 TPythonDump pyDump; // suppress dump by the next line
5307 bool done = DoubleNodes( aNodes, aModifiedElems );
5309 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5313 SMESH_CATCH( SMESH::throwCorbaException );
5317 //================================================================================
5319 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5320 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5321 * \param theNodes - group of nodes to be doubled.
5322 * \param theModifiedElems - group of elements to be updated.
5323 * \return a new group with newly created nodes
5324 * \sa DoubleNodeGroup()
5326 //================================================================================
5328 SMESH::SMESH_Group_ptr
5329 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5330 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5331 throw (SALOME::SALOME_Exception)
5334 SMESH::SMESH_Group_var aNewGroup;
5336 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5337 return aNewGroup._retn();
5340 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5341 SMESH::long_array_var aModifiedElems;
5342 if ( !CORBA::is_nil( theModifiedElems ) )
5343 aModifiedElems = theModifiedElems->GetListOfID();
5345 aModifiedElems = new SMESH::long_array;
5346 aModifiedElems->length( 0 );
5349 TPythonDump pyDump; // suppress dump by the next line
5351 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5354 // Create group with newly created nodes
5355 SMESH::long_array_var anIds = GetLastCreatedNodes();
5356 if (anIds->length() > 0) {
5357 string anUnindexedName (theNodes->GetName());
5358 string aNewName = generateGroupName(anUnindexedName + "_double");
5359 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5360 aNewGroup->Add(anIds);
5361 pyDump << aNewGroup << " = ";
5365 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5366 << theModifiedElems << " )";
5368 return aNewGroup._retn();
5370 SMESH_CATCH( SMESH::throwCorbaException );
5374 //================================================================================
5376 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5377 This method provided for convenience works as DoubleNodes() described above.
5378 \param theNodes - list of groups of nodes to be doubled
5379 \param theModifiedElems - list of groups of elements to be updated.
5380 \return TRUE if operation has been completed successfully, FALSE otherwise
5381 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5383 //================================================================================
5385 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5386 const SMESH::ListOfGroups& theModifiedElems )
5387 throw (SALOME::SALOME_Exception)
5392 std::list< int > aNodes;
5394 for ( i = 0, n = theNodes.length(); i < n; i++ )
5396 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5397 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5399 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5400 for ( j = 0, m = aCurr->length(); j < m; j++ )
5401 aNodes.push_back( aCurr[ j ] );
5405 std::list< int > anElems;
5406 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5408 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5409 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5411 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5412 for ( j = 0, m = aCurr->length(); j < m; j++ )
5413 anElems.push_back( aCurr[ j ] );
5417 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5419 declareMeshModified( /*isReComputeSafe=*/false );
5421 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5425 SMESH_CATCH( SMESH::throwCorbaException );
5429 //================================================================================
5431 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5432 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5433 * \param theNodes - group of nodes to be doubled.
5434 * \param theModifiedElems - group of elements to be updated.
5435 * \return a new group with newly created nodes
5436 * \sa DoubleNodeGroups()
5438 //================================================================================
5440 SMESH::SMESH_Group_ptr
5441 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5442 const SMESH::ListOfGroups& theModifiedElems )
5443 throw (SALOME::SALOME_Exception)
5445 SMESH::SMESH_Group_var aNewGroup;
5447 TPythonDump pyDump; // suppress dump by the next line
5449 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5453 // Create group with newly created nodes
5454 SMESH::long_array_var anIds = GetLastCreatedNodes();
5455 if (anIds->length() > 0) {
5456 string anUnindexedName (theNodes[0]->GetName());
5457 string aNewName = generateGroupName(anUnindexedName + "_double");
5458 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5459 aNewGroup->Add(anIds);
5460 pyDump << aNewGroup << " = ";
5464 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5465 << theModifiedElems << " )";
5467 return aNewGroup._retn();
5471 //================================================================================
5473 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5474 \param theElems - the list of elements (edges or faces) to be replicated
5475 The nodes for duplication could be found from these elements
5476 \param theNodesNot - list of nodes to NOT replicate
5477 \param theAffectedElems - the list of elements (cells and edges) to which the
5478 replicated nodes should be associated to.
5479 \return TRUE if operation has been completed successfully, FALSE otherwise
5480 \sa DoubleNodeGroup(), DoubleNodeGroups()
5482 //================================================================================
5484 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5485 const SMESH::long_array& theNodesNot,
5486 const SMESH::long_array& theAffectedElems )
5487 throw (SALOME::SALOME_Exception)
5492 SMESHDS_Mesh* aMeshDS = getMeshDS();
5493 TIDSortedElemSet anElems, aNodes, anAffected;
5494 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5495 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5496 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5498 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5500 // Update Python script
5501 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5502 << theNodesNot << ", " << theAffectedElems << " )";
5504 declareMeshModified( /*isReComputeSafe=*/false );
5507 SMESH_CATCH( SMESH::throwCorbaException );
5511 //================================================================================
5513 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5514 \param theElems - the list of elements (edges or faces) to be replicated
5515 The nodes for duplication could be found from these elements
5516 \param theNodesNot - list of nodes to NOT replicate
5517 \param theShape - shape to detect affected elements (element which geometric center
5518 located on or inside shape).
5519 The replicated nodes should be associated to affected elements.
5520 \return TRUE if operation has been completed successfully, FALSE otherwise
5521 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5523 //================================================================================
5525 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5526 const SMESH::long_array& theNodesNot,
5527 GEOM::GEOM_Object_ptr theShape )
5528 throw (SALOME::SALOME_Exception)
5534 SMESHDS_Mesh* aMeshDS = getMeshDS();
5535 TIDSortedElemSet anElems, aNodes;
5536 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5537 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5539 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5540 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5542 // Update Python script
5543 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5544 << theNodesNot << ", " << theShape << " )";
5546 declareMeshModified( /*isReComputeSafe=*/false );
5549 SMESH_CATCH( SMESH::throwCorbaException );
5553 //================================================================================
5555 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5556 \param theElems - group of of elements (edges or faces) to be replicated
5557 \param theNodesNot - group of nodes not to replicated
5558 \param theAffectedElems - group of elements to which the replicated nodes
5559 should be associated to.
5560 \return TRUE if operation has been completed successfully, FALSE otherwise
5561 \sa DoubleNodes(), DoubleNodeGroups()
5563 //================================================================================
5566 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5567 SMESH::SMESH_GroupBase_ptr theNodesNot,
5568 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5569 throw (SALOME::SALOME_Exception)
5572 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5578 SMESHDS_Mesh* aMeshDS = getMeshDS();
5579 TIDSortedElemSet anElems, aNodes, anAffected;
5580 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5581 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5582 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5584 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5586 // Update Python script
5587 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5588 << theNodesNot << ", " << theAffectedElems << " )";
5590 declareMeshModified( /*isReComputeSafe=*/false );
5593 SMESH_CATCH( SMESH::throwCorbaException );
5597 //================================================================================
5599 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5600 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5601 * \param theElems - group of of elements (edges or faces) to be replicated
5602 * \param theNodesNot - group of nodes not to replicated
5603 * \param theAffectedElems - group of elements to which the replicated nodes
5604 * should be associated to.
5605 * \return a new group with newly created elements
5606 * \sa DoubleNodeElemGroup()
5608 //================================================================================
5610 SMESH::SMESH_Group_ptr
5611 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5612 SMESH::SMESH_GroupBase_ptr theNodesNot,
5613 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5614 throw (SALOME::SALOME_Exception)
5617 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5621 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5622 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5624 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5626 << theNodesNot << ", "
5627 << theAffectedElems << " )";
5629 return elemGroup._retn();
5632 //================================================================================
5634 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5635 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5636 * \param theElems - group of of elements (edges or faces) to be replicated
5637 * \param theNodesNot - group of nodes not to replicated
5638 * \param theAffectedElems - group of elements to which the replicated nodes
5639 * should be associated to.
5640 * \return a new group with newly created elements
5641 * \sa DoubleNodeElemGroup()
5643 //================================================================================
5645 SMESH::ListOfGroups*
5646 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5647 SMESH::SMESH_GroupBase_ptr theNodesNot,
5648 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5649 CORBA::Boolean theElemGroupNeeded,
5650 CORBA::Boolean theNodeGroupNeeded)
5651 throw (SALOME::SALOME_Exception)
5654 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5655 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5656 aTwoGroups->length( 2 );
5658 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5659 return aTwoGroups._retn();
5664 SMESHDS_Mesh* aMeshDS = getMeshDS();
5665 TIDSortedElemSet anElems, aNodes, anAffected;
5666 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5667 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5668 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5671 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5673 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5679 // Create group with newly created elements
5680 CORBA::String_var elemGroupName = theElems->GetName();
5681 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5682 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5684 SMESH::long_array_var anIds = GetLastCreatedElems();
5685 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5686 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5687 aNewElemGroup->Add(anIds);
5689 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5691 SMESH::long_array_var anIds = GetLastCreatedNodes();
5692 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5693 aNewNodeGroup->Add(anIds);
5697 // Update Python script
5700 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5701 else pyDump << aNewElemGroup << ", ";
5702 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5703 else pyDump << aNewNodeGroup << " ] = ";
5705 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5706 << theNodesNot << ", "
5707 << theAffectedElems << ", "
5708 << theElemGroupNeeded << ", "
5709 << theNodeGroupNeeded <<" )";
5711 aTwoGroups[0] = aNewElemGroup._retn();
5712 aTwoGroups[1] = aNewNodeGroup._retn();
5713 return aTwoGroups._retn();
5715 SMESH_CATCH( SMESH::throwCorbaException );
5719 //================================================================================
5721 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5722 \param theElems - group of of elements (edges or faces) to be replicated
5723 \param theNodesNot - group of nodes not to replicated
5724 \param theShape - shape to detect affected elements (element which geometric center
5725 located on or inside shape).
5726 The replicated nodes should be associated to affected elements.
5727 \return TRUE if operation has been completed successfully, FALSE otherwise
5728 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5730 //================================================================================
5733 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5734 SMESH::SMESH_GroupBase_ptr theNodesNot,
5735 GEOM::GEOM_Object_ptr theShape )
5736 throw (SALOME::SALOME_Exception)
5739 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5745 SMESHDS_Mesh* aMeshDS = getMeshDS();
5746 TIDSortedElemSet anElems, aNodes, anAffected;
5747 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5748 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5750 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5751 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5754 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5756 // Update Python script
5757 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5758 << theNodesNot << ", " << theShape << " )";
5761 SMESH_CATCH( SMESH::throwCorbaException );
5765 //================================================================================
5767 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
5768 * \param [in] theGrpList - groups
5769 * \param [in] theMeshDS - mesh
5770 * \param [out] theElemSet - set of elements
5771 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
5773 //================================================================================
5775 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5776 SMESHDS_Mesh* theMeshDS,
5777 TIDSortedElemSet& theElemSet,
5778 const bool theIsNodeGrp)
5780 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5782 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5783 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5784 : aGrp->GetType() != SMESH::NODE ) )
5786 SMESH::long_array_var anIDs = aGrp->GetIDs();
5787 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5792 //================================================================================
5794 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5795 This method provided for convenience works as DoubleNodes() described above.
5796 \param theElems - list of groups of elements (edges or faces) to be replicated
5797 \param theNodesNot - list of groups of nodes not to replicated
5798 \param theAffectedElems - group of elements to which the replicated nodes
5799 should be associated to.
5800 \return TRUE if operation has been completed successfully, FALSE otherwise
5801 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5803 //================================================================================
5806 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5807 const SMESH::ListOfGroups& theNodesNot,
5808 const SMESH::ListOfGroups& theAffectedElems)
5809 throw (SALOME::SALOME_Exception)
5815 SMESHDS_Mesh* aMeshDS = getMeshDS();
5816 TIDSortedElemSet anElems, aNodes, anAffected;
5817 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5818 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5819 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5821 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5823 // Update Python script
5824 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5825 << &theNodesNot << ", " << &theAffectedElems << " )";
5827 declareMeshModified( /*isReComputeSafe=*/false );
5830 SMESH_CATCH( SMESH::throwCorbaException );
5834 //================================================================================
5836 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5837 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5838 \param theElems - list of groups of elements (edges or faces) to be replicated
5839 \param theNodesNot - list of groups of nodes not to replicated
5840 \param theAffectedElems - group of elements to which the replicated nodes
5841 should be associated to.
5842 * \return a new group with newly created elements
5843 * \sa DoubleNodeElemGroups()
5845 //================================================================================
5847 SMESH::SMESH_Group_ptr
5848 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5849 const SMESH::ListOfGroups& theNodesNot,
5850 const SMESH::ListOfGroups& theAffectedElems)
5851 throw (SALOME::SALOME_Exception)
5854 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
5858 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5859 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5861 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
5863 << theNodesNot << ", "
5864 << theAffectedElems << " )";
5866 return elemGroup._retn();
5869 //================================================================================
5871 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5872 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5873 \param theElems - list of groups of elements (edges or faces) to be replicated
5874 \param theNodesNot - list of groups of nodes not to replicated
5875 \param theAffectedElems - group of elements to which the replicated nodes
5876 should be associated to.
5877 * \return a new group with newly created elements
5878 * \sa DoubleNodeElemGroups()
5880 //================================================================================
5882 SMESH::ListOfGroups*
5883 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
5884 const SMESH::ListOfGroups& theNodesNot,
5885 const SMESH::ListOfGroups& theAffectedElems,
5886 CORBA::Boolean theElemGroupNeeded,
5887 CORBA::Boolean theNodeGroupNeeded)
5888 throw (SALOME::SALOME_Exception)
5891 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5892 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5893 aTwoGroups->length( 2 );
5898 SMESHDS_Mesh* aMeshDS = getMeshDS();
5899 TIDSortedElemSet anElems, aNodes, anAffected;
5900 listOfGroupToSet(theElems, aMeshDS, anElems, false );
5901 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5902 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5904 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5906 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5911 // Create group with newly created elements
5912 CORBA::String_var elemGroupName = theElems[0]->GetName();
5913 string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
5914 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5916 SMESH::long_array_var anIds = GetLastCreatedElems();
5917 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5918 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5919 aNewElemGroup->Add(anIds);
5921 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5923 SMESH::long_array_var anIds = GetLastCreatedNodes();
5924 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5925 aNewNodeGroup->Add(anIds);
5929 // Update Python script
5932 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5933 else pyDump << aNewElemGroup << ", ";
5934 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5935 else pyDump << aNewNodeGroup << " ] = ";
5937 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
5938 << &theNodesNot << ", "
5939 << &theAffectedElems << ", "
5940 << theElemGroupNeeded << ", "
5941 << theNodeGroupNeeded << " )";
5943 aTwoGroups[0] = aNewElemGroup._retn();
5944 aTwoGroups[1] = aNewNodeGroup._retn();
5945 return aTwoGroups._retn();
5947 SMESH_CATCH( SMESH::throwCorbaException );
5951 //================================================================================
5953 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5954 This method provided for convenience works as DoubleNodes() described above.
5955 \param theElems - list of groups of elements (edges or faces) to be replicated
5956 \param theNodesNot - list of groups of nodes not to replicated
5957 \param theShape - shape to detect affected elements (element which geometric center
5958 located on or inside shape).
5959 The replicated nodes should be associated to affected elements.
5960 \return TRUE if operation has been completed successfully, FALSE otherwise
5961 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5963 //================================================================================
5966 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5967 const SMESH::ListOfGroups& theNodesNot,
5968 GEOM::GEOM_Object_ptr theShape )
5969 throw (SALOME::SALOME_Exception)
5975 SMESHDS_Mesh* aMeshDS = getMeshDS();
5976 TIDSortedElemSet anElems, aNodes;
5977 listOfGroupToSet(theElems, aMeshDS, anElems,false );
5978 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5980 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5981 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5983 // Update Python script
5984 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5985 << &theNodesNot << ", " << theShape << " )";
5987 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5990 SMESH_CATCH( SMESH::throwCorbaException );
5994 //================================================================================
5996 \brief Identify the elements that will be affected by node duplication (actual
5997 duplication is not performed.
5998 This method is the first step of DoubleNodeElemGroupsInRegion.
5999 \param theElems - list of groups of elements (edges or faces) to be replicated
6000 \param theNodesNot - list of groups of nodes not to replicated
6001 \param theShape - shape to detect affected elements (element which geometric center
6002 located on or inside shape).
6003 The replicated nodes should be associated to affected elements.
6004 \return groups of affected elements
6005 \sa DoubleNodeElemGroupsInRegion()
6007 //================================================================================
6008 SMESH::ListOfGroups*
6009 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6010 const SMESH::ListOfGroups& theNodesNot,
6011 GEOM::GEOM_Object_ptr theShape )
6012 throw (SALOME::SALOME_Exception)
6015 MESSAGE("AffectedElemGroupsInRegion");
6016 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6017 bool isEdgeGroup = false;
6018 bool isFaceGroup = false;
6019 bool isVolumeGroup = false;
6020 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6021 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6022 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6026 ::SMESH_MeshEditor aMeshEditor(myMesh);
6028 SMESHDS_Mesh* aMeshDS = getMeshDS();
6029 TIDSortedElemSet anElems, aNodes;
6030 listOfGroupToSet(theElems, aMeshDS, anElems, false);
6031 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6033 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6034 TIDSortedElemSet anAffected;
6035 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6038 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6043 int lg = anAffected.size();
6044 MESSAGE("lg="<< lg);
6045 SMESH::long_array_var volumeIds = new SMESH::long_array;
6046 volumeIds->length(lg);
6047 SMESH::long_array_var faceIds = new SMESH::long_array;
6048 faceIds->length(lg);
6049 SMESH::long_array_var edgeIds = new SMESH::long_array;
6050 edgeIds->length(lg);
6055 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6056 for (; eIt != anAffected.end(); ++eIt)
6058 const SMDS_MeshElement* anElem = *eIt;
6061 int elemId = anElem->GetID();
6062 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6063 volumeIds[ivol++] = elemId;
6064 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6065 faceIds[iface++] = elemId;
6066 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6067 edgeIds[iedge++] = elemId;
6069 volumeIds->length(ivol);
6070 faceIds->length(iface);
6071 edgeIds->length(iedge);
6073 aNewVolumeGroup->Add(volumeIds);
6074 aNewFaceGroup->Add(faceIds);
6075 aNewEdgeGroup->Add(edgeIds);
6076 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6077 isFaceGroup = (aNewFaceGroup->Size() > 0);
6078 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6082 if (isEdgeGroup) nbGroups++;
6083 if (isFaceGroup) nbGroups++;
6084 if (isVolumeGroup) nbGroups++;
6085 aListOfGroups->length(nbGroups);
6088 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6089 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6090 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6092 // Update Python script
6095 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6096 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6097 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6099 pyDump << this << ".AffectedElemGroupsInRegion( "
6100 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6102 return aListOfGroups._retn();
6104 SMESH_CATCH( SMESH::throwCorbaException );
6108 //================================================================================
6110 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6111 The created 2D mesh elements based on nodes of free faces of boundary volumes
6112 \return TRUE if operation has been completed successfully, FALSE otherwise
6114 //================================================================================
6116 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6117 throw (SALOME::SALOME_Exception)
6122 bool aResult = getEditor().Make2DMeshFrom3D();
6124 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6126 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6129 SMESH_CATCH( SMESH::throwCorbaException );
6133 //================================================================================
6135 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6136 * The list of groups must contain at least two groups. The groups have to be disjoint:
6137 * no common element into two different groups.
6138 * The nodes of the internal faces at the boundaries of the groups are doubled.
6139 * Optionally, the internal faces are replaced by flat elements.
6140 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6141 * The flat elements are stored in groups of volumes.
6142 * These groups are named according to the position of the group in the list:
6143 * 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.
6144 * 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.
6145 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6146 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6147 * \param theDomains - list of groups of volumes
6148 * \param createJointElems - if TRUE, create the elements
6149 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6150 * the boundary between \a theDomains and the rest mesh
6151 * \return TRUE if operation has been completed successfully, FALSE otherwise
6153 //================================================================================
6156 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6157 CORBA::Boolean createJointElems,
6158 CORBA::Boolean onAllBoundaries )
6159 throw (SALOME::SALOME_Exception)
6166 SMESHDS_Mesh* aMeshDS = getMeshDS();
6168 // MESSAGE("theDomains.length = "<<theDomains.length());
6169 if ( theDomains.length() <= 1 && !onAllBoundaries )
6170 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6172 vector<TIDSortedElemSet> domains;
6173 domains.resize( theDomains.length() );
6175 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6177 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6178 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6180 // if ( aGrp->GetType() != SMESH::VOLUME )
6181 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6182 SMESH::long_array_var anIDs = aGrp->GetIDs();
6183 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6187 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6188 // TODO publish the groups of flat elements in study
6190 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6192 // Update Python script
6193 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6194 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6196 SMESH_CATCH( SMESH::throwCorbaException );
6198 myMesh_i->CreateGroupServants(); // publish created groups if any
6203 //================================================================================
6205 * \brief Double nodes on some external faces and create flat elements.
6206 * Flat elements are mainly used by some types of mechanic calculations.
6208 * Each group of the list must be constituted of faces.
6209 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6210 * @param theGroupsOfFaces - list of groups of faces
6211 * @return TRUE if operation has been completed successfully, FALSE otherwise
6213 //================================================================================
6216 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6217 throw (SALOME::SALOME_Exception)
6222 SMESHDS_Mesh* aMeshDS = getMeshDS();
6224 vector<TIDSortedElemSet> faceGroups;
6227 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6229 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6230 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6232 TIDSortedElemSet faceGroup;
6234 faceGroups.push_back(faceGroup);
6235 SMESH::long_array_var anIDs = aGrp->GetIDs();
6236 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6240 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6241 // TODO publish the groups of flat elements in study
6243 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6245 // Update Python script
6246 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6249 SMESH_CATCH( SMESH::throwCorbaException );
6253 //================================================================================
6255 * \brief Identify all the elements around a geom shape, get the faces delimiting
6258 * Build groups of volume to remove, groups of faces to replace on the skin of the
6259 * object, groups of faces to remove inside the object, (idem edges).
6260 * Build ordered list of nodes at the border of each group of faces to replace
6261 * (to be used to build a geom subshape).
6263 //================================================================================
6265 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6266 GEOM::GEOM_Object_ptr theShape,
6267 const char* groupName,
6268 const SMESH::double_array& theNodesCoords,
6269 SMESH::array_of_long_array_out GroupsOfNodes)
6270 throw (SALOME::SALOME_Exception)
6275 std::vector<std::vector<int> > aListOfListOfNodes;
6276 ::SMESH_MeshEditor aMeshEditor( myMesh );
6278 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6279 if ( !theNodeSearcher )
6280 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6282 vector<double> nodesCoords;
6283 for (int i = 0; i < theNodesCoords.length(); i++)
6285 nodesCoords.push_back( theNodesCoords[i] );
6288 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6289 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6290 nodesCoords, aListOfListOfNodes);
6292 GroupsOfNodes = new SMESH::array_of_long_array;
6293 GroupsOfNodes->length( aListOfListOfNodes.size() );
6294 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6295 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6297 vector<int>& aListOfNodes = *llIt;
6298 vector<int>::iterator lIt = aListOfNodes.begin();;
6299 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6300 aGroup.length( aListOfNodes.size() );
6301 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6302 aGroup[ j ] = (*lIt);
6304 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6307 << ", '" << groupName << "', "
6308 << theNodesCoords << " )";
6310 SMESH_CATCH( SMESH::throwCorbaException );
6313 // issue 20749 ===================================================================
6315 * \brief Creates missing boundary elements
6316 * \param elements - elements whose boundary is to be checked
6317 * \param dimension - defines type of boundary elements to create
6318 * \param groupName - a name of group to store created boundary elements in,
6319 * "" means not to create the group
6320 * \param meshName - a name of new mesh to store created boundary elements in,
6321 * "" means not to create the new mesh
6322 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6323 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6324 * boundary elements will be copied into the new mesh
6325 * \param group - returns the create group, if any
6326 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6328 // ================================================================================
6330 SMESH::SMESH_Mesh_ptr
6331 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6332 SMESH::Bnd_Dimension dim,
6333 const char* groupName,
6334 const char* meshName,
6335 CORBA::Boolean toCopyElements,
6336 CORBA::Boolean toCopyExistingBondary,
6337 SMESH::SMESH_Group_out group)
6338 throw (SALOME::SALOME_Exception)
6343 if ( dim > SMESH::BND_1DFROM2D )
6344 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6346 SMESHDS_Mesh* aMeshDS = getMeshDS();
6348 SMESH::SMESH_Mesh_var mesh_var;
6349 SMESH::SMESH_Group_var group_var;
6353 TIDSortedElemSet elements;
6354 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6355 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6359 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6360 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6362 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6364 // group of new boundary elements
6365 SMESH_Group* smesh_group = 0;
6366 if ( strlen(groupName) )
6368 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6369 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6370 smesh_group = group_i->GetSmeshGroup();
6374 getEditor().MakeBoundaryMesh( elements,
6375 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6379 toCopyExistingBondary);
6382 smesh_mesh->GetMeshDS()->Modified();
6385 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6387 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6388 if ( mesh_var->_is_nil() )
6389 pyDump << myMesh_i->_this() << ", ";
6391 pyDump << mesh_var << ", ";
6392 if ( group_var->_is_nil() )
6393 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6395 pyDump << group_var << " = ";
6396 pyDump << this << ".MakeBoundaryMesh( "
6398 << "SMESH." << dimName[int(dim)] << ", "
6399 << "'" << groupName << "', "
6400 << "'" << meshName<< "', "
6401 << toCopyElements << ", "
6402 << toCopyExistingBondary << ")";
6404 group = group_var._retn();
6405 return mesh_var._retn();
6407 SMESH_CATCH( SMESH::throwCorbaException );
6408 return SMESH::SMESH_Mesh::_nil();
6411 //================================================================================
6413 * \brief Creates missing boundary elements
6414 * \param dimension - defines type of boundary elements to create
6415 * \param groupName - a name of group to store all boundary elements in,
6416 * "" means not to create the group
6417 * \param meshName - a name of a new mesh, which is a copy of the initial
6418 * mesh + created boundary elements; "" means not to create the new mesh
6419 * \param toCopyAll - if true, the whole initial mesh will be copied into
6420 * the new mesh else only boundary elements will be copied into the new mesh
6421 * \param groups - optional groups of elements to make boundary around
6422 * \param mesh - returns the mesh where elements were added to
6423 * \param group - returns the created group, if any
6424 * \retval long - number of added boundary elements
6426 //================================================================================
6428 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6429 const char* groupName,
6430 const char* meshName,
6431 CORBA::Boolean toCopyAll,
6432 const SMESH::ListOfIDSources& groups,
6433 SMESH::SMESH_Mesh_out mesh,
6434 SMESH::SMESH_Group_out group)
6435 throw (SALOME::SALOME_Exception)
6440 if ( dim > SMESH::BND_1DFROM2D )
6441 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6443 // separate groups belonging to this and other mesh
6444 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6445 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6446 groupsOfThisMesh->length( groups.length() );
6447 groupsOfOtherMesh->length( groups.length() );
6448 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6449 for ( int i = 0; i < groups.length(); ++i )
6451 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6452 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6453 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6455 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6456 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6457 THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6459 groupsOfThisMesh->length( nbGroups );
6460 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6465 if ( nbGroupsOfOtherMesh > 0 )
6467 // process groups belonging to another mesh
6468 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6469 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6470 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6471 groupsOfOtherMesh, mesh, group );
6474 SMESH::SMESH_Mesh_var mesh_var;
6475 SMESH::SMESH_Group_var group_var;
6478 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6479 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6483 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6485 /*toCopyGroups=*/false,
6486 /*toKeepIDs=*/true);
6488 mesh_var = makeMesh(meshName);
6490 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6491 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6494 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6495 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6497 // group of boundary elements
6498 SMESH_Group* smesh_group = 0;
6499 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6500 if ( strlen(groupName) )
6502 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6503 group_var = mesh_i->CreateGroup( groupType, groupName );
6504 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6505 smesh_group = group_i->GetSmeshGroup();
6508 TIDSortedElemSet elements;
6510 if ( groups.length() > 0 )
6512 for ( int i = 0; i < nbGroups; ++i )
6515 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6517 SMESH::Bnd_Dimension bdim =
6518 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6519 nbAdded += getEditor().MakeBoundaryMesh( elements,
6520 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6523 /*toCopyElements=*/false,
6524 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6525 /*toAddExistingBondary=*/true,
6526 /*aroundElements=*/true);
6532 nbAdded += getEditor().MakeBoundaryMesh( elements,
6533 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6536 /*toCopyElements=*/false,
6537 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6538 /*toAddExistingBondary=*/true);
6540 tgtMesh->GetMeshDS()->Modified();
6542 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6544 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6545 pyDump << "nbAdded, ";
6546 if ( mesh_var->_is_nil() )
6547 pyDump << myMesh_i->_this() << ", ";
6549 pyDump << mesh_var << ", ";
6550 if ( group_var->_is_nil() )
6551 pyDump << "_NoneGroup = "; // assignment to None is forbiden
6553 pyDump << group_var << " = ";
6554 pyDump << this << ".MakeBoundaryElements( "
6555 << "SMESH." << dimName[int(dim)] << ", "
6556 << "'" << groupName << "', "
6557 << "'" << meshName<< "', "
6558 << toCopyAll << ", "
6561 mesh = mesh_var._retn();
6562 group = group_var._retn();
6565 SMESH_CATCH( SMESH::throwCorbaException );