1 // Copyright (C) 2007-2019 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_SetIterator.hxx"
46 #include "SMDS_VolumeTool.hxx"
47 #include "SMESHDS_Group.hxx"
48 #include "SMESHDS_GroupOnGeom.hxx"
49 #include "SMESH_ControlsDef.hxx"
50 #include "SMESH_Filter_i.hxx"
51 #include "SMESH_Gen_i.hxx"
52 #include "SMESH_Group.hxx"
53 #include "SMESH_Group_i.hxx"
54 #include "SMESH_MeshAlgos.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PythonDump.hxx"
58 #include "SMESH_subMeshEventListener.hxx"
59 #include "SMESH_subMesh_i.hxx"
61 #include <utilities.h>
62 #include <Utils_ExceptHandlers.hxx>
63 #include <Utils_CorbaException.hxx>
64 #include <SALOMEDS_wrap.hxx>
65 #include <SALOME_GenericObj_i.hh>
67 #include <BRepAdaptor_Surface.hxx>
68 #include <BRep_Tool.hxx>
69 #include <TopExp_Explorer.hxx>
71 #include <TopoDS_Edge.hxx>
72 #include <TopoDS_Face.hxx>
77 #include <Standard_Failure.hxx>
78 #include <Standard_ErrorHandler.hxx>
83 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
85 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
88 using SMESH::TPythonDump;
91 namespace MeshEditor_I {
93 //=============================================================================
95 * \brief Mesh to apply modifications for preview purposes
97 //=============================================================================
99 struct TPreviewMesh: public SMESH_Mesh
101 SMDSAbs_ElementType myPreviewType; // type to show
103 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
104 _isShapeToMesh = (_id = 0);
105 _myMeshDS = new SMESHDS_Mesh( _id, true );
106 myPreviewType = previewElements;
108 //!< Copy a set of elements
109 void Copy(const TIDSortedElemSet & theElements,
110 TIDSortedElemSet& theCopyElements,
111 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
112 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
114 // loop on theIDsOfElements
115 TIDSortedElemSet::const_iterator eIt = theElements.begin();
116 for ( ; eIt != theElements.end(); ++eIt )
118 const SMDS_MeshElement* anElem = *eIt;
119 if ( !anElem ) continue;
120 SMDSAbs_ElementType type = anElem->GetType();
121 if ( type == theAvoidType ||
122 ( theSelectType != SMDSAbs_All && type != theSelectType ))
124 const SMDS_MeshElement* anElemCopy;
125 if ( type == SMDSAbs_Node)
126 anElemCopy = Copy( cast2Node(anElem) );
128 anElemCopy = Copy( anElem );
130 theCopyElements.insert( theCopyElements.end(), anElemCopy );
134 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
136 // copy element nodes
137 int anElemNbNodes = anElem->NbNodes();
138 vector< int > anElemNodesID( anElemNbNodes ) ;
139 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
140 for ( int i = 0; itElemNodes->more(); i++)
142 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
144 anElemNodesID[i] = anElemNode->GetID();
147 // creates a corresponding element on copied nodes
148 ::SMESH_MeshEditor::ElemFeatures elemType;
149 elemType.Init( anElem, /*basicOnly=*/false );
150 elemType.SetID( anElem->GetID() );
151 SMDS_MeshElement* anElemCopy =
152 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
156 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
158 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
159 anElemNode->GetID());
163 GetMeshDS()->ClearMesh();
165 void Remove( SMDSAbs_ElementType type )
167 Remove( GetMeshDS()->elementsIterator( type ));
169 void Remove( SMDS_ElemIteratorPtr eIt )
171 while ( eIt->more() )
172 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
174 };// struct TPreviewMesh
176 static SMESH_NodeSearcher * theNodeSearcher = 0;
177 static SMESH_ElementSearcher * theElementSearcher = 0;
179 //=============================================================================
181 * \brief Deleter of theNodeSearcher and theElementSearcher at any compute event occurred
183 //=============================================================================
185 struct TSearchersDeleter : public SMESH_subMeshEventListener
188 string myMeshPartIOR;
190 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
191 "SMESH_MeshEditor_i::TSearchersDeleter"),
193 //!< Delete theNodeSearcher
196 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
197 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
199 typedef map < int, SMESH_subMesh * > TDependsOnMap;
200 //!< The meshod called by submesh: do my main job
201 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
202 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
204 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
206 Unset( sm->GetFather() );
209 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
210 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
212 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
219 myMeshPartIOR = meshPartIOR;
220 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
221 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
222 while ( smIt->more() )
225 sm->SetEventListener( this, 0, sm );
229 //!< delete self from all submeshes
230 void Unset(SMESH_Mesh* mesh)
232 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
233 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
234 while ( smIt->more() )
235 smIt->next()->DeleteEventListener( this );
240 } theSearchersDeleter;
242 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
244 TCollection_AsciiString typeStr;
245 switch ( theMirrorType ) {
246 case SMESH::SMESH_MeshEditor::POINT:
247 typeStr = "SMESH.SMESH_MeshEditor.POINT";
249 case SMESH::SMESH_MeshEditor::AXIS:
250 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
253 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
257 //================================================================================
259 * \brief function for conversion of long_array to TIDSortedElemSet
260 * \param IDs - array of IDs
261 * \param aMesh - mesh
262 * \param aMap - collection to fill
263 * \param aType - element type
265 //================================================================================
267 void arrayToSet(const SMESH::long_array & IDs,
268 const SMESHDS_Mesh* aMesh,
269 TIDSortedElemSet& aMap,
270 const SMDSAbs_ElementType aType = SMDSAbs_All,
271 SMDS_MeshElement::Filter* aFilter = NULL)
273 SMDS_MeshElement::NonNullFilter filter1;
274 SMDS_MeshElement::TypeFilter filter2( aType );
276 if ( aFilter == NULL )
277 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
279 SMDS_MeshElement::Filter & filter = *aFilter;
281 if ( aType == SMDSAbs_Node )
282 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
283 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
285 aMap.insert( aMap.end(), elem );
288 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
289 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
291 aMap.insert( aMap.end(), elem );
295 //================================================================================
297 * \brief Retrieve nodes from SMESH_IDSource
299 //================================================================================
301 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
302 const SMESHDS_Mesh* theMeshDS,
303 TIDSortedNodeSet& theNodeSet)
306 if ( CORBA::is_nil( theObject ) )
308 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
310 for ( SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator(); nIt->more(); )
311 if ( const SMDS_MeshElement * elem = nIt->next() )
312 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
316 SMESH::array_of_ElementType_var types = theObject->GetTypes();
317 SMESH::long_array_var aElementsId = theObject->GetIDs();
318 if ( types->length() == 1 && types[0] == SMESH::NODE)
320 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
321 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
322 theNodeSet.insert( theNodeSet.end(), n);
326 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
327 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
328 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
333 //================================================================================
335 * \brief Returns elements connected to the given elements
337 //================================================================================
339 void getElementsAround(const TIDSortedElemSet& theElements,
340 const SMESHDS_Mesh* theMeshDS,
341 TIDSortedElemSet& theElementsAround)
343 if ( theElements.empty() ) return;
345 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
346 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
348 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
349 return; // all the elements are in theElements
352 elemType = SMDSAbs_All;
354 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
356 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
357 for ( ; elemIt != theElements.end(); ++elemIt )
359 const SMDS_MeshElement* e = *elemIt;
360 int i = e->NbCornerNodes();
363 const SMDS_MeshNode* n = e->GetNode( i );
364 if ( !isNodeChecked[ n->GetID() ])
366 isNodeChecked[ n->GetID() ] = true;
367 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
368 while ( invIt->more() )
370 const SMDS_MeshElement* elemAround = invIt->next();
371 if ( !theElements.count( elemAround ))
372 theElementsAround.insert( elemAround );
379 //================================================================================
381 * \brief Return a string used to detect change of mesh part on which theElementSearcher
382 * is going to be used
384 //================================================================================
386 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type = SMESH::ALL )
388 if ( SMESH::DownCast<SMESH_Mesh_i*>( theMeshPart ))
390 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
391 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
392 // take into account passible group modification
393 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
394 partIOR += SMESH_Comment( type );
398 } // namespace MeshEditor_I
400 using namespace MeshEditor_I;
402 //=============================================================================
406 //=============================================================================
408 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
410 myMesh( &theMesh->GetImpl() ),
412 myIsPreviewMode ( isPreview ),
418 //================================================================================
422 //================================================================================
424 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
426 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
427 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
428 poa->deactivate_object(anObjectId.in());
430 //deleteAuxIDSources();
431 delete myPreviewMesh; myPreviewMesh = 0;
432 delete myPreviewEditor; myPreviewEditor = 0;
435 //================================================================================
437 * \brief Returns the mesh
439 //================================================================================
441 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
443 return myMesh_i->_this();
446 //================================================================================
448 * \brief Clear members
450 //================================================================================
452 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
454 if ( myIsPreviewMode ) {
455 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
458 if ( deleteSearchers )
459 TSearchersDeleter::Delete();
461 getEditor().GetError().reset();
462 getEditor().ClearLastCreated();
465 //================================================================================
467 * \brief Increment mesh modif time and optionally record that the performed
468 * modification may influence further mesh re-compute.
469 * \param [in] isReComputeSafe - true if the modification does not influence
470 * further mesh re-compute
472 //================================================================================
474 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
476 myMesh->GetMeshDS()->Modified();
477 if ( !isReComputeSafe )
478 myMesh->SetIsModified( true );
481 //================================================================================
483 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
484 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
486 //================================================================================
488 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
490 if ( myIsPreviewMode && !myPreviewEditor ) {
491 if ( !myPreviewMesh ) getPreviewMesh();
492 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
494 return myIsPreviewMode ? *myPreviewEditor : myEditor;
497 //================================================================================
499 * \brief Initialize and return myPreviewMesh
500 * \param previewElements - type of elements to show in preview
502 * WARNING: call it once per method!
504 //================================================================================
506 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
508 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
510 delete myPreviewEditor;
512 delete myPreviewMesh;
513 myPreviewMesh = new TPreviewMesh( previewElements );
515 myPreviewMesh->Clear();
516 return myPreviewMesh;
519 //================================================================================
521 * Return data of mesh edition preview
523 //================================================================================
525 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
526 throw (SALOME::SALOME_Exception)
529 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
531 if ( myIsPreviewMode || hasBadElems )
533 list<int> aNodesConnectivity;
534 typedef map<int, int> TNodesMap;
537 SMESHDS_Mesh* aMeshDS;
538 std::unique_ptr< SMESH_MeshPartDS > aMeshPartDS;
540 const list<const SMDS_MeshElement*>& badElems =
541 static_cast<SMESH_BadInputElements*>( getEditor().GetError().get() )->myBadElements;
542 aMeshPartDS.reset( new SMESH_MeshPartDS( badElems ));
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.size() );
627 for ( size_t i = 0; i < aSeq.size(); i++)
628 myLastCreatedNodes[i] = aSeq[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.size() );
650 for ( size_t i = 0; i < aSeq.size(); i++ )
651 myLastCreatedElems[i] = aSeq[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 occurred 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->HasBadElems();
693 errOut->subShapeID = -1;
694 errOut->hasBadMesh = false;
697 return errOut._retn();
698 SMESH_CATCH( SMESH::throwCorbaException );
702 //=======================================================================
703 //function : MakeIDSource
704 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
705 // Call UnRegister() as you fininsh using it!!
706 //=======================================================================
708 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
709 public virtual SALOME::GenericObj_i
711 SMESH::long_array _ids;
712 SMESH::ElementType _type;
713 SMESH::SMESH_Mesh_ptr _mesh;
714 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
715 SMESH::long_array* GetMeshInfo() { return 0; }
716 SMESH::long_array* GetNbElementsByType()
718 SMESH::long_array_var aRes = new SMESH::long_array();
719 aRes->length(SMESH::NB_ELEMENT_TYPES);
720 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
721 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
724 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
725 bool IsMeshInfoCorrect() { return true; }
726 SMESH::array_of_ElementType* GetTypes()
728 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
729 if ( _ids.length() > 0 ) {
733 return types._retn();
735 SALOMEDS::TMPFile* GetVtkUgStream()
737 SALOMEDS::TMPFile_var SeqFile;
738 return SeqFile._retn();
742 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
743 SMESH::ElementType type)
745 _IDSource* idSrc = new _IDSource;
746 idSrc->_mesh = myMesh_i->_this();
749 if ( type == SMESH::ALL && ids.length() > 0 )
750 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
752 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
754 return anIDSourceVar._retn();
757 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
759 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
762 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
765 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
767 nbIds = (int) tmpIdSource->_ids.length();
768 return & tmpIdSource->_ids[0];
774 // void SMESH_MeshEditor_i::deleteAuxIDSources()
776 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
777 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
779 // myAuxIDSources.clear();
782 //=============================================================================
786 //=============================================================================
789 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
790 throw (SALOME::SALOME_Exception)
797 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
798 IdList.push_back( IDsOfElements[i] );
800 // Update Python script
801 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
804 bool ret = getEditor().Remove( IdList, false );
806 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
809 SMESH_CATCH( SMESH::throwCorbaException );
813 //=============================================================================
817 //=============================================================================
819 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
820 throw (SALOME::SALOME_Exception)
826 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
827 IdList.push_back( IDsOfNodes[i] );
829 // Update Python script
830 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
832 bool ret = getEditor().Remove( IdList, true );
834 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
837 SMESH_CATCH( SMESH::throwCorbaException );
841 //=============================================================================
845 //=============================================================================
847 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
848 throw (SALOME::SALOME_Exception)
853 // Update Python script
854 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
856 // Create filter to find all orphan nodes
857 SMESH::Controls::Filter::TIdSequence seq;
858 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
859 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
861 // remove orphan nodes (if there are any)
862 list< int > IdList( seq.begin(), seq.end() );
864 int nbNodesBefore = myMesh->NbNodes();
865 getEditor().Remove( IdList, true );
866 int nbNodesAfter = myMesh->NbNodes();
868 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
869 return nbNodesBefore - nbNodesAfter;
871 SMESH_CATCH( SMESH::throwCorbaException );
875 //=============================================================================
879 //=============================================================================
881 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
882 throw (SALOME::SALOME_Exception)
887 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
889 // Update Python script
890 TPythonDump() << "nodeID = " << this << ".AddNode( "
891 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
893 declareMeshModified( /*isReComputeSafe=*/false );
896 SMESH_CATCH( SMESH::throwCorbaException );
900 //=============================================================================
902 * Create 0D element on the given node.
904 //=============================================================================
906 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode,
907 CORBA::Boolean DuplicateElements)
908 throw (SALOME::SALOME_Exception)
913 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
914 SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
916 SMDS_MeshElement* elem = 0;
917 if ( DuplicateElements || !it0D->more() )
918 elem = getMeshDS()->Add0DElement(aNode);
920 // Update Python script
921 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
923 declareMeshModified( /*isReComputeSafe=*/false );
925 return elem ? elem->GetID() : 0;
927 SMESH_CATCH( SMESH::throwCorbaException );
931 //=============================================================================
933 * Create a ball element on the given node.
935 //=============================================================================
937 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
938 throw (SALOME::SALOME_Exception)
943 if ( diameter < std::numeric_limits<double>::min() )
944 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
946 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
947 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
949 // Update Python script
950 TPythonDump() << "ballElem = "
951 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
953 declareMeshModified( /*isReComputeSafe=*/false );
954 return elem ? elem->GetID() : 0;
956 SMESH_CATCH( SMESH::throwCorbaException );
960 //=============================================================================
962 * Create an edge, either linear and quadratic (this is determed
963 * by number of given nodes, two or three)
965 //=============================================================================
967 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
968 throw (SALOME::SALOME_Exception)
973 int NbNodes = IDsOfNodes.length();
974 SMDS_MeshElement* elem = 0;
977 CORBA::Long index1 = IDsOfNodes[0];
978 CORBA::Long index2 = IDsOfNodes[1];
979 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
980 getMeshDS()->FindNode(index2));
982 // Update Python script
983 TPythonDump() << "edge = " << this << ".AddEdge([ "
984 << index1 << ", " << index2 <<" ])";
987 CORBA::Long n1 = IDsOfNodes[0];
988 CORBA::Long n2 = IDsOfNodes[1];
989 CORBA::Long n12 = IDsOfNodes[2];
990 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
991 getMeshDS()->FindNode(n2),
992 getMeshDS()->FindNode(n12));
993 // Update Python script
994 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
995 <<n1<<", "<<n2<<", "<<n12<<" ])";
998 declareMeshModified( /*isReComputeSafe=*/false );
999 return elem ? elem->GetID() : 0;
1001 SMESH_CATCH( SMESH::throwCorbaException );
1005 //=============================================================================
1009 //=============================================================================
1011 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1012 throw (SALOME::SALOME_Exception)
1017 int NbNodes = IDsOfNodes.length();
1023 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1024 for (int i = 0; i < NbNodes; i++)
1025 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1027 SMDS_MeshElement* elem = 0;
1029 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1030 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1031 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1032 nodes[4], nodes[5]); break;
1033 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1034 nodes[4], nodes[5], nodes[6]); break;
1035 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1036 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1037 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1038 nodes[4], nodes[5], nodes[6], nodes[7],
1040 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1043 // Update Python script
1044 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1046 declareMeshModified( /*isReComputeSafe=*/false );
1048 return elem ? elem->GetID() : 0;
1050 SMESH_CATCH( SMESH::throwCorbaException );
1054 //=============================================================================
1058 //=============================================================================
1060 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1061 throw (SALOME::SALOME_Exception)
1066 int NbNodes = IDsOfNodes.length();
1067 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1068 for (int i = 0; i < NbNodes; i++)
1069 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1072 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1074 // Update Python script
1075 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1077 declareMeshModified( /*isReComputeSafe=*/false );
1078 return elem ? elem->GetID() : 0;
1080 SMESH_CATCH( SMESH::throwCorbaException );
1084 //=============================================================================
1086 * AddQuadPolygonalFace
1088 //=============================================================================
1090 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1091 throw (SALOME::SALOME_Exception)
1096 int NbNodes = IDsOfNodes.length();
1097 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1098 for (int i = 0; i < NbNodes; i++)
1099 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1101 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1103 // Update Python script
1104 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1106 declareMeshModified( /*isReComputeSafe=*/false );
1107 return elem ? elem->GetID() : 0;
1109 SMESH_CATCH( SMESH::throwCorbaException );
1113 //=============================================================================
1115 * Create volume, either linear and quadratic (this is determed
1116 * by number of given nodes)
1118 //=============================================================================
1120 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1121 throw (SALOME::SALOME_Exception)
1126 int NbNodes = IDsOfNodes.length();
1127 vector< const SMDS_MeshNode*> n(NbNodes);
1128 for(int i=0;i<NbNodes;i++)
1129 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1131 SMDS_MeshElement* elem = 0;
1134 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1135 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1136 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1137 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1138 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1139 n[6],n[7],n[8],n[9]);
1141 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1142 n[6],n[7],n[8],n[9],n[10],n[11]);
1144 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1145 n[7],n[8],n[9],n[10],n[11],n[12]);
1147 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1148 n[9],n[10],n[11],n[12],n[13],n[14]);
1150 case 20: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]);
1154 case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1155 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1158 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1159 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1160 n[15],n[16],n[17],n[18],n[19],
1161 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1165 // Update Python script
1166 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1168 declareMeshModified( /*isReComputeSafe=*/false );
1169 return elem ? elem->GetID() : 0;
1171 SMESH_CATCH( SMESH::throwCorbaException );
1175 //=============================================================================
1177 * AddPolyhedralVolume
1179 //=============================================================================
1180 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1181 const SMESH::long_array & Quantities)
1182 throw (SALOME::SALOME_Exception)
1187 int NbNodes = IDsOfNodes.length();
1188 std::vector<const SMDS_MeshNode*> n (NbNodes);
1189 for (int i = 0; i < NbNodes; i++)
1191 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1192 if (!aNode) return 0;
1196 int NbFaces = Quantities.length();
1197 std::vector<int> q (NbFaces);
1198 for (int j = 0; j < NbFaces; j++)
1199 q[j] = Quantities[j];
1201 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1203 // Update Python script
1204 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1205 << IDsOfNodes << ", " << Quantities << " )";
1207 declareMeshModified( /*isReComputeSafe=*/false );
1208 return elem ? elem->GetID() : 0;
1210 SMESH_CATCH( SMESH::throwCorbaException );
1214 //=============================================================================
1216 * AddPolyhedralVolumeByFaces
1218 //=============================================================================
1220 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1221 throw (SALOME::SALOME_Exception)
1226 int NbFaces = IdsOfFaces.length();
1227 std::vector<const SMDS_MeshNode*> poly_nodes;
1228 std::vector<int> quantities (NbFaces);
1230 for (int i = 0; i < NbFaces; i++) {
1231 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1232 quantities[i] = aFace->NbNodes();
1234 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1235 while (It->more()) {
1236 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1240 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1242 // Update Python script
1243 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1244 << IdsOfFaces << " )";
1246 declareMeshModified( /*isReComputeSafe=*/false );
1247 return elem ? elem->GetID() : 0;
1249 SMESH_CATCH( SMESH::throwCorbaException );
1253 //=============================================================================
1255 // \brief Create 0D elements on all nodes of the given object.
1256 // \param theObject object on whose nodes 0D elements will be created.
1257 // \param theGroupName optional name of a group to add 0D elements created
1258 // and/or found on nodes of \a theObject.
1259 // \param DuplicateElements to add one more 0D element to a node or not.
1260 // \return an object (a new group or a temporary SMESH_IDSource) holding
1261 // ids of new and/or found 0D elements.
1263 //=============================================================================
1265 SMESH::SMESH_IDSource_ptr
1266 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1267 const char* theGroupName,
1268 CORBA::Boolean theDuplicateElements)
1269 throw (SALOME::SALOME_Exception)
1274 SMESH::SMESH_IDSource_var result;
1277 TIDSortedElemSet elements, elems0D;
1278 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1279 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1281 SMESH::long_array_var newElems = new SMESH::long_array;
1282 newElems->length( elems0D.size() );
1283 TIDSortedElemSet::iterator eIt = elems0D.begin();
1284 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1285 newElems[ i ] = (*eIt)->GetID();
1287 SMESH::SMESH_GroupBase_var groupToFill;
1288 if ( theGroupName && strlen( theGroupName ))
1290 // Get existing group named theGroupName
1291 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1292 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1293 SMESH::SMESH_GroupBase_var group = groups[i];
1294 if ( !group->_is_nil() ) {
1295 CORBA::String_var name = group->GetName();
1296 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1297 groupToFill = group;
1302 if ( groupToFill->_is_nil() )
1303 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1304 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1305 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1308 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1310 group_i->Add( newElems );
1311 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1312 pyDump << groupToFill;
1316 result = MakeIDSource( newElems, SMESH::ELEM0D );
1317 pyDump << "elem0DIDs";
1320 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1321 << theObject << ", '" << theGroupName << "' )";
1323 return result._retn();
1325 SMESH_CATCH( SMESH::throwCorbaException );
1329 //=============================================================================
1331 * \brief Bind a node to a vertex
1332 * \param NodeID - node ID
1333 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1334 * \retval boolean - false if NodeID or VertexID is invalid
1336 //=============================================================================
1338 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1339 throw (SALOME::SALOME_Exception)
1343 SMESHDS_Mesh * mesh = getMeshDS();
1344 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1346 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1348 if ( mesh->MaxShapeIndex() < VertexID )
1349 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1351 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1352 if ( shape.ShapeType() != TopAbs_VERTEX )
1353 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1355 mesh->SetNodeOnVertex( node, VertexID );
1357 myMesh->SetIsModified( true );
1359 SMESH_CATCH( SMESH::throwCorbaException );
1362 //=============================================================================
1364 * \brief Store node position on an edge
1365 * \param NodeID - node ID
1366 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1367 * \param paramOnEdge - parameter on edge where the node is located
1368 * \retval boolean - false if any parameter is invalid
1370 //=============================================================================
1372 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1373 CORBA::Double paramOnEdge)
1374 throw (SALOME::SALOME_Exception)
1378 SMESHDS_Mesh * mesh = getMeshDS();
1379 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1381 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1383 if ( mesh->MaxShapeIndex() < EdgeID )
1384 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1386 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1387 if ( shape.ShapeType() != TopAbs_EDGE )
1388 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1391 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1392 if ( paramOnEdge < f || paramOnEdge > l )
1393 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1395 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1397 myMesh->SetIsModified( true );
1399 SMESH_CATCH( SMESH::throwCorbaException );
1402 //=============================================================================
1404 * \brief Store node position on a face
1405 * \param NodeID - node ID
1406 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1407 * \param u - U parameter on face where the node is located
1408 * \param v - V parameter on face where the node is located
1409 * \retval boolean - false if any parameter is invalid
1411 //=============================================================================
1413 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1414 CORBA::Double u, CORBA::Double v)
1415 throw (SALOME::SALOME_Exception)
1418 SMESHDS_Mesh * mesh = getMeshDS();
1419 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1421 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1423 if ( mesh->MaxShapeIndex() < FaceID )
1424 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1426 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1427 if ( shape.ShapeType() != TopAbs_FACE )
1428 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1430 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1431 bool isOut = ( u < surf.FirstUParameter() ||
1432 u > surf.LastUParameter() ||
1433 v < surf.FirstVParameter() ||
1434 v > surf.LastVParameter() );
1438 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1439 << " u( " << surf.FirstUParameter()
1440 << "," << surf.LastUParameter()
1441 << ") v( " << surf.FirstVParameter()
1442 << "," << surf.LastVParameter() << ")" );
1444 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1447 mesh->SetNodeOnFace( node, FaceID, u, v );
1448 myMesh->SetIsModified( true );
1450 SMESH_CATCH( SMESH::throwCorbaException );
1453 //=============================================================================
1455 * \brief Bind a node to a solid
1456 * \param NodeID - node ID
1457 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1458 * \retval boolean - false if NodeID or SolidID is invalid
1460 //=============================================================================
1462 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1463 throw (SALOME::SALOME_Exception)
1466 SMESHDS_Mesh * mesh = getMeshDS();
1467 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1469 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1471 if ( mesh->MaxShapeIndex() < SolidID )
1472 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1474 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1475 if ( shape.ShapeType() != TopAbs_SOLID &&
1476 shape.ShapeType() != TopAbs_SHELL)
1477 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1479 mesh->SetNodeInVolume( node, SolidID );
1481 SMESH_CATCH( SMESH::throwCorbaException );
1484 //=============================================================================
1486 * \brief Bind an element to a shape
1487 * \param ElementID - element ID
1488 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1490 //=============================================================================
1492 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1493 CORBA::Long ShapeID)
1494 throw (SALOME::SALOME_Exception)
1497 SMESHDS_Mesh * mesh = getMeshDS();
1498 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1500 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1502 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1503 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1505 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1506 if ( shape.ShapeType() != TopAbs_EDGE &&
1507 shape.ShapeType() != TopAbs_FACE &&
1508 shape.ShapeType() != TopAbs_SOLID &&
1509 shape.ShapeType() != TopAbs_SHELL )
1510 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1512 mesh->SetMeshElementOnShape( elem, ShapeID );
1514 myMesh->SetIsModified( true );
1516 SMESH_CATCH( SMESH::throwCorbaException );
1519 //=============================================================================
1523 //=============================================================================
1525 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1526 CORBA::Long NodeID2)
1527 throw (SALOME::SALOME_Exception)
1532 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1533 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1537 // Update Python script
1538 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1539 << NodeID1 << ", " << NodeID2 << " )";
1541 int ret = getEditor().InverseDiag ( n1, n2 );
1543 declareMeshModified( /*isReComputeSafe=*/false );
1546 SMESH_CATCH( SMESH::throwCorbaException );
1550 //=============================================================================
1554 //=============================================================================
1556 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1557 CORBA::Long NodeID2)
1558 throw (SALOME::SALOME_Exception)
1563 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1564 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1568 // Update Python script
1569 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1570 << NodeID1 << ", " << NodeID2 << " )";
1573 bool stat = getEditor().DeleteDiag ( n1, n2 );
1575 declareMeshModified( /*isReComputeSafe=*/!stat );
1579 SMESH_CATCH( SMESH::throwCorbaException );
1583 //=============================================================================
1587 //=============================================================================
1589 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1590 throw (SALOME::SALOME_Exception)
1595 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1597 CORBA::Long index = IDsOfElements[i];
1598 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1600 getEditor().Reorient( elem );
1602 // Update Python script
1603 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1605 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1608 SMESH_CATCH( SMESH::throwCorbaException );
1612 //=============================================================================
1616 //=============================================================================
1618 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1619 throw (SALOME::SALOME_Exception)
1624 TPythonDump aTPythonDump; // suppress dump in Reorient()
1626 prepareIdSource( theObject );
1628 SMESH::long_array_var anElementsId = theObject->GetIDs();
1629 CORBA::Boolean isDone = Reorient(anElementsId);
1631 // Update Python script
1632 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1634 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1637 SMESH_CATCH( SMESH::throwCorbaException );
1641 //=======================================================================
1642 //function : Reorient2D
1643 //purpose : Reorient faces contained in \a the2Dgroup.
1644 // the2Dgroup - the mesh or its part to reorient
1645 // theDirection - desired direction of normal of \a theFace
1646 // theFace - ID of face whose orientation is checked.
1647 // It can be < 1 then \a thePoint is used to find a face.
1648 // thePoint - is used to find a face if \a theFace < 1.
1649 // return number of reoriented elements.
1650 //=======================================================================
1652 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1653 const SMESH::DirStruct& theDirection,
1654 CORBA::Long theFace,
1655 const SMESH::PointStruct& thePoint)
1656 throw (SALOME::SALOME_Exception)
1659 initData(/*deleteSearchers=*/false);
1661 TIDSortedElemSet elements;
1662 IDSource_Error error;
1663 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1664 if ( error == IDSource_EMPTY )
1666 if ( error == IDSource_INVALID )
1667 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1670 const SMDS_MeshElement* face = 0;
1673 face = getMeshDS()->FindElement( theFace );
1675 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1676 if ( face->GetType() != SMDSAbs_Face )
1677 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1681 // create theElementSearcher if needed
1682 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1683 if ( !theElementSearcher )
1685 if ( elements.empty() ) // search in the whole mesh
1687 if ( myMesh->NbFaces() == 0 )
1688 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1690 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1694 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1695 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1697 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1701 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1702 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1705 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1706 if ( !elements.empty() && !elements.count( face ))
1707 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1710 const SMESH::PointStruct * P = &theDirection.PS;
1711 gp_Vec dirVec( P->x, P->y, P->z );
1712 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1713 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1715 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1718 declareMeshModified( /*isReComputeSafe=*/false );
1720 TPythonDump() << this << ".Reorient2D( "
1721 << the2Dgroup << ", "
1722 << theDirection << ", "
1724 << thePoint << " )";
1728 SMESH_CATCH( SMESH::throwCorbaException );
1732 //=======================================================================
1733 //function : Reorient2DBy3D
1734 //purpose : Reorient faces basing on orientation of adjacent volumes.
1735 //=======================================================================
1737 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1738 SMESH::SMESH_IDSource_ptr volumeGroup,
1739 CORBA::Boolean outsideNormal)
1740 throw (SALOME::SALOME_Exception)
1745 TIDSortedElemSet volumes;
1746 IDSource_Error volsError;
1747 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1750 for ( size_t i = 0; i < faceGroups.length(); ++i )
1752 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1754 TIDSortedElemSet faces;
1755 IDSource_Error error;
1756 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1757 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1758 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1759 if ( error == IDSource_OK && volsError != IDSource_OK )
1760 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1762 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1764 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1769 declareMeshModified( /*isReComputeSafe=*/false );
1771 TPythonDump() << this << ".Reorient2DBy3D( "
1772 << faceGroups << ", "
1773 << volumeGroup << ", "
1774 << outsideNormal << " )";
1778 SMESH_CATCH( SMESH::throwCorbaException );
1782 //=============================================================================
1784 * \brief Fuse neighbour triangles into quadrangles.
1786 //=============================================================================
1788 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1789 SMESH::NumericalFunctor_ptr Criterion,
1790 CORBA::Double MaxAngle)
1791 throw (SALOME::SALOME_Exception)
1796 SMESHDS_Mesh* aMesh = getMeshDS();
1797 TIDSortedElemSet faces,copyFaces;
1798 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1799 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1800 TIDSortedElemSet* workElements = & faces;
1802 if ( myIsPreviewMode ) {
1803 SMDSAbs_ElementType select = SMDSAbs_Face;
1804 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1805 workElements = & copyFaces;
1808 SMESH::NumericalFunctor_i* aNumericalFunctor =
1809 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1810 SMESH::Controls::NumericalFunctorPtr aCrit;
1811 if ( !aNumericalFunctor )
1812 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1814 aCrit = aNumericalFunctor->GetNumericalFunctor();
1816 if ( !myIsPreviewMode ) {
1817 // Update Python script
1818 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1819 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1822 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1824 declareMeshModified( /*isReComputeSafe=*/!stat );
1827 SMESH_CATCH( SMESH::throwCorbaException );
1831 //=============================================================================
1833 * \brief Fuse neighbour triangles into quadrangles.
1835 //=============================================================================
1837 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1838 SMESH::NumericalFunctor_ptr Criterion,
1839 CORBA::Double MaxAngle)
1840 throw (SALOME::SALOME_Exception)
1845 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1847 prepareIdSource( theObject );
1848 SMESH::long_array_var anElementsId = theObject->GetIDs();
1849 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1851 if ( !myIsPreviewMode ) {
1852 SMESH::NumericalFunctor_i* aNumericalFunctor =
1853 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1855 // Update Python script
1856 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1857 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1862 SMESH_CATCH( SMESH::throwCorbaException );
1866 //=============================================================================
1868 * \brief Split quadrangles into triangles.
1870 //=============================================================================
1872 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1873 SMESH::NumericalFunctor_ptr Criterion)
1874 throw (SALOME::SALOME_Exception)
1879 SMESHDS_Mesh* aMesh = getMeshDS();
1880 TIDSortedElemSet faces;
1881 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1883 SMESH::NumericalFunctor_i* aNumericalFunctor =
1884 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1885 SMESH::Controls::NumericalFunctorPtr aCrit;
1886 if ( !aNumericalFunctor )
1887 aCrit.reset( new SMESH::Controls::AspectRatio() );
1889 aCrit = aNumericalFunctor->GetNumericalFunctor();
1892 // Update Python script
1893 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1895 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1897 declareMeshModified( /*isReComputeSafe=*/false );
1900 SMESH_CATCH( SMESH::throwCorbaException );
1904 //=============================================================================
1906 * \brief Split quadrangles into triangles.
1908 //=============================================================================
1910 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1911 SMESH::NumericalFunctor_ptr Criterion)
1912 throw (SALOME::SALOME_Exception)
1917 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1919 prepareIdSource( theObject );
1920 SMESH::long_array_var anElementsId = theObject->GetIDs();
1921 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1923 SMESH::NumericalFunctor_i* aNumericalFunctor =
1924 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1926 // Update Python script
1927 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1929 declareMeshModified( /*isReComputeSafe=*/false );
1932 SMESH_CATCH( SMESH::throwCorbaException );
1936 //================================================================================
1938 * \brief Split each of quadrangles into 4 triangles.
1939 * \param [in] theObject - theQuads Container of quadrangles to split.
1941 //================================================================================
1943 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1944 throw (SALOME::SALOME_Exception)
1949 TIDSortedElemSet faces;
1950 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1952 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1954 getEditor().QuadTo4Tri( faces );
1955 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1957 SMESH_CATCH( SMESH::throwCorbaException );
1960 //=============================================================================
1962 * \brief Split quadrangles into triangles.
1964 //=============================================================================
1966 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1967 CORBA::Boolean Diag13)
1968 throw (SALOME::SALOME_Exception)
1973 SMESHDS_Mesh* aMesh = getMeshDS();
1974 TIDSortedElemSet faces;
1975 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1977 // Update Python script
1978 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1979 << IDsOfElements << ", " << Diag13 << " )";
1981 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1983 declareMeshModified( /*isReComputeSafe=*/ !stat );
1986 SMESH_CATCH( SMESH::throwCorbaException );
1990 //=============================================================================
1992 * \brief Split quadrangles into triangles.
1994 //=============================================================================
1996 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1997 CORBA::Boolean Diag13)
1998 throw (SALOME::SALOME_Exception)
2003 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2005 prepareIdSource( theObject );
2006 SMESH::long_array_var anElementsId = theObject->GetIDs();
2007 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2009 // Update Python script
2010 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2011 << theObject << ", " << Diag13 << " )";
2013 declareMeshModified( /*isReComputeSafe=*/!isDone );
2016 SMESH_CATCH( SMESH::throwCorbaException );
2021 //=============================================================================
2023 * Find better splitting of the given quadrangle.
2024 * \param IDOfQuad ID of the quadrangle to be split.
2025 * \param Criterion A criterion to choose a diagonal for splitting.
2026 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2027 * diagonal is better, 0 if error occurs.
2029 //=============================================================================
2031 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2032 SMESH::NumericalFunctor_ptr Criterion)
2033 throw (SALOME::SALOME_Exception)
2038 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2039 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2041 SMESH::NumericalFunctor_i* aNumericalFunctor =
2042 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2043 SMESH::Controls::NumericalFunctorPtr aCrit;
2044 if (aNumericalFunctor)
2045 aCrit = aNumericalFunctor->GetNumericalFunctor();
2047 aCrit.reset(new SMESH::Controls::AspectRatio());
2049 int id = getEditor().BestSplit(quad, aCrit);
2050 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2054 SMESH_CATCH( SMESH::throwCorbaException );
2058 //================================================================================
2060 * \brief Split volumic elements into tetrahedrons
2062 //================================================================================
2064 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2065 CORBA::Short methodFlags)
2066 throw (SALOME::SALOME_Exception)
2071 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2072 const int noneFacet = -1;
2073 prepareIdSource( elems );
2074 if ( SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME ))
2075 while ( volIt->more() )
2076 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2078 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2079 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2081 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2082 << elems << ", " << methodFlags << " )";
2084 SMESH_CATCH( SMESH::throwCorbaException );
2087 //================================================================================
2089 * \brief Split hexahedra into triangular prisms
2090 * \param elems - elements to split
2091 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2092 * to split into triangles
2093 * \param methodFlags - flags passing splitting method:
2094 * 1 - split the hexahedron into 2 prisms
2095 * 2 - split the hexahedron into 4 prisms
2097 //================================================================================
2099 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2100 const SMESH::PointStruct & startHexPoint,
2101 const SMESH::DirStruct& facetToSplitNormal,
2102 CORBA::Short methodFlags,
2103 CORBA::Boolean allDomains)
2104 throw (SALOME::SALOME_Exception)
2108 prepareIdSource( elems );
2110 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2113 gp_Dir( facetToSplitNormal.PS.x,
2114 facetToSplitNormal.PS.y,
2115 facetToSplitNormal.PS.z ));
2116 TIDSortedElemSet elemSet;
2117 prepareIdSource( elems );
2118 SMESH::long_array_var anElementsId = elems->GetIDs();
2119 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2120 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2122 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2123 while ( !elemSet.empty() )
2125 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2129 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2130 for ( ; ef != elemFacets.end(); ++ef )
2131 elemSet.erase( ef->first );
2134 if ( methodFlags == 2 )
2135 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2137 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2139 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2140 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2142 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2144 << startHexPoint << ", "
2145 << facetToSplitNormal<< ", "
2146 << methodFlags<< ", "
2147 << allDomains << " )";
2149 SMESH_CATCH( SMESH::throwCorbaException );
2152 //================================================================================
2154 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2155 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2156 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2157 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2158 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2159 * will be split in order to keep the mesh conformal.
2160 * \param elems - elements to split
2162 //================================================================================
2164 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2165 throw (SALOME::SALOME_Exception)
2170 TIDSortedElemSet elemSet;
2171 for ( size_t i = 0; i < theElems.length(); ++i )
2173 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2174 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2175 if ( mesh->GetId() != myMesh_i->GetId() )
2176 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2178 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2180 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2182 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2184 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2185 << theElems << " )";
2187 SMESH_CATCH( SMESH::throwCorbaException );
2190 //=======================================================================
2193 //=======================================================================
2196 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2197 const SMESH::long_array & IDsOfFixedNodes,
2198 CORBA::Long MaxNbOfIterations,
2199 CORBA::Double MaxAspectRatio,
2200 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2201 throw (SALOME::SALOME_Exception)
2203 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2204 MaxAspectRatio, Method, false );
2208 //=======================================================================
2209 //function : SmoothParametric
2211 //=======================================================================
2214 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2215 const SMESH::long_array & IDsOfFixedNodes,
2216 CORBA::Long MaxNbOfIterations,
2217 CORBA::Double MaxAspectRatio,
2218 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2219 throw (SALOME::SALOME_Exception)
2221 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2222 MaxAspectRatio, Method, true );
2226 //=======================================================================
2227 //function : SmoothObject
2229 //=======================================================================
2232 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2233 const SMESH::long_array & IDsOfFixedNodes,
2234 CORBA::Long MaxNbOfIterations,
2235 CORBA::Double MaxAspectRatio,
2236 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2237 throw (SALOME::SALOME_Exception)
2239 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2240 MaxAspectRatio, Method, false);
2244 //=======================================================================
2245 //function : SmoothParametricObject
2247 //=======================================================================
2250 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2251 const SMESH::long_array & IDsOfFixedNodes,
2252 CORBA::Long MaxNbOfIterations,
2253 CORBA::Double MaxAspectRatio,
2254 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2255 throw (SALOME::SALOME_Exception)
2257 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2258 MaxAspectRatio, Method, true);
2262 //=============================================================================
2266 //=============================================================================
2269 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2270 const SMESH::long_array & IDsOfFixedNodes,
2271 CORBA::Long MaxNbOfIterations,
2272 CORBA::Double MaxAspectRatio,
2273 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2275 throw (SALOME::SALOME_Exception)
2280 SMESHDS_Mesh* aMesh = getMeshDS();
2282 TIDSortedElemSet elements;
2283 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2285 set<const SMDS_MeshNode*> fixedNodes;
2286 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2287 CORBA::Long index = IDsOfFixedNodes[i];
2288 const SMDS_MeshNode * node = aMesh->FindNode(index);
2290 fixedNodes.insert( node );
2292 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2293 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2294 method = ::SMESH_MeshEditor::CENTROIDAL;
2296 getEditor().Smooth(elements, fixedNodes, method,
2297 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2299 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2301 // Update Python script
2302 TPythonDump() << "isDone = " << this << "."
2303 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2304 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2305 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2306 << "SMESH.SMESH_MeshEditor."
2307 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2308 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2312 SMESH_CATCH( SMESH::throwCorbaException );
2316 //=============================================================================
2320 //=============================================================================
2323 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2324 const SMESH::long_array & IDsOfFixedNodes,
2325 CORBA::Long MaxNbOfIterations,
2326 CORBA::Double MaxAspectRatio,
2327 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2329 throw (SALOME::SALOME_Exception)
2334 TPythonDump aTPythonDump; // suppress dump in smooth()
2336 prepareIdSource( theObject );
2337 SMESH::long_array_var anElementsId = theObject->GetIDs();
2338 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2339 MaxAspectRatio, Method, IsParametric);
2341 // Update Python script
2342 aTPythonDump << "isDone = " << this << "."
2343 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2344 << theObject << ", " << IDsOfFixedNodes << ", "
2345 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2346 << "SMESH.SMESH_MeshEditor."
2347 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2348 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2352 SMESH_CATCH( SMESH::throwCorbaException );
2356 //=============================================================================
2360 //=============================================================================
2362 void SMESH_MeshEditor_i::RenumberNodes()
2363 throw (SALOME::SALOME_Exception)
2366 // Update Python script
2367 TPythonDump() << this << ".RenumberNodes()";
2369 getMeshDS()->Renumber( true );
2371 SMESH_CATCH( SMESH::throwCorbaException );
2374 //=============================================================================
2378 //=============================================================================
2380 void SMESH_MeshEditor_i::RenumberElements()
2381 throw (SALOME::SALOME_Exception)
2384 // Update Python script
2385 TPythonDump() << this << ".RenumberElements()";
2387 getMeshDS()->Renumber( false );
2389 SMESH_CATCH( SMESH::throwCorbaException );
2392 //=======================================================================
2394 * \brief Return groups by their IDs
2396 //=======================================================================
2398 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2399 throw (SALOME::SALOME_Exception)
2404 myMesh_i->CreateGroupServants();
2405 return myMesh_i->GetGroups( *groupIDs );
2407 SMESH_CATCH( SMESH::throwCorbaException );
2411 //=======================================================================
2412 //function : RotationSweepObjects
2414 //=======================================================================
2416 SMESH::ListOfGroups*
2417 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2418 const SMESH::ListOfIDSources & theEdges,
2419 const SMESH::ListOfIDSources & theFaces,
2420 const SMESH::AxisStruct & theAxis,
2421 CORBA::Double theAngleInRadians,
2422 CORBA::Long theNbOfSteps,
2423 CORBA::Double theTolerance,
2424 const bool theMakeGroups)
2425 throw (SALOME::SALOME_Exception)
2430 TIDSortedElemSet elemsNodes[2];
2431 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2432 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2433 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2435 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2436 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2437 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2438 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2440 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2441 bool makeWalls=true;
2442 if ( myIsPreviewMode )
2444 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2445 TPreviewMesh * tmpMesh = getPreviewMesh();
2446 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2447 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2448 workElements = & copyElements[0];
2449 //makeWalls = false; -- faces are needed for preview
2452 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2454 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2455 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2457 ::SMESH_MeshEditor::PGroupIDs groupIds =
2458 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2459 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2461 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2463 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2465 if ( !myIsPreviewMode )
2467 dumpGroupsList( aPythonDump, aGroups );
2468 aPythonDump << this<< ".RotationSweepObjects( "
2473 << TVar( theAngleInRadians ) << ", "
2474 << TVar( theNbOfSteps ) << ", "
2475 << TVar( theTolerance ) << ", "
2476 << theMakeGroups << " )";
2480 getPreviewMesh()->Remove( SMDSAbs_Volume );
2483 return aGroups ? aGroups : new SMESH::ListOfGroups;
2485 SMESH_CATCH( SMESH::throwCorbaException );
2489 namespace MeshEditor_I
2492 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2494 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2496 bool myIsExtrusionByNormal;
2498 static int makeFlags( CORBA::Boolean MakeGroups,
2499 CORBA::Boolean ScaleVariation = false,
2500 CORBA::Boolean AngleVariation = false,
2501 CORBA::Boolean ByAverageNormal = false,
2502 CORBA::Boolean UseInputElemsOnly = false,
2503 CORBA::Long Flags = 0,
2504 CORBA::Boolean MakeBoundary = true )
2506 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2507 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2508 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2509 if ( ScaleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2510 if ( AngleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION;
2511 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2515 ExtrusionParams(const SMESH::DirStruct & theDir,
2516 CORBA::Long theNbOfSteps,
2517 const SMESH::double_array & theScaleFactors,
2518 CORBA::Boolean theScaleVariation,
2519 const SMESH::double_array & theAngles,
2520 CORBA::Boolean theAngleVariation,
2521 const SMESH::double_array & theBasePoint,
2522 CORBA::Boolean theMakeGroups):
2523 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2527 toList( theScaleFactors ),
2528 toList( theAngles ),
2529 TBasePoint( theBasePoint ),
2530 makeFlags( theMakeGroups, theScaleVariation, theAngleVariation )),
2531 myIsExtrusionByNormal( false )
2535 ExtrusionParams(const SMESH::DirStruct & theDir,
2536 CORBA::Long theNbOfSteps,
2537 CORBA::Boolean theMakeGroups,
2538 CORBA::Long theExtrFlags,
2539 CORBA::Double theSewTolerance):
2540 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2544 std::list<double>(),
2545 std::list<double>(),
2547 makeFlags( theMakeGroups, false, false, false, false,
2548 theExtrFlags, false ),
2550 myIsExtrusionByNormal( false )
2553 // params for extrusion by normal
2554 ExtrusionParams(CORBA::Double theStepSize,
2555 CORBA::Long theNbOfSteps,
2556 CORBA::Short theDim,
2557 CORBA::Boolean theByAverageNormal,
2558 CORBA::Boolean theUseInputElemsOnly,
2559 CORBA::Boolean theMakeGroups ):
2560 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2562 makeFlags( theMakeGroups, false, false,
2563 theByAverageNormal, theUseInputElemsOnly ),
2565 myIsExtrusionByNormal( true )
2571 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2574 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2576 std::list<double> scales;
2577 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2578 scales.push_back( theScaleFactors[i] );
2584 // structure used to convert SMESH::double_array to gp_XYZ*
2588 TBasePoint( const SMESH::double_array & theBasePoint )
2591 if ( theBasePoint.length() == 3 )
2593 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2597 operator const gp_XYZ*() const { return pp; }
2602 //=======================================================================
2604 * \brief Generate dim+1 elements by extrusion of elements along vector
2605 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2606 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2607 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2608 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2609 * \param [in] nbOfSteps - number of elements to generate from one element
2610 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2611 * corresponding to groups the input elements included in.
2612 * \return ListOfGroups - new groups created if \a toMakeGroups is true
2614 //=======================================================================
2616 SMESH::ListOfGroups*
2617 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2618 const SMESH::ListOfIDSources & theEdges,
2619 const SMESH::ListOfIDSources & theFaces,
2620 const SMESH::DirStruct & theStepVector,
2621 CORBA::Long theNbOfSteps,
2622 CORBA::Boolean theToMakeGroups,
2623 const SMESH::double_array & theScaleFactors,
2624 CORBA::Boolean theScalesVariation,
2625 const SMESH::double_array & theBasePoint,
2626 const SMESH::double_array & theAngles,
2627 CORBA::Boolean theAnglesVariation)
2628 throw (SALOME::SALOME_Exception)
2633 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, theScalesVariation,
2634 theAngles, theAnglesVariation, theBasePoint, theToMakeGroups );
2636 TIDSortedElemSet elemsNodes[2];
2637 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2638 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2639 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2641 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2642 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2643 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2644 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2646 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2647 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2648 if ( myIsPreviewMode )
2650 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2651 // previewType = SMDSAbs_Edge;
2653 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2654 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2655 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2656 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2657 workElements = & copyElements[0];
2659 params.SetNoGroups();
2661 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2663 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2664 ::SMESH_MeshEditor::PGroupIDs groupIds =
2665 getEditor().ExtrusionSweep( workElements, params, aHistory );
2667 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2669 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2671 if ( !myIsPreviewMode )
2673 dumpGroupsList( aPythonDump, aGroups );
2674 aPythonDump << this<< ".ExtrusionSweepObjects( "
2678 << theStepVector << ", "
2679 << TVar( theNbOfSteps ) << ", "
2680 << theToMakeGroups << ", "
2681 << TVar( theScaleFactors ) << ", "
2682 << theScalesVariation << ", "
2683 << TVar( theBasePoint ) << ", "
2684 << TVar( theAngles ) << ", "
2685 << theAnglesVariation << " )";
2689 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2692 return aGroups ? aGroups : new SMESH::ListOfGroups;
2694 SMESH_CATCH( SMESH::throwCorbaException );
2698 //=======================================================================
2699 //function : ExtrusionByNormal
2701 //=======================================================================
2703 SMESH::ListOfGroups*
2704 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2705 CORBA::Double stepSize,
2706 CORBA::Long nbOfSteps,
2707 CORBA::Boolean byAverageNormal,
2708 CORBA::Boolean useInputElemsOnly,
2709 CORBA::Boolean makeGroups,
2711 throw (SALOME::SALOME_Exception)
2716 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2718 ExtrusionParams params( stepSize, nbOfSteps, dim,
2719 byAverageNormal, useInputElemsOnly, makeGroups );
2721 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2722 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2724 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2725 if (( elemTypes->length() == 1 ) &&
2726 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2727 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2730 TIDSortedElemSet elemsNodes[2];
2731 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2732 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2734 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2735 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2736 if ( myIsPreviewMode )
2738 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2739 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2740 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2741 workElements = & copyElements[0];
2743 params.SetNoGroups();
2746 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2747 ::SMESH_MeshEditor::PGroupIDs groupIds =
2748 getEditor().ExtrusionSweep( workElements, params, aHistory );
2750 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2752 if (!myIsPreviewMode) {
2753 dumpGroupsList(aPythonDump, aGroups);
2754 aPythonDump << this << ".ExtrusionByNormal( " << objects
2755 << ", " << TVar( stepSize )
2756 << ", " << TVar( nbOfSteps )
2757 << ", " << byAverageNormal
2758 << ", " << useInputElemsOnly
2759 << ", " << makeGroups
2765 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2768 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2770 return aGroups ? aGroups : new SMESH::ListOfGroups;
2772 SMESH_CATCH( SMESH::throwCorbaException );
2776 //=======================================================================
2777 //function : AdvancedExtrusion
2779 //=======================================================================
2781 SMESH::ListOfGroups*
2782 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2783 const SMESH::DirStruct & theStepVector,
2784 CORBA::Long theNbOfSteps,
2785 CORBA::Long theExtrFlags,
2786 CORBA::Double theSewTolerance,
2787 CORBA::Boolean theMakeGroups)
2788 throw (SALOME::SALOME_Exception)
2793 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2795 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2796 theExtrFlags, theSewTolerance );
2798 TIDSortedElemSet elemsNodes[2];
2799 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2801 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2802 ::SMESH_MeshEditor::PGroupIDs groupIds =
2803 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2805 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2807 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2809 if ( !myIsPreviewMode ) {
2810 dumpGroupsList(aPythonDump, aGroups);
2811 aPythonDump << this << ".AdvancedExtrusion( "
2812 << theIDsOfElements << ", "
2813 << theStepVector << ", "
2814 << theNbOfSteps << ", "
2815 << theExtrFlags << ", "
2816 << theSewTolerance << ", "
2817 << theMakeGroups << " )";
2821 getPreviewMesh()->Remove( SMDSAbs_Volume );
2824 return aGroups ? aGroups : new SMESH::ListOfGroups;
2826 SMESH_CATCH( SMESH::throwCorbaException );
2830 //================================================================================
2832 * \brief Convert extrusion error to IDL enum
2834 //================================================================================
2838 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2840 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2844 RETCASE( EXTR_NO_ELEMENTS );
2845 RETCASE( EXTR_PATH_NOT_EDGE );
2846 RETCASE( EXTR_BAD_PATH_SHAPE );
2847 RETCASE( EXTR_BAD_STARTING_NODE );
2848 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2849 RETCASE( EXTR_CANT_GET_TANGENT );
2851 return SMESH::SMESH_MeshEditor::EXTR_OK;
2855 //=======================================================================
2856 //function : extrusionAlongPath
2858 //=======================================================================
2859 SMESH::ListOfGroups*
2860 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2861 const SMESH::ListOfIDSources & theEdges,
2862 const SMESH::ListOfIDSources & theFaces,
2863 SMESH::SMESH_IDSource_ptr thePathObject,
2864 GEOM::GEOM_Object_ptr thePathShape,
2865 CORBA::Long theNodeStart,
2866 CORBA::Boolean theHasAngles,
2867 const SMESH::double_array & theAngles,
2868 CORBA::Boolean theAnglesVariation,
2869 CORBA::Boolean theHasRefPoint,
2870 const SMESH::PointStruct & theRefPoint,
2872 const SMESH::double_array & theScaleFactors,
2873 CORBA::Boolean theScalesVariation,
2874 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2875 throw (SALOME::SALOME_Exception)
2880 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2882 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2883 if ( thePathObject->_is_nil() )
2884 return aGroups._retn();
2887 SMDS_ElemIteratorPtr pathEdgesIterator;
2889 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathObject );
2890 if ( !CORBA::is_nil( thePathShape ) && aMeshImp )
2892 // get a sub-mesh of thePathShape
2893 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2894 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2896 return aGroups._retn();
2898 if ( !aSubMesh->GetSubMeshDS() )
2900 SMESHDS_Mesh * meshDS = aMeshImp->GetImpl().GetMeshDS();
2901 meshDS->AddCompoundSubmesh( aShape, TopAbs_EDGE );
2902 if ( !aSubMesh->GetSubMeshDS() )
2903 return aGroups._retn();
2905 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2906 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2907 if ( !pathEdgesIterator->more() ||
2908 pathEdgesIterator->next()->GetType() != SMDSAbs_Edge )
2909 return aGroups._retn();
2911 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2915 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2916 prepareIdSource( thePathObject );
2917 pathEdgesIterator = SMESH_Mesh_i::GetElements( thePathObject, SMESH::EDGE );
2918 if ( !pathEdgesIterator || !pathEdgesIterator->more() )
2919 return aGroups._retn();
2924 SMESH::SMESH_Mesh_var pathMesh = thePathObject->GetMesh();
2925 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( pathMesh );
2929 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2930 const SMDS_MeshNode* nodeStart = aMeshImp->GetImpl().GetMeshDS()->FindNode( theNodeStart );
2932 return aGroups._retn();
2935 TIDSortedElemSet elemsNodes[2];
2936 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2937 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2938 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2940 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2941 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2942 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2943 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2945 list<double> angles = ExtrusionParams::toList( theAngles );
2946 list<double> scales = ExtrusionParams::toList( theScaleFactors );
2948 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2949 const gp_Pnt *refPntPtr = theHasRefPoint ? &refPnt : 0;
2951 int nbOldGroups = myMesh->NbGroup();
2953 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2954 if ( myIsPreviewMode )
2956 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2957 TPreviewMesh * tmpMesh = getPreviewMesh();
2958 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2959 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2960 workElements = & copyElements[0];
2961 theMakeGroups = false;
2964 ::SMESH_MeshEditor::Extrusion_Error error =
2965 getEditor().ExtrusionAlongTrack( workElements,
2966 &(aMeshImp->GetImpl()), pathEdgesIterator, nodeStart,
2967 angles, theAnglesVariation,
2968 scales, theScalesVariation,
2969 refPntPtr, theMakeGroups );
2971 declareMeshModified( /*isReComputeSafe=*/true );
2972 theError = convExtrError( error );
2974 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2975 if ( theMakeGroups ) {
2976 list<int> groupIDs = myMesh->GetGroupIds();
2977 list<int>::iterator newBegin = groupIDs.begin();
2978 std::advance( newBegin, nbOldGroups ); // skip old groups
2979 groupIDs.erase( groupIDs.begin(), newBegin );
2980 aGroups = getGroups( & groupIDs );
2981 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2984 if ( !myIsPreviewMode ) {
2985 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2986 else aPythonDump << "(_noGroups, error) = ";
2987 aPythonDump << this << ".ExtrusionAlongPathObjects( "
2991 << thePathObject << ", "
2992 << thePathShape << ", "
2993 << theNodeStart << ", "
2994 << theHasAngles << ", "
2995 << TVar( theAngles ) << ", "
2996 << theAnglesVariation << ", "
2997 << theHasRefPoint << ", "
2998 << "SMESH.PointStruct( "
2999 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3000 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3001 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
3002 << theMakeGroups << ", "
3003 << TVar( theScaleFactors ) << ", "
3004 << theScalesVariation << " )";
3008 getPreviewMesh()->Remove( SMDSAbs_Volume );
3011 return aGroups._retn();
3013 SMESH_CATCH( SMESH::throwCorbaException );
3017 //================================================================================
3019 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
3020 * of given angles along path steps
3021 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
3022 * which proceeds the extrusion
3023 * \param PathShape is shape(edge); as the mesh can be complex, the edge
3024 * is used to define the sub-mesh for the path
3026 //================================================================================
3028 SMESH::double_array*
3029 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
3030 GEOM::GEOM_Object_ptr thePathShape,
3031 const SMESH::double_array & theAngles)
3033 SMESH::double_array_var aResult = new SMESH::double_array();
3034 int nbAngles = theAngles.length();
3035 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3037 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3038 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3039 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3040 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3041 return aResult._retn();
3042 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3043 if ( nbSteps == nbAngles )
3045 aResult.inout() = theAngles;
3049 aResult->length( nbSteps );
3050 double rAn2St = double( nbAngles ) / double( nbSteps );
3051 double angPrev = 0, angle;
3052 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3054 double angCur = rAn2St * ( iSt+1 );
3055 double angCurFloor = floor( angCur );
3056 double angPrevFloor = floor( angPrev );
3057 if ( angPrevFloor == angCurFloor )
3058 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3061 int iP = int( angPrevFloor );
3062 double angPrevCeil = ceil(angPrev);
3063 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3065 int iC = int( angCurFloor );
3066 if ( iC < nbAngles )
3067 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3069 iP = int( angPrevCeil );
3071 angle += theAngles[ iC ];
3073 aResult[ iSt ] = angle;
3078 // Update Python script
3079 TPythonDump() << "rotAngles = " << theAngles;
3080 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3081 << thePathMesh << ", "
3082 << thePathShape << ", "
3085 return aResult._retn();
3088 //=======================================================================
3091 //=======================================================================
3093 SMESH::ListOfGroups*
3094 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3095 const SMESH::AxisStruct & theAxis,
3096 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3097 CORBA::Boolean theCopy,
3099 ::SMESH_Mesh* theTargetMesh)
3100 throw (SALOME::SALOME_Exception)
3105 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3106 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3108 if ( theTargetMesh )
3112 switch ( theMirrorType ) {
3113 case SMESH::SMESH_MeshEditor::POINT:
3114 aTrsf.SetMirror( P );
3116 case SMESH::SMESH_MeshEditor::AXIS:
3117 aTrsf.SetMirror( gp_Ax1( P, V ));
3120 aTrsf.SetMirror( gp_Ax2( P, V ));
3123 TIDSortedElemSet copyElements;
3124 TIDSortedElemSet* workElements = & theElements;
3126 if ( myIsPreviewMode )
3128 TPreviewMesh * tmpMesh = getPreviewMesh();
3129 tmpMesh->Copy( theElements, copyElements);
3130 if ( !theCopy && !theTargetMesh )
3132 TIDSortedElemSet elemsAround, elemsAroundCopy;
3133 getElementsAround( theElements, getMeshDS(), elemsAround );
3134 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3136 workElements = & copyElements;
3137 theMakeGroups = false;
3140 ::SMESH_MeshEditor::PGroupIDs groupIds =
3141 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3143 if ( !myIsPreviewMode )
3145 if ( theTargetMesh )
3146 theTargetMesh->GetMeshDS()->Modified();
3148 declareMeshModified( /*isReComputeSafe=*/false );
3151 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3153 SMESH_CATCH( SMESH::throwCorbaException );
3157 //=======================================================================
3160 //=======================================================================
3162 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3163 const SMESH::AxisStruct & theAxis,
3164 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3165 CORBA::Boolean theCopy)
3166 throw (SALOME::SALOME_Exception)
3168 if ( !myIsPreviewMode ) {
3169 TPythonDump() << this << ".Mirror( "
3170 << theIDsOfElements << ", "
3172 << mirrorTypeName(theMirrorType) << ", "
3175 if ( theIDsOfElements.length() > 0 )
3177 TIDSortedElemSet elements;
3178 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3179 mirror(elements, theAxis, theMirrorType, theCopy, false);
3184 //=======================================================================
3185 //function : MirrorObject
3187 //=======================================================================
3189 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3190 const SMESH::AxisStruct & theAxis,
3191 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3192 CORBA::Boolean theCopy)
3193 throw (SALOME::SALOME_Exception)
3195 if ( !myIsPreviewMode ) {
3196 TPythonDump() << this << ".MirrorObject( "
3197 << theObject << ", "
3199 << mirrorTypeName(theMirrorType) << ", "
3202 TIDSortedElemSet elements;
3204 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3206 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3207 mirror(elements, theAxis, theMirrorType, theCopy, false);
3210 //=======================================================================
3211 //function : MirrorMakeGroups
3213 //=======================================================================
3215 SMESH::ListOfGroups*
3216 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3217 const SMESH::AxisStruct& theMirror,
3218 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3219 throw (SALOME::SALOME_Exception)
3221 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3223 SMESH::ListOfGroups * aGroups = 0;
3224 if ( theIDsOfElements.length() > 0 )
3226 TIDSortedElemSet elements;
3227 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3228 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3230 if (!myIsPreviewMode) {
3231 dumpGroupsList(aPythonDump, aGroups);
3232 aPythonDump << this << ".MirrorMakeGroups( "
3233 << theIDsOfElements << ", "
3234 << theMirror << ", "
3235 << mirrorTypeName(theMirrorType) << " )";
3240 //=======================================================================
3241 //function : MirrorObjectMakeGroups
3243 //=======================================================================
3245 SMESH::ListOfGroups*
3246 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3247 const SMESH::AxisStruct& theMirror,
3248 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3249 throw (SALOME::SALOME_Exception)
3251 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3253 SMESH::ListOfGroups * aGroups = 0;
3254 TIDSortedElemSet elements;
3255 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3256 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3258 if (!myIsPreviewMode)
3260 dumpGroupsList(aPythonDump,aGroups);
3261 aPythonDump << this << ".MirrorObjectMakeGroups( "
3262 << theObject << ", "
3263 << theMirror << ", "
3264 << mirrorTypeName(theMirrorType) << " )";
3269 //=======================================================================
3270 //function : MirrorMakeMesh
3272 //=======================================================================
3274 SMESH::SMESH_Mesh_ptr
3275 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3276 const SMESH::AxisStruct& theMirror,
3277 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3278 CORBA::Boolean theCopyGroups,
3279 const char* theMeshName)
3280 throw (SALOME::SALOME_Exception)
3282 SMESH_Mesh_i* mesh_i;
3283 SMESH::SMESH_Mesh_var mesh;
3284 { // open new scope to dump "MakeMesh" command
3285 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3287 TPythonDump pydump; // to prevent dump at mesh creation
3289 mesh = makeMesh( theMeshName );
3290 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3291 if (mesh_i && theIDsOfElements.length() > 0 )
3293 TIDSortedElemSet elements;
3294 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3295 mirror(elements, theMirror, theMirrorType,
3296 false, theCopyGroups, & mesh_i->GetImpl());
3297 mesh_i->CreateGroupServants();
3300 if (!myIsPreviewMode) {
3301 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3302 << theIDsOfElements << ", "
3303 << theMirror << ", "
3304 << mirrorTypeName(theMirrorType) << ", "
3305 << theCopyGroups << ", '"
3306 << theMeshName << "' )";
3311 if (!myIsPreviewMode && mesh_i)
3312 mesh_i->GetGroups();
3314 return mesh._retn();
3317 //=======================================================================
3318 //function : MirrorObjectMakeMesh
3320 //=======================================================================
3322 SMESH::SMESH_Mesh_ptr
3323 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3324 const SMESH::AxisStruct& theMirror,
3325 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3326 CORBA::Boolean theCopyGroups,
3327 const char* theMeshName)
3328 throw (SALOME::SALOME_Exception)
3330 SMESH_Mesh_i* mesh_i;
3331 SMESH::SMESH_Mesh_var mesh;
3332 { // open new scope to dump "MakeMesh" command
3333 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3335 TPythonDump pydump; // to prevent dump at mesh creation
3337 mesh = makeMesh( theMeshName );
3338 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3339 TIDSortedElemSet elements;
3341 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3343 mirror(elements, theMirror, theMirrorType,
3344 false, theCopyGroups, & mesh_i->GetImpl());
3345 mesh_i->CreateGroupServants();
3347 if (!myIsPreviewMode) {
3348 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3349 << theObject << ", "
3350 << theMirror << ", "
3351 << mirrorTypeName(theMirrorType) << ", "
3352 << theCopyGroups << ", '"
3353 << theMeshName << "' )";
3358 if (!myIsPreviewMode && mesh_i)
3359 mesh_i->GetGroups();
3361 return mesh._retn();
3364 //=======================================================================
3365 //function : translate
3367 //=======================================================================
3369 SMESH::ListOfGroups*
3370 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3371 const SMESH::DirStruct & theVector,
3372 CORBA::Boolean theCopy,
3374 ::SMESH_Mesh* theTargetMesh)
3375 throw (SALOME::SALOME_Exception)
3380 if ( theTargetMesh )
3384 const SMESH::PointStruct * P = &theVector.PS;
3385 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3387 TIDSortedElemSet copyElements;
3388 TIDSortedElemSet* workElements = &theElements;
3390 if ( myIsPreviewMode )
3392 TPreviewMesh * tmpMesh = getPreviewMesh();
3393 tmpMesh->Copy( theElements, copyElements);
3394 if ( !theCopy && !theTargetMesh )
3396 TIDSortedElemSet elemsAround, elemsAroundCopy;
3397 getElementsAround( theElements, getMeshDS(), elemsAround );
3398 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3400 workElements = & copyElements;
3401 theMakeGroups = false;
3404 ::SMESH_MeshEditor::PGroupIDs groupIds =
3405 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3407 if ( !myIsPreviewMode )
3409 if ( theTargetMesh )
3410 theTargetMesh->GetMeshDS()->Modified();
3412 declareMeshModified( /*isReComputeSafe=*/false );
3415 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3417 SMESH_CATCH( SMESH::throwCorbaException );
3421 //=======================================================================
3422 //function : Translate
3424 //=======================================================================
3426 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3427 const SMESH::DirStruct & theVector,
3428 CORBA::Boolean theCopy)
3429 throw (SALOME::SALOME_Exception)
3431 if (!myIsPreviewMode) {
3432 TPythonDump() << this << ".Translate( "
3433 << theIDsOfElements << ", "
3434 << theVector << ", "
3437 if (theIDsOfElements.length()) {
3438 TIDSortedElemSet elements;
3439 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3440 translate(elements, theVector, theCopy, false);
3444 //=======================================================================
3445 //function : TranslateObject
3447 //=======================================================================
3449 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3450 const SMESH::DirStruct & theVector,
3451 CORBA::Boolean theCopy)
3452 throw (SALOME::SALOME_Exception)
3454 if (!myIsPreviewMode) {
3455 TPythonDump() << this << ".TranslateObject( "
3456 << theObject << ", "
3457 << theVector << ", "
3460 TIDSortedElemSet elements;
3462 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3464 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3465 translate(elements, theVector, theCopy, false);
3468 //=======================================================================
3469 //function : TranslateMakeGroups
3471 //=======================================================================
3473 SMESH::ListOfGroups*
3474 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3475 const SMESH::DirStruct& theVector)
3476 throw (SALOME::SALOME_Exception)
3478 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3480 SMESH::ListOfGroups * aGroups = 0;
3481 if (theIDsOfElements.length()) {
3482 TIDSortedElemSet elements;
3483 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3484 aGroups = translate(elements,theVector,true,true);
3486 if (!myIsPreviewMode) {
3487 dumpGroupsList(aPythonDump, aGroups);
3488 aPythonDump << this << ".TranslateMakeGroups( "
3489 << theIDsOfElements << ", "
3490 << theVector << " )";
3495 //=======================================================================
3496 //function : TranslateObjectMakeGroups
3498 //=======================================================================
3500 SMESH::ListOfGroups*
3501 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3502 const SMESH::DirStruct& theVector)
3503 throw (SALOME::SALOME_Exception)
3505 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3507 SMESH::ListOfGroups * aGroups = 0;
3508 TIDSortedElemSet elements;
3509 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3510 aGroups = translate(elements, theVector, true, true);
3512 if (!myIsPreviewMode) {
3513 dumpGroupsList(aPythonDump, aGroups);
3514 aPythonDump << this << ".TranslateObjectMakeGroups( "
3515 << theObject << ", "
3516 << theVector << " )";
3521 //=======================================================================
3522 //function : TranslateMakeMesh
3524 //=======================================================================
3526 SMESH::SMESH_Mesh_ptr
3527 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3528 const SMESH::DirStruct& theVector,
3529 CORBA::Boolean theCopyGroups,
3530 const char* theMeshName)
3531 throw (SALOME::SALOME_Exception)
3533 SMESH_Mesh_i* mesh_i;
3534 SMESH::SMESH_Mesh_var mesh;
3536 { // open new scope to dump "MakeMesh" command
3537 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3539 TPythonDump pydump; // to prevent dump at mesh creation
3541 mesh = makeMesh( theMeshName );
3542 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3544 if ( mesh_i && theIDsOfElements.length() )
3546 TIDSortedElemSet elements;
3547 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3548 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3549 mesh_i->CreateGroupServants();
3552 if ( !myIsPreviewMode ) {
3553 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3554 << theIDsOfElements << ", "
3555 << theVector << ", "
3556 << theCopyGroups << ", '"
3557 << theMeshName << "' )";
3562 if (!myIsPreviewMode && mesh_i)
3563 mesh_i->GetGroups();
3565 return mesh._retn();
3568 //=======================================================================
3569 //function : TranslateObjectMakeMesh
3571 //=======================================================================
3573 SMESH::SMESH_Mesh_ptr
3574 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3575 const SMESH::DirStruct& theVector,
3576 CORBA::Boolean theCopyGroups,
3577 const char* theMeshName)
3578 throw (SALOME::SALOME_Exception)
3581 SMESH_Mesh_i* mesh_i;
3582 SMESH::SMESH_Mesh_var mesh;
3583 { // open new scope to dump "MakeMesh" command
3584 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3586 TPythonDump pydump; // to prevent dump at mesh creation
3587 mesh = makeMesh( theMeshName );
3588 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3590 TIDSortedElemSet elements;
3592 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3594 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3595 mesh_i->CreateGroupServants();
3597 if ( !myIsPreviewMode ) {
3598 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3599 << theObject << ", "
3600 << theVector << ", "
3601 << theCopyGroups << ", '"
3602 << theMeshName << "' )";
3607 if (!myIsPreviewMode && mesh_i)
3608 mesh_i->GetGroups();
3610 return mesh._retn();
3612 SMESH_CATCH( SMESH::throwCorbaException );
3616 //=======================================================================
3619 //=======================================================================
3621 SMESH::ListOfGroups*
3622 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3623 const SMESH::AxisStruct & theAxis,
3624 CORBA::Double theAngle,
3625 CORBA::Boolean theCopy,
3627 ::SMESH_Mesh* theTargetMesh)
3628 throw (SALOME::SALOME_Exception)
3633 if ( theTargetMesh )
3636 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3637 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3640 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3642 TIDSortedElemSet copyElements;
3643 TIDSortedElemSet* workElements = &theElements;
3644 if ( myIsPreviewMode ) {
3645 TPreviewMesh * tmpMesh = getPreviewMesh();
3646 tmpMesh->Copy( theElements, copyElements );
3647 if ( !theCopy && !theTargetMesh )
3649 TIDSortedElemSet elemsAround, elemsAroundCopy;
3650 getElementsAround( theElements, getMeshDS(), elemsAround );
3651 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3653 workElements = ©Elements;
3654 theMakeGroups = false;
3657 ::SMESH_MeshEditor::PGroupIDs groupIds =
3658 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3660 if ( !myIsPreviewMode)
3662 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3663 else declareMeshModified( /*isReComputeSafe=*/false );
3666 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3668 SMESH_CATCH( SMESH::throwCorbaException );
3672 //=======================================================================
3675 //=======================================================================
3677 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3678 const SMESH::AxisStruct & theAxis,
3679 CORBA::Double theAngle,
3680 CORBA::Boolean theCopy)
3681 throw (SALOME::SALOME_Exception)
3683 if (!myIsPreviewMode) {
3684 TPythonDump() << this << ".Rotate( "
3685 << theIDsOfElements << ", "
3687 << TVar( theAngle ) << ", "
3690 if (theIDsOfElements.length() > 0)
3692 TIDSortedElemSet elements;
3693 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3694 rotate(elements,theAxis,theAngle,theCopy,false);
3698 //=======================================================================
3699 //function : RotateObject
3701 //=======================================================================
3703 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3704 const SMESH::AxisStruct & theAxis,
3705 CORBA::Double theAngle,
3706 CORBA::Boolean theCopy)
3707 throw (SALOME::SALOME_Exception)
3709 if ( !myIsPreviewMode ) {
3710 TPythonDump() << this << ".RotateObject( "
3711 << theObject << ", "
3713 << TVar( theAngle ) << ", "
3716 TIDSortedElemSet elements;
3717 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3718 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3719 rotate(elements,theAxis,theAngle,theCopy,false);
3722 //=======================================================================
3723 //function : RotateMakeGroups
3725 //=======================================================================
3727 SMESH::ListOfGroups*
3728 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3729 const SMESH::AxisStruct& theAxis,
3730 CORBA::Double theAngle)
3731 throw (SALOME::SALOME_Exception)
3733 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3735 SMESH::ListOfGroups * aGroups = 0;
3736 if (theIDsOfElements.length() > 0)
3738 TIDSortedElemSet elements;
3739 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3740 aGroups = rotate(elements,theAxis,theAngle,true,true);
3742 if (!myIsPreviewMode) {
3743 dumpGroupsList(aPythonDump, aGroups);
3744 aPythonDump << this << ".RotateMakeGroups( "
3745 << theIDsOfElements << ", "
3747 << TVar( theAngle ) << " )";
3752 //=======================================================================
3753 //function : RotateObjectMakeGroups
3755 //=======================================================================
3757 SMESH::ListOfGroups*
3758 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3759 const SMESH::AxisStruct& theAxis,
3760 CORBA::Double theAngle)
3761 throw (SALOME::SALOME_Exception)
3763 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3765 SMESH::ListOfGroups * aGroups = 0;
3766 TIDSortedElemSet elements;
3767 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3768 aGroups = rotate(elements, theAxis, theAngle, true, true);
3770 if (!myIsPreviewMode) {
3771 dumpGroupsList(aPythonDump, aGroups);
3772 aPythonDump << this << ".RotateObjectMakeGroups( "
3773 << theObject << ", "
3775 << TVar( theAngle ) << " )";
3780 //=======================================================================
3781 //function : RotateMakeMesh
3783 //=======================================================================
3785 SMESH::SMESH_Mesh_ptr
3786 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3787 const SMESH::AxisStruct& theAxis,
3788 CORBA::Double theAngleInRadians,
3789 CORBA::Boolean theCopyGroups,
3790 const char* theMeshName)
3791 throw (SALOME::SALOME_Exception)
3794 SMESH::SMESH_Mesh_var mesh;
3795 SMESH_Mesh_i* mesh_i;
3797 { // open new scope to dump "MakeMesh" command
3798 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3800 TPythonDump pydump; // to prevent dump at mesh creation
3802 mesh = makeMesh( theMeshName );
3803 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3805 if ( mesh_i && theIDsOfElements.length() > 0 )
3807 TIDSortedElemSet elements;
3808 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3809 rotate(elements, theAxis, theAngleInRadians,
3810 false, theCopyGroups, & mesh_i->GetImpl());
3811 mesh_i->CreateGroupServants();
3813 if ( !myIsPreviewMode ) {
3814 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3815 << theIDsOfElements << ", "
3817 << TVar( theAngleInRadians ) << ", "
3818 << theCopyGroups << ", '"
3819 << theMeshName << "' )";
3824 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3825 mesh_i->GetGroups();
3827 return mesh._retn();
3829 SMESH_CATCH( SMESH::throwCorbaException );
3833 //=======================================================================
3834 //function : RotateObjectMakeMesh
3836 //=======================================================================
3838 SMESH::SMESH_Mesh_ptr
3839 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3840 const SMESH::AxisStruct& theAxis,
3841 CORBA::Double theAngleInRadians,
3842 CORBA::Boolean theCopyGroups,
3843 const char* theMeshName)
3844 throw (SALOME::SALOME_Exception)
3847 SMESH::SMESH_Mesh_var mesh;
3848 SMESH_Mesh_i* mesh_i;
3850 {// open new scope to dump "MakeMesh" command
3851 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3853 TPythonDump pydump; // to prevent dump at mesh creation
3854 mesh = makeMesh( theMeshName );
3855 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3857 TIDSortedElemSet elements;
3859 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3861 rotate(elements, theAxis, theAngleInRadians,
3862 false, theCopyGroups, & mesh_i->GetImpl());
3863 mesh_i->CreateGroupServants();
3865 if ( !myIsPreviewMode ) {
3866 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3867 << theObject << ", "
3869 << TVar( theAngleInRadians ) << ", "
3870 << theCopyGroups << ", '"
3871 << theMeshName << "' )";
3876 if (!myIsPreviewMode && mesh_i)
3877 mesh_i->GetGroups();
3879 return mesh._retn();
3881 SMESH_CATCH( SMESH::throwCorbaException );
3885 //=======================================================================
3888 //=======================================================================
3890 SMESH::ListOfGroups*
3891 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3892 const SMESH::PointStruct& thePoint,
3893 const SMESH::double_array& theScaleFact,
3894 CORBA::Boolean theCopy,
3896 ::SMESH_Mesh* theTargetMesh)
3897 throw (SALOME::SALOME_Exception)
3901 if ( theScaleFact.length() < 1 )
3902 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3903 if ( theScaleFact.length() == 2 )
3904 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3906 if ( theTargetMesh )
3909 TIDSortedElemSet elements;
3910 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3911 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3916 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3917 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3921 // fight against orthogonalization
3922 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3923 // 0, S[1], 0, thePoint.y * (1-S[1]),
3924 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3925 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3926 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3927 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3928 loc.SetCoord( thePoint.x * (1-S[0]),
3929 thePoint.y * (1-S[1]),
3930 thePoint.z * (1-S[2]));
3931 M.SetDiagonal( S[0], S[1], S[2] );
3933 TIDSortedElemSet copyElements;
3934 TIDSortedElemSet* workElements = &elements;
3935 if ( myIsPreviewMode )
3937 TPreviewMesh * tmpMesh = getPreviewMesh();
3938 tmpMesh->Copy( elements, copyElements);
3939 if ( !theCopy && !theTargetMesh )
3941 TIDSortedElemSet elemsAround, elemsAroundCopy;
3942 getElementsAround( elements, getMeshDS(), elemsAround );
3943 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3945 workElements = & copyElements;
3946 theMakeGroups = false;
3949 ::SMESH_MeshEditor::PGroupIDs groupIds =
3950 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3952 if ( !myIsPreviewMode )
3954 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3955 else declareMeshModified( /*isReComputeSafe=*/false );
3957 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3959 SMESH_CATCH( SMESH::throwCorbaException );
3963 //=======================================================================
3966 //=======================================================================
3968 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3969 const SMESH::PointStruct& thePoint,
3970 const SMESH::double_array& theScaleFact,
3971 CORBA::Boolean theCopy)
3972 throw (SALOME::SALOME_Exception)
3974 if ( !myIsPreviewMode ) {
3975 TPythonDump() << this << ".Scale( "
3976 << theObject << ", "
3978 << TVar( theScaleFact ) << ", "
3981 scale(theObject, thePoint, theScaleFact, theCopy, false);
3985 //=======================================================================
3986 //function : ScaleMakeGroups
3988 //=======================================================================
3990 SMESH::ListOfGroups*
3991 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3992 const SMESH::PointStruct& thePoint,
3993 const SMESH::double_array& theScaleFact)
3994 throw (SALOME::SALOME_Exception)
3996 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3998 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3999 if (!myIsPreviewMode) {
4000 dumpGroupsList(aPythonDump, aGroups);
4001 aPythonDump << this << ".Scale("
4004 << TVar( theScaleFact ) << ",True,True)";
4010 //=======================================================================
4011 //function : ScaleMakeMesh
4013 //=======================================================================
4015 SMESH::SMESH_Mesh_ptr
4016 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4017 const SMESH::PointStruct& thePoint,
4018 const SMESH::double_array& theScaleFact,
4019 CORBA::Boolean theCopyGroups,
4020 const char* theMeshName)
4021 throw (SALOME::SALOME_Exception)
4023 SMESH_Mesh_i* mesh_i;
4024 SMESH::SMESH_Mesh_var mesh;
4025 { // open new scope to dump "MakeMesh" command
4026 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4028 TPythonDump pydump; // to prevent dump at mesh creation
4029 mesh = makeMesh( theMeshName );
4030 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4034 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4035 mesh_i->CreateGroupServants();
4037 if ( !myIsPreviewMode )
4038 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4039 << theObject << ", "
4041 << TVar( theScaleFact ) << ", "
4042 << theCopyGroups << ", '"
4043 << theMeshName << "' )";
4047 if (!myIsPreviewMode && mesh_i)
4048 mesh_i->GetGroups();
4050 return mesh._retn();
4053 //================================================================================
4055 * \brief Make an offset mesh from a source 2D mesh
4056 * \param [inout] theObject - source mesh. New elements are added to this mesh
4057 * if \a theMeshName is empty.
4058 * \param [in] theValue - offset value
4059 * \param [in] theCopyGroups - to generate groups
4060 * \param [in] theMeshName - optional name of a new mesh
4061 * \param [out] theGroups - new groups
4062 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
4064 //================================================================================
4066 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4067 CORBA::Double theValue,
4068 CORBA::Boolean theCopyGroups,
4069 CORBA::Boolean theCopyElements,
4070 const char* theMeshName,
4071 SMESH::ListOfGroups_out theGroups)
4072 throw (SALOME::SALOME_Exception)
4077 SMESHDS_Mesh* aMeshDS = getMeshDS();
4079 SMESH::SMESH_Mesh_var mesh_var;
4080 ::SMESH_MeshEditor::PGroupIDs groupIds;
4084 TIDSortedElemSet elements, copyElements;
4085 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4086 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4089 SMESH_Mesh* tgtMesh = 0;
4090 if ( myIsPreviewMode )
4092 TPreviewMesh * tmpMesh = getPreviewMesh();
4094 tmpMesh->Copy( elements, copyElements );
4095 elements.swap( copyElements );
4096 theCopyGroups = false;
4097 theCopyElements = false;
4102 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4103 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4104 tgtMesh = & mesh_i->GetImpl();
4106 groupIds = getEditor().Offset( elements, theValue, tgtMesh,
4107 theCopyGroups, theCopyElements, !myIsPreviewMode );
4109 tgtMesh->GetMeshDS()->Modified();
4112 if ( myIsPreviewMode )
4114 //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4118 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4120 if ( *theMeshName && mesh_var->NbFaces() == 0 )
4122 // new mesh empty, remove it
4123 SALOMEDS::Study_var study = SMESH_Gen_i::getStudyServant();
4124 SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
4125 SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::ObjectToSObject( mesh_var );
4126 builder->RemoveObjectWithChildren( meshSO );
4127 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4130 // result of Offset() is a tuple (mesh, groups)
4131 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4132 else pyDump << mesh_var << ", ";
4133 pyDump << theGroups << " = " << this << ".Offset( "
4134 << theObject << ", "
4136 << theCopyGroups << ", "
4137 << theCopyElements << ", "
4138 << "'" << theMeshName<< "')";
4141 return mesh_var._retn();
4143 SMESH_CATCH( SMESH::throwCorbaException );
4144 return SMESH::SMESH_Mesh::_nil();
4147 //=======================================================================
4148 //function : findCoincidentNodes
4150 //=======================================================================
4152 void SMESH_MeshEditor_i::
4153 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4154 CORBA::Double Tolerance,
4155 SMESH::array_of_long_array_out GroupsOfNodes,
4156 CORBA::Boolean SeparateCornersAndMedium)
4158 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4159 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4161 GroupsOfNodes = new SMESH::array_of_long_array;
4162 GroupsOfNodes->length( aListOfListOfNodes.size() );
4163 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4164 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4166 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4167 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4168 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4169 aGroup.length( aListOfNodes.size() );
4170 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4171 aGroup[ j ] = (*lIt)->GetID();
4175 //=======================================================================
4176 //function : FindCoincidentNodes
4178 //=======================================================================
4180 void SMESH_MeshEditor_i::
4181 FindCoincidentNodes (CORBA::Double Tolerance,
4182 SMESH::array_of_long_array_out GroupsOfNodes,
4183 CORBA::Boolean SeparateCornersAndMedium)
4184 throw (SALOME::SALOME_Exception)
4189 TIDSortedNodeSet nodes; // no input nodes
4190 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4192 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4193 << Tolerance << ", "
4194 << SeparateCornersAndMedium << " )";
4196 SMESH_CATCH( SMESH::throwCorbaException );
4199 //=======================================================================
4200 //function : FindCoincidentNodesOnPart
4202 //=======================================================================
4204 void SMESH_MeshEditor_i::
4205 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4206 CORBA::Double Tolerance,
4207 SMESH::array_of_long_array_out GroupsOfNodes,
4208 CORBA::Boolean SeparateCornersAndMedium)
4209 throw (SALOME::SALOME_Exception)
4214 TIDSortedNodeSet nodes;
4215 prepareIdSource( theObject );
4216 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4218 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4220 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4222 << Tolerance << ", "
4223 << SeparateCornersAndMedium << " )";
4225 SMESH_CATCH( SMESH::throwCorbaException );
4228 //================================================================================
4230 * \brief Finds nodes coincident with Tolerance within Objects excluding nodes within
4231 * ExceptSubMeshOrGroups
4233 //================================================================================
4235 void SMESH_MeshEditor_i::
4236 FindCoincidentNodesOnPartBut(const SMESH::ListOfIDSources& theObjects,
4237 CORBA::Double theTolerance,
4238 SMESH::array_of_long_array_out theGroupsOfNodes,
4239 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4240 CORBA::Boolean theSeparateCornersAndMedium)
4241 throw (SALOME::SALOME_Exception)
4246 TIDSortedNodeSet nodes;
4247 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4249 prepareIdSource( theObjects[i] );
4250 idSourceToNodeSet( theObjects[i], getMeshDS(), nodes );
4252 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4254 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4256 while ( nodeIt->more() )
4257 nodes.erase( cast2Node( nodeIt->next() ));
4259 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4261 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4262 << theObjects <<", "
4263 << theTolerance << ", "
4264 << theExceptSubMeshOrGroups << ", "
4265 << theSeparateCornersAndMedium << " )";
4267 SMESH_CATCH( SMESH::throwCorbaException );
4270 //=======================================================================
4271 //function : MergeNodes
4273 //=======================================================================
4275 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4276 const SMESH::ListOfIDSources& NodesToKeep,
4277 CORBA::Boolean AvoidMakingHoles)
4278 throw (SALOME::SALOME_Exception)
4283 SMESHDS_Mesh* aMesh = getMeshDS();
4285 TPythonDump aTPythonDump;
4286 aTPythonDump << this << ".MergeNodes([";
4288 TIDSortedNodeSet setOfNodesToKeep;
4289 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4291 prepareIdSource( NodesToKeep[i] );
4292 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ))
4293 while ( nodeIt->more() )
4294 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4297 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4298 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4300 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4301 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4302 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4303 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4305 CORBA::Long index = aNodeGroup[ j ];
4306 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4308 if ( setOfNodesToKeep.count( node ))
4309 aListOfNodes.push_front( node );
4311 aListOfNodes.push_back( node );
4314 if ( aListOfNodes.size() < 2 )
4315 aListOfListOfNodes.pop_back();
4317 if ( i > 0 ) aTPythonDump << ", ";
4318 aTPythonDump << aNodeGroup;
4321 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4323 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4325 declareMeshModified( /*isReComputeSafe=*/false );
4327 SMESH_CATCH( SMESH::throwCorbaException );
4330 //=======================================================================
4331 //function : FindEqualElements
4333 //=======================================================================
4335 void SMESH_MeshEditor_i::FindEqualElements(const SMESH::ListOfIDSources& theObjects,
4336 const SMESH::ListOfIDSources& theExceptObjects,
4337 SMESH::array_of_long_array_out theGroupsOfElementsID)
4338 throw (SALOME::SALOME_Exception)
4343 theGroupsOfElementsID = new SMESH::array_of_long_array;
4345 TIDSortedElemSet elems;
4346 bool hasOkObject = false;
4347 bool emptyIfIsMesh= ( theObjects.length() == 1 && theExceptObjects.length() == 0 );
4349 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4351 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( theObjects[i] );
4352 if ( !( !group->_is_nil() && group->GetType() == SMESH::NODE ))
4353 if ( idSourceToSet( theObjects[i], getMeshDS(), elems, SMDSAbs_All, emptyIfIsMesh ))
4359 for ( CORBA::ULong i = 0; i < theExceptObjects.length(); ++i )
4361 if ( SMDS_ElemIteratorPtr elemIt = myMesh_i->GetElements( theExceptObjects[i], SMESH::ALL ))
4362 while ( elemIt->more() )
4363 elems.erase( elemIt->next() );
4366 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4367 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4369 theGroupsOfElementsID->length( aListOfListOfElementsID.size() );
4371 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4372 aListOfListOfElementsID.begin();
4373 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4375 SMESH::long_array& aGroup = (*theGroupsOfElementsID)[ j ];
4376 list<int>& listOfIDs = *arraysIt;
4377 aGroup.length( listOfIDs.size() );
4378 list<int>::iterator idIt = listOfIDs.begin();
4379 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4380 aGroup[ k ] = *idIt;
4383 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4384 << theObjects << ", "
4385 << theExceptObjects << " )";
4388 SMESH_CATCH( SMESH::throwCorbaException );
4391 //=======================================================================
4392 //function : MergeElements
4394 //=======================================================================
4396 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& theGroupsOfElementsID,
4397 const SMESH::ListOfIDSources& theElementsToKeep)
4398 throw (SALOME::SALOME_Exception)
4403 TPythonDump aTPythonDump;
4404 aTPythonDump << this << ".MergeElements( [";
4406 NCollection_Map< int > idsToKeep;
4407 for ( CORBA::ULong i = 0; i < theElementsToKeep.length(); i++ )
4409 if ( CORBA::is_nil( theElementsToKeep[i] ))
4411 SMESH::array_of_ElementType_var elemTypes = theElementsToKeep[i]->GetTypes();
4412 if ( elemTypes->length() == 1 && elemTypes[0] == SMESH::NODE )
4414 SMESH::long_array_var elementsId = theElementsToKeep[i]->GetIDs();
4415 for ( CORBA::ULong j = 0; j < elementsId->length(); ++j )
4416 idsToKeep.Add( elementsId[ j ]);
4419 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4421 for ( CORBA::ULong i = 0; i < theGroupsOfElementsID.length(); i++ )
4423 const SMESH::long_array& anElemsIDGroup = theGroupsOfElementsID[ i ];
4424 aListOfListOfElementsID.push_back( list< int >() );
4425 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4426 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ )
4428 CORBA::Long id = anElemsIDGroup[ j ];
4429 if ( idsToKeep.Contains( id )) aListOfElemsID.push_front( id );
4430 else aListOfElemsID.push_back( id );
4432 if ( aListOfElemsID.size() < 2 )
4433 aListOfListOfElementsID.pop_back();
4434 if ( i > 0 ) aTPythonDump << ", ";
4435 aTPythonDump << anElemsIDGroup;
4438 getEditor().MergeElements(aListOfListOfElementsID);
4440 declareMeshModified( /*isReComputeSafe=*/true );
4442 aTPythonDump << "], " << theElementsToKeep << " )";
4444 SMESH_CATCH( SMESH::throwCorbaException );
4447 //=======================================================================
4448 //function : MergeEqualElements
4450 //=======================================================================
4452 void SMESH_MeshEditor_i::MergeEqualElements()
4453 throw (SALOME::SALOME_Exception)
4458 getEditor().MergeEqualElements();
4460 declareMeshModified( /*isReComputeSafe=*/true );
4462 TPythonDump() << this << ".MergeEqualElements()";
4464 SMESH_CATCH( SMESH::throwCorbaException );
4467 //=============================================================================
4469 * Move the node to a given point
4471 //=============================================================================
4473 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4477 throw (SALOME::SALOME_Exception)
4480 initData(/*deleteSearchers=*/false);
4482 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4486 if ( theNodeSearcher )
4487 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4489 if ( myIsPreviewMode ) // make preview data
4491 // in a preview mesh, make edges linked to a node
4492 TPreviewMesh& tmpMesh = *getPreviewMesh();
4493 TIDSortedElemSet linkedNodes;
4494 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4495 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4496 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4497 for ( ; nIt != linkedNodes.end(); ++nIt )
4499 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4500 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4504 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4505 // fill preview data
4507 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4508 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4510 getMeshDS()->MoveNode(node, x, y, z);
4512 if ( !myIsPreviewMode )
4514 // Update Python script
4515 TPythonDump() << "isDone = " << this << ".MoveNode( "
4516 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4517 declareMeshModified( /*isReComputeSafe=*/false );
4520 SMESH_CATCH( SMESH::throwCorbaException );
4525 //================================================================================
4527 * \brief Return ID of node closest to a given point
4529 //================================================================================
4531 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4534 throw (SALOME::SALOME_Exception)
4537 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4539 if ( !theNodeSearcher ) {
4540 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4543 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4544 return node->GetID();
4546 SMESH_CATCH( SMESH::throwCorbaException );
4550 //================================================================================
4552 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4553 * move the node closest to the point to point's location and return ID of the node
4555 //================================================================================
4557 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4560 CORBA::Long theNodeID)
4561 throw (SALOME::SALOME_Exception)
4564 // We keep theNodeSearcher until any mesh modification:
4565 // 1) initData() deletes theNodeSearcher at any edition,
4566 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4568 initData(/*deleteSearchers=*/false);
4570 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4572 int nodeID = theNodeID;
4573 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4574 if ( !node ) // preview moving node
4576 if ( !theNodeSearcher ) {
4577 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4580 node = theNodeSearcher->FindClosestTo( p );
4583 nodeID = node->GetID();
4584 if ( myIsPreviewMode ) // make preview data
4586 // in a preview mesh, make edges linked to a node
4587 TPreviewMesh tmpMesh = *getPreviewMesh();
4588 TIDSortedElemSet linkedNodes;
4589 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4590 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4591 for ( ; nIt != linkedNodes.end(); ++nIt )
4593 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4594 tmpMesh.Copy( &edge );
4597 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4599 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4600 // fill preview data
4602 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4604 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4608 getMeshDS()->MoveNode(node, x, y, z);
4612 if ( !myIsPreviewMode )
4614 TPythonDump() << "nodeID = " << this
4615 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4616 << ", " << nodeID << " )";
4618 declareMeshModified( /*isReComputeSafe=*/false );
4623 SMESH_CATCH( SMESH::throwCorbaException );
4627 //=======================================================================
4629 * Return elements of given type where the given point is IN or ON.
4631 * 'ALL' type means elements of any type excluding nodes
4633 //=======================================================================
4635 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4638 SMESH::ElementType type)
4639 throw (SALOME::SALOME_Exception)
4642 SMESH::long_array_var res = new SMESH::long_array;
4643 vector< const SMDS_MeshElement* > foundElems;
4645 theSearchersDeleter.Set( myMesh );
4646 if ( !theElementSearcher ) {
4647 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4649 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4650 SMDSAbs_ElementType( type ),
4652 res->length( foundElems.size() );
4653 for ( size_t i = 0; i < foundElems.size(); ++i )
4654 res[i] = foundElems[i]->GetID();
4658 SMESH_CATCH( SMESH::throwCorbaException );
4662 //=======================================================================
4663 //function : FindAmongElementsByPoint
4664 //purpose : Searching among the given elements, return elements of given type
4665 // where the given point is IN or ON.
4666 // 'ALL' type means elements of any type excluding nodes
4667 //=======================================================================
4670 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4674 SMESH::ElementType type)
4675 throw (SALOME::SALOME_Exception)
4678 SMESH::long_array_var res = new SMESH::long_array;
4680 prepareIdSource( elementIDs );
4681 if ( type != SMESH::NODE )
4683 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4684 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4685 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4686 type != types[0] ) // but search of elements of dim > 0
4690 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4691 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4692 if ( mesh_i != myMesh_i )
4694 SMESH::SMESH_MeshEditor_var editor=
4695 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4696 return editor->FindAmongElementsByPoint( elementIDs, x,y,z, type );
4699 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4700 return FindElementsByPoint( x,y,z, type );
4702 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4704 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4705 if ( !theElementSearcher )
4707 // create a searcher from elementIDs
4708 SMDS_ElemIteratorPtr elemIt;
4709 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( elementIDs ))
4711 //prepareIdSource( elementIDs );
4712 elemIt = myMesh_i->GetElements( elementIDs, type );
4716 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4719 vector< const SMDS_MeshElement* > foundElems;
4721 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4722 SMDSAbs_ElementType( type ),
4724 res->length( foundElems.size() );
4725 for ( size_t i = 0; i < foundElems.size(); ++i )
4726 res[i] = foundElems[i]->GetID();
4730 SMESH_CATCH( SMESH::throwCorbaException );
4734 //=======================================================================
4735 //function : ProjectPoint
4736 //purpose : Project a point to a mesh object.
4737 // Return ID of an element of given type where the given point is projected
4738 // and coordinates of the projection point.
4739 // In the case if nothing found, return -1 and []
4740 //=======================================================================
4742 CORBA::Long SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
4745 SMESH::ElementType type,
4746 SMESH::SMESH_IDSource_ptr meshObject,
4747 SMESH::double_array_out projecton)
4748 throw (SALOME::SALOME_Exception)
4750 if ( CORBA::is_nil( meshObject ))
4751 THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
4755 SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
4756 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4757 if ( mesh_i != myMesh_i )
4759 SMESH::SMESH_MeshEditor_var editor=
4760 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4761 return editor->ProjectPoint( x,y,z, type, meshObject, projecton );
4765 theSearchersDeleter.Set( myMesh, getPartIOR( meshObject, type ));
4766 if ( !theElementSearcher )
4768 // create a searcher from meshObject
4770 SMDS_ElemIteratorPtr elemIt;
4771 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
4773 prepareIdSource( meshObject );
4774 elemIt = myMesh_i->GetElements( meshObject, type );
4778 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4781 const SMDS_MeshElement* elem = 0;
4782 gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
4783 SMDSAbs_ElementType( type ),
4786 projecton = new SMESH::double_array();
4787 if ( elem && !elem->IsNull() )
4789 projecton->length( 3 );
4790 projecton[0] = pProj.X();
4791 projecton[1] = pProj.Y();
4792 projecton[2] = pProj.Z();
4793 return elem->GetID();
4796 SMESH_CATCH( SMESH::throwCorbaException );
4800 //=======================================================================
4801 //function : GetPointState
4802 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4803 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4804 //=======================================================================
4806 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4809 throw (SALOME::SALOME_Exception)
4812 theSearchersDeleter.Set( myMesh );
4813 if ( !theElementSearcher ) {
4814 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4816 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4818 SMESH_CATCH( SMESH::throwCorbaException );
4822 //=======================================================================
4823 //function : IsManifold
4824 //purpose : Check if a 2D mesh is manifold
4825 //=======================================================================
4827 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4828 throw (SALOME::SALOME_Exception)
4830 bool isManifold = true;
4833 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4834 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4836 /*closedOnly=*/true,
4838 SMESH_CATCH( SMESH::throwCorbaException );
4843 //=======================================================================
4844 //function : IsCoherentOrientation2D
4845 //purpose : Check if orientation of 2D elements is coherent
4846 //=======================================================================
4848 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4849 throw (SALOME::SALOME_Exception)
4851 bool isGoodOri = true;
4854 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4855 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4857 /*closedOnly=*/true,
4860 SMESH_CATCH( SMESH::throwCorbaException );
4865 //=======================================================================
4866 //function : Get1DBranches
4867 //purpose : Partition given 1D elements into groups of contiguous edges.
4868 // A node where number of meeting edges != 2 is a group end.
4869 // An optional startNode is used to orient groups it belongs to.
4870 //return : a list of edge groups and a list of corresponding node groups.
4871 // If a group is closed, the first and last nodes of the group are same.
4872 //=======================================================================
4874 SMESH::array_of_long_array*
4875 SMESH_MeshEditor_i::Get1DBranches( SMESH::SMESH_IDSource_ptr theEdges,
4876 CORBA::Long theStartNode,
4877 SMESH::array_of_long_array_out theNodeGroups )
4878 throw (SALOME::SALOME_Exception)
4880 if ( CORBA::is_nil( theEdges ))
4881 THROW_SALOME_CORBA_EXCEPTION("Get1DBranches(): NULL group given", SALOME::BAD_PARAM);
4883 SMESH::array_of_long_array_var edgeGroupArray = new SMESH::array_of_long_array;
4884 theNodeGroups = new SMESH::array_of_long_array;
4888 prepareIdSource( theEdges );
4890 SMESH_MeshAlgos::TElemGroupVector edgeBranches;
4891 SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
4892 SMESH_MeshAlgos::Get1DBranches( SMESH_Mesh_i::GetElements( theEdges, SMESH::EDGE ),
4895 getMeshDS()->FindNode( theStartNode ));
4897 edgeGroupArray->length( edgeBranches.size() );
4898 for ( size_t iG = 0; iG < edgeBranches.size(); ++iG )
4900 edgeGroupArray[ iG ].length( edgeBranches[ iG ].size() );
4901 for ( size_t i = 0; i < edgeBranches[ iG ].size(); ++i )
4902 edgeGroupArray[ iG ][ i ] = edgeBranches[ iG ][ i ]->GetID();
4905 theNodeGroups->length( nodeBranches.size() );
4906 for ( size_t iG = 0; iG < nodeBranches.size(); ++iG )
4908 theNodeGroups[ iG ].length( nodeBranches[ iG ].size() );
4909 for ( size_t i = 0; i < nodeBranches[ iG ].size(); ++i )
4910 theNodeGroups[ iG ][ i ] = nodeBranches[ iG ][ i ]->GetID();
4913 SMESH_CATCH( SMESH::throwCorbaException );
4915 return edgeGroupArray._retn();
4918 //=======================================================================
4919 //function : FindSharpEdges
4920 //purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
4921 //=======================================================================
4923 SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
4924 CORBA::Boolean theAddExisting)
4925 throw (SALOME::SALOME_Exception)
4927 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
4932 std::vector< SMESH_MeshAlgos::Edge > edges =
4933 SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
4935 if ( myIsPreviewMode ) // fill a preview mesh with edges
4937 TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
4938 SMDS_Mesh* meshDS = mesh->GetMeshDS();
4939 for ( size_t i = 0; i < edges.size(); ++i )
4941 SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
4942 SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4943 SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
4944 if ( edges[i]._medium )
4946 xyz1.Set( edges[i]._medium );
4947 SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4948 mesh->GetMeshDS()->AddEdge( n1, n2, nm );
4952 mesh->GetMeshDS()->AddEdge( n1, n2 );
4958 resultEdges->length( edges.size() );
4959 for ( size_t i = 0; i < edges.size(); ++i )
4961 resultEdges[ i ].node1 = edges[i]._node1->GetID();
4962 resultEdges[ i ].node2 = edges[i]._node2->GetID();
4963 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
4966 SMESH_CATCH( SMESH::throwCorbaException );
4967 return resultEdges._retn();
4970 //=======================================================================
4971 //function : FindFreeBorders
4972 //purpose : Returns all or only closed FreeBorder's.
4973 //=======================================================================
4975 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4976 throw (SALOME::SALOME_Exception)
4978 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4981 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4982 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4984 resBorders->length( foundFreeBordes.size() );
4985 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
4987 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
4988 SMESH::FreeBorder& bordOut = resBorders[i];
4989 bordOut.nodeIDs.length( bordNodes.size() );
4990 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
4991 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
4994 SMESH_CATCH( SMESH::throwCorbaException );
4996 return resBorders._retn();
4999 //=======================================================================
5000 //function : FillHole
5001 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
5002 //=======================================================================
5004 SMESH::SMESH_Group_ptr
5005 SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole,
5006 const char* theGroupName)
5007 throw (SALOME::SALOME_Exception)
5011 if ( theHole.nodeIDs.length() < 4 )
5012 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
5013 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
5014 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
5015 "First and last nodes must be same", SALOME::BAD_PARAM);
5017 SMESH_MeshAlgos::TFreeBorder bordNodes;
5018 bordNodes.resize( theHole.nodeIDs.length() );
5019 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
5021 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
5022 if ( !bordNodes[ iN ] )
5023 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
5024 << " does not exist", SALOME::BAD_PARAM);
5029 // prepare a preview mesh
5030 MeshEditor_I::TPreviewMesh* previewMesh = 0;
5031 SMDS_Mesh* meshDS = getMeshDS();
5032 if ( myIsPreviewMode )
5034 // copy faces sharing nodes of theHole
5035 TIDSortedElemSet holeFaces;
5036 previewMesh = getPreviewMesh( SMDSAbs_Face );
5037 for ( size_t i = 0; i < bordNodes.size(); ++i )
5039 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
5040 while ( fIt->more() )
5042 const SMDS_MeshElement* face = fIt->next();
5043 if ( holeFaces.insert( face ).second )
5044 previewMesh->Copy( face );
5046 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
5047 ASSERT( bordNodes[i] );
5049 meshDS = previewMesh->GetMeshDS();
5053 std::vector<const SMDS_MeshElement*> newFaces;
5054 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
5056 if ( myIsPreviewMode )
5059 previewMesh->Clear();
5060 for ( size_t i = 0; i < newFaces.size(); ++i )
5061 previewMesh->Copy( newFaces[i] );
5065 // return new faces via a group
5066 SMESH::SMESH_Group_var group;
5067 if ( theGroupName && theGroupName[0] && !newFaces.empty() )
5069 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5070 for ( CORBA::ULong i = 0; i < groups->length(); ++i )
5072 SMESH::SMESH_GroupBase_var g = groups[ i ];
5073 if ( g->GetType() != SMESH::FACE ) continue;
5074 SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g );
5075 if ( standalone->_is_nil() ) continue;
5076 CORBA::String_var name = g->GetName();
5077 if ( strcmp( theGroupName, name.in() ) == 0 )
5083 if ( group->_is_nil() )
5084 group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName );
5086 if ( !group->_is_nil() )
5088 SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group );
5089 SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() );
5090 for ( size_t i = 0; i < newFaces.size(); ++i )
5091 grpDS->Add( newFaces[ i ]);
5096 getEditor().ClearLastCreated();
5097 SMESH_SequenceOfElemPtr& aSeq =
5098 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
5099 aSeq.swap( newFaces );
5102 if ( group->_is_nil() ) pyDump << "_group = ";
5103 else pyDump << group << " = ";
5104 pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
5106 return group._retn();
5109 SMESH_CATCH( SMESH::throwCorbaException );
5111 return SMESH::SMESH_Group::_nil();
5114 //=======================================================================
5115 //function : convError
5117 //=======================================================================
5119 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5121 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5125 RETCASE( SEW_BORDER1_NOT_FOUND );
5126 RETCASE( SEW_BORDER2_NOT_FOUND );
5127 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5128 RETCASE( SEW_BAD_SIDE_NODES );
5129 RETCASE( SEW_VOLUMES_TO_SPLIT );
5130 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5131 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5132 RETCASE( SEW_BAD_SIDE1_NODES );
5133 RETCASE( SEW_BAD_SIDE2_NODES );
5134 RETCASE( SEW_INTERNAL_ERROR );
5136 return SMESH::SMESH_MeshEditor::SEW_OK;
5139 //=======================================================================
5141 * Returns groups of FreeBorder's coincident within the given tolerance.
5142 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
5143 * to free borders being compared is used.
5145 //=======================================================================
5147 SMESH::CoincidentFreeBorders*
5148 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
5150 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
5154 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
5155 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
5157 // copy free borders
5158 aCFB->borders.length( cfb._borders.size() );
5159 for ( size_t i = 0; i < cfb._borders.size(); ++i )
5161 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
5162 SMESH::FreeBorder& aBRD = aCFB->borders[i];
5163 aBRD.nodeIDs.length( nodes.size() );
5164 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5165 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
5168 // copy coincident parts
5169 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
5170 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
5172 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
5173 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
5174 aGRP.length( grp.size() );
5175 for ( size_t iP = 0; iP < grp.size(); ++iP )
5177 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
5178 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5179 aPART.border = part._border;
5180 aPART.node1 = part._node1;
5181 aPART.node2 = part._node2;
5182 aPART.nodeLast = part._nodeLast;
5185 SMESH_CATCH( SMESH::doNothing );
5187 TPythonDump() << "CoincidentFreeBorders = "
5188 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
5190 return aCFB._retn();
5193 //=======================================================================
5195 * Sew FreeBorder's of each group
5197 //=======================================================================
5199 CORBA::Short SMESH_MeshEditor_i::
5200 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
5201 CORBA::Boolean createPolygons,
5202 CORBA::Boolean createPolyhedra)
5203 throw (SALOME::SALOME_Exception)
5205 CORBA::Short nbSewed = 0;
5207 SMESH_MeshAlgos::TFreeBorderVec groups;
5208 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
5210 // check the input and collect nodes
5211 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
5213 borderNodes.clear();
5214 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
5215 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
5217 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5218 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
5219 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
5221 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
5223 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
5224 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
5225 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
5226 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
5227 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
5228 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5230 // do not keep these nodes for further sewing as nodes can be removed by the sewing
5231 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
5232 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
5233 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
5235 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
5237 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
5239 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5241 borderNodes.push_back( n1 );
5242 borderNodes.push_back( n2 );
5243 borderNodes.push_back( n3 );
5245 groups.push_back( borderNodes );
5248 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
5249 // to get nodes that replace other nodes during merge we create 0D elements
5250 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
5253 vector< const SMDS_MeshElement* > tmp0Delems;
5254 for ( size_t i = 0; i < groups.size(); ++i )
5256 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5257 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5259 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
5261 tmp0Delems.push_back( it0D->next() );
5263 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
5267 // cout << endl << "INIT" << endl;
5268 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5270 // cout << i << " ";
5271 // if ( i % 3 == 0 ) cout << "^ ";
5272 // tmp0Delems[i]->GetNode(0)->Print( cout );
5277 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
5279 for ( size_t i = 0; i < groups.size(); ++i )
5281 bool isBordToBord = true;
5282 bool groupSewed = false;
5283 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5284 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
5286 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
5287 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
5288 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
5290 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
5291 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
5292 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
5294 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
5297 // TIDSortedElemSet emptySet, avoidSet;
5298 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
5300 // cout << "WRONG 2nd 1" << endl;
5301 // n0->Print( cout );
5302 // n1->Print( cout );
5304 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
5306 // cout << "WRONG 2nd 2" << endl;
5307 // n3->Print( cout );
5308 // n4->Print( cout );
5311 if ( !isBordToBord )
5313 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5314 n2 = 0; // and n2 is not used
5316 // 1st border moves to 2nd
5317 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5319 /*2ndIsFreeBorder=*/ isBordToBord,
5320 createPolygons, createPolyhedra);
5321 groupSewed = ( res == ok );
5323 isBordToBord = false;
5324 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5325 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5327 // cout << t << " ";
5328 // if ( t % 3 == 0 ) cout << "^ ";
5329 // tmp0Delems[t]->GetNode(0)->Print( cout );
5332 i0D += nodes.size();
5333 nbSewed += groupSewed;
5336 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5337 << freeBorders << ", "
5338 << createPolygons << ", "
5339 << createPolyhedra << " )";
5341 SMESH_CATCH( SMESH::doNothing );
5343 declareMeshModified( /*isReComputeSafe=*/false );
5345 // remove tmp 0D elements
5347 set< const SMDS_MeshElement* > removed0D;
5348 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5350 if ( removed0D.insert( tmp0Delems[i] ).second )
5351 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5353 SMESH_CATCH( SMESH::throwCorbaException );
5358 //=======================================================================
5359 //function : SewFreeBorders
5361 //=======================================================================
5363 SMESH::SMESH_MeshEditor::Sew_Error
5364 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5365 CORBA::Long SecondNodeID1,
5366 CORBA::Long LastNodeID1,
5367 CORBA::Long FirstNodeID2,
5368 CORBA::Long SecondNodeID2,
5369 CORBA::Long LastNodeID2,
5370 CORBA::Boolean CreatePolygons,
5371 CORBA::Boolean CreatePolyedrs)
5372 throw (SALOME::SALOME_Exception)
5377 SMESHDS_Mesh* aMesh = getMeshDS();
5379 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5380 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5381 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5382 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5383 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5384 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5386 if (!aBorderFirstNode ||
5387 !aBorderSecondNode||
5389 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5390 if (!aSide2FirstNode ||
5391 !aSide2SecondNode ||
5393 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5395 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5396 << FirstNodeID1 << ", "
5397 << SecondNodeID1 << ", "
5398 << LastNodeID1 << ", "
5399 << FirstNodeID2 << ", "
5400 << SecondNodeID2 << ", "
5401 << LastNodeID2 << ", "
5402 << CreatePolygons<< ", "
5403 << CreatePolyedrs<< " )";
5405 SMESH::SMESH_MeshEditor::Sew_Error error =
5406 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5417 declareMeshModified( /*isReComputeSafe=*/false );
5420 SMESH_CATCH( SMESH::throwCorbaException );
5421 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5425 //=======================================================================
5426 //function : SewConformFreeBorders
5428 //=======================================================================
5430 SMESH::SMESH_MeshEditor::Sew_Error
5431 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5432 CORBA::Long SecondNodeID1,
5433 CORBA::Long LastNodeID1,
5434 CORBA::Long FirstNodeID2,
5435 CORBA::Long SecondNodeID2)
5436 throw (SALOME::SALOME_Exception)
5441 SMESHDS_Mesh* aMesh = getMeshDS();
5443 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5444 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5445 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5446 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5447 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5448 const SMDS_MeshNode* aSide2ThirdNode = 0;
5450 if (!aBorderFirstNode ||
5451 !aBorderSecondNode||
5453 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5454 if (!aSide2FirstNode ||
5456 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5458 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5459 << FirstNodeID1 << ", "
5460 << SecondNodeID1 << ", "
5461 << LastNodeID1 << ", "
5462 << FirstNodeID2 << ", "
5463 << SecondNodeID2 << " )";
5465 SMESH::SMESH_MeshEditor::Sew_Error error =
5466 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5475 declareMeshModified( /*isReComputeSafe=*/false );
5478 SMESH_CATCH( SMESH::throwCorbaException );
5479 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5483 //=======================================================================
5484 //function : SewBorderToSide
5486 //=======================================================================
5488 SMESH::SMESH_MeshEditor::Sew_Error
5489 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5490 CORBA::Long SecondNodeIDOnFreeBorder,
5491 CORBA::Long LastNodeIDOnFreeBorder,
5492 CORBA::Long FirstNodeIDOnSide,
5493 CORBA::Long LastNodeIDOnSide,
5494 CORBA::Boolean CreatePolygons,
5495 CORBA::Boolean CreatePolyedrs)
5496 throw (SALOME::SALOME_Exception)
5501 SMESHDS_Mesh* aMesh = getMeshDS();
5503 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5504 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5505 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5506 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5507 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5508 const SMDS_MeshNode* aSide2ThirdNode = 0;
5510 if (!aBorderFirstNode ||
5511 !aBorderSecondNode||
5513 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5514 if (!aSide2FirstNode ||
5516 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5518 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5519 << FirstNodeIDOnFreeBorder << ", "
5520 << SecondNodeIDOnFreeBorder << ", "
5521 << LastNodeIDOnFreeBorder << ", "
5522 << FirstNodeIDOnSide << ", "
5523 << LastNodeIDOnSide << ", "
5524 << CreatePolygons << ", "
5525 << CreatePolyedrs << ") ";
5527 SMESH::SMESH_MeshEditor::Sew_Error error =
5528 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5538 declareMeshModified( /*isReComputeSafe=*/false );
5541 SMESH_CATCH( SMESH::throwCorbaException );
5542 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5546 //=======================================================================
5547 //function : SewSideElements
5549 //=======================================================================
5551 SMESH::SMESH_MeshEditor::Sew_Error
5552 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5553 const SMESH::long_array& IDsOfSide2Elements,
5554 CORBA::Long NodeID1OfSide1ToMerge,
5555 CORBA::Long NodeID1OfSide2ToMerge,
5556 CORBA::Long NodeID2OfSide1ToMerge,
5557 CORBA::Long NodeID2OfSide2ToMerge)
5558 throw (SALOME::SALOME_Exception)
5563 SMESHDS_Mesh* aMesh = getMeshDS();
5565 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5566 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5567 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5568 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5570 if (!aFirstNode1ToMerge ||
5571 !aFirstNode2ToMerge )
5572 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5573 if (!aSecondNode1ToMerge||
5574 !aSecondNode2ToMerge)
5575 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5577 TIDSortedElemSet aSide1Elems, aSide2Elems;
5578 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5579 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5581 TPythonDump() << "error = " << this << ".SewSideElements( "
5582 << IDsOfSide1Elements << ", "
5583 << IDsOfSide2Elements << ", "
5584 << NodeID1OfSide1ToMerge << ", "
5585 << NodeID1OfSide2ToMerge << ", "
5586 << NodeID2OfSide1ToMerge << ", "
5587 << NodeID2OfSide2ToMerge << ")";
5589 SMESH::SMESH_MeshEditor::Sew_Error error =
5590 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5593 aSecondNode1ToMerge,
5594 aSecondNode2ToMerge));
5596 declareMeshModified( /*isReComputeSafe=*/false );
5599 SMESH_CATCH( SMESH::throwCorbaException );
5600 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5603 //================================================================================
5605 * \brief Set new nodes for given element
5606 * \param ide - element id
5607 * \param newIDs - new node ids
5608 * \retval CORBA::Boolean - true if result is OK
5610 //================================================================================
5612 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5613 const SMESH::long_array& newIDs)
5614 throw (SALOME::SALOME_Exception)
5619 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5620 if(!elem) return false;
5622 int nbn = newIDs.length();
5624 vector<const SMDS_MeshNode*> aNodes(nbn);
5627 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5630 aNodes[nbn1] = aNode;
5633 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5634 << ide << ", " << newIDs << " )";
5636 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5638 declareMeshModified( /*isReComputeSafe=*/ !res );
5642 SMESH_CATCH( SMESH::throwCorbaException );
5646 //=======================================================================
5648 * \brief Makes a part of the mesh quadratic or bi-quadratic
5650 //=======================================================================
5652 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5653 CORBA::Boolean theToBiQuad,
5654 SMESH::SMESH_IDSource_ptr theObject)
5655 throw (SALOME::SALOME_Exception)
5660 TIDSortedElemSet elems;
5662 if ( !( elemsOK = CORBA::is_nil( theObject )))
5664 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5665 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5669 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5670 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5672 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5673 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5675 declareMeshModified( /*isReComputeSafe=*/false );
5678 SMESH_CATCH( SMESH::throwCorbaException );
5681 //=======================================================================
5682 //function : ConvertFromQuadratic
5684 //=======================================================================
5686 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5687 throw (SALOME::SALOME_Exception)
5692 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5693 TPythonDump() << this << ".ConvertFromQuadratic()";
5694 declareMeshModified( /*isReComputeSafe=*/!isDone );
5697 SMESH_CATCH( SMESH::throwCorbaException );
5701 //=======================================================================
5702 //function : ConvertToQuadratic
5704 //=======================================================================
5706 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5707 throw (SALOME::SALOME_Exception)
5709 convertToQuadratic( theForce3d, false );
5710 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5713 //================================================================================
5715 * \brief Makes a part of the mesh quadratic
5717 //================================================================================
5719 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5720 SMESH::SMESH_IDSource_ptr theObject)
5721 throw (SALOME::SALOME_Exception)
5723 convertToQuadratic( theForce3d, false, theObject );
5724 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5727 //================================================================================
5729 * \brief Makes a part of the mesh bi-quadratic
5731 //================================================================================
5733 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5734 SMESH::SMESH_IDSource_ptr theObject)
5735 throw (SALOME::SALOME_Exception)
5737 convertToQuadratic( theForce3d, true, theObject );
5738 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5741 //================================================================================
5743 * \brief Makes a part of the mesh linear
5745 //================================================================================
5747 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5748 throw (SALOME::SALOME_Exception)
5755 TIDSortedElemSet elems;
5756 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5758 if ( elems.empty() )
5760 ConvertFromQuadratic();
5762 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5764 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5768 getEditor().ConvertFromQuadratic(elems);
5771 declareMeshModified( /*isReComputeSafe=*/false );
5773 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5775 SMESH_CATCH( SMESH::throwCorbaException );
5778 //=======================================================================
5779 //function : makeMesh
5780 //purpose : create a named imported mesh
5781 //=======================================================================
5783 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5785 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5786 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5787 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5788 gen->SetName( meshSO, theMeshName, "Mesh" );
5789 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5791 return mesh._retn();
5794 //=======================================================================
5795 //function : dumpGroupsList
5797 //=======================================================================
5799 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5800 const SMESH::ListOfGroups * theGroupList)
5802 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5803 if ( isDumpGroupList )
5804 theDumpPython << theGroupList << " = ";
5807 //================================================================================
5809 \brief Generates the unique group name.
5810 \param thePrefix name prefix
5813 //================================================================================
5815 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5817 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5818 set<std::string> groupNames;
5820 // Get existing group names
5821 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5822 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5823 if (CORBA::is_nil(aGroup))
5826 CORBA::String_var name = aGroup->GetName();
5827 groupNames.insert( name.in() );
5831 std::string name = thePrefix;
5834 while (!groupNames.insert(name).second)
5835 name = SMESH_Comment( thePrefix ) << "_" << index++;
5840 //================================================================================
5842 * \brief Prepare SMESH_IDSource for work
5844 //================================================================================
5846 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5848 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5850 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5851 filter->SetMesh( mesh );
5854 //================================================================================
5856 * \brief Retrieve elements of given type from SMESH_IDSource
5858 //================================================================================
5860 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5861 const SMESHDS_Mesh* theMeshDS,
5862 TIDSortedElemSet& theElemSet,
5863 const SMDSAbs_ElementType theType,
5864 const bool emptyIfIsMesh,
5865 IDSource_Error* error)
5868 if ( error ) *error = IDSource_OK;
5870 if ( CORBA::is_nil( theIDSource ))
5872 if ( error ) *error = IDSource_INVALID;
5875 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5877 if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
5878 *error = IDSource_EMPTY;
5881 if ( getMeshDS() == theMeshDS ) // check if theIDSource belongs to myMesh
5883 SMESH::SMESH_Mesh_var mesh = theIDSource->GetMesh();
5884 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5885 if ( mesh_i && mesh_i != myMesh_i )
5888 *error = IDSource_INVALID;
5892 prepareIdSource( theIDSource );
5893 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5894 if ( anIDs->length() == 0 )
5896 if ( error ) *error = IDSource_EMPTY;
5899 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5900 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5902 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5904 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5908 if ( error ) *error = IDSource_INVALID;
5914 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5915 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5917 if ( error ) *error = IDSource_INVALID;
5924 //================================================================================
5926 * \brief Duplicates given elements, i.e. creates new elements based on the
5927 * same nodes as the given ones.
5928 * \param theElements - container of elements to duplicate.
5929 * \param theGroupName - a name of group to contain the generated elements.
5930 * If a group with such a name already exists, the new elements
5931 * are added to the existing group, else a new group is created.
5932 * If \a theGroupName is empty, new elements are not added
5934 * \return a group where the new elements are added. NULL if theGroupName == "".
5937 //================================================================================
5939 SMESH::SMESH_Group_ptr
5940 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5941 const char* theGroupName)
5942 throw (SALOME::SALOME_Exception)
5944 SMESH::SMESH_Group_var newGroup;
5951 TIDSortedElemSet elems;
5952 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5954 getEditor().DoubleElements( elems );
5956 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5959 SMESH::ElementType type =
5960 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5961 // find existing group
5962 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5963 for ( size_t i = 0; i < groups->length(); ++i )
5964 if ( groups[i]->GetType() == type )
5966 CORBA::String_var name = groups[i]->GetName();
5967 if ( strcmp( name, theGroupName ) == 0 ) {
5968 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5972 // create a new group
5973 if ( newGroup->_is_nil() )
5974 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5976 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5978 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5979 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5980 for ( size_t i = 0; i < aSeq.size(); i++ )
5981 groupDS->SMDSGroup().Add( aSeq[i] );
5986 if ( !newGroup->_is_nil() )
5987 pyDump << newGroup << " = ";
5988 pyDump << this << ".DoubleElements( "
5989 << theElements << ", " << "'" << theGroupName <<"')";
5991 SMESH_CATCH( SMESH::throwCorbaException );
5993 return newGroup._retn();
5996 //================================================================================
5998 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5999 \param theNodes - identifiers of nodes to be doubled
6000 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
6001 nodes. If list of element identifiers is empty then nodes are doubled but
6002 they not assigned to elements
6003 \return TRUE if operation has been completed successfully, FALSE otherwise
6004 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
6006 //================================================================================
6008 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
6009 const SMESH::long_array& theModifiedElems )
6010 throw (SALOME::SALOME_Exception)
6015 list< int > aListOfNodes;
6017 for ( i = 0, n = theNodes.length(); i < n; i++ )
6018 aListOfNodes.push_back( theNodes[ i ] );
6020 list< int > aListOfElems;
6021 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6022 aListOfElems.push_back( theModifiedElems[ i ] );
6024 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
6026 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6028 // Update Python script
6029 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
6033 SMESH_CATCH( SMESH::throwCorbaException );
6037 //================================================================================
6039 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6040 This method provided for convenience works as DoubleNodes() described above.
6041 \param theNodeId - identifier of node to be doubled.
6042 \param theModifiedElems - identifiers of elements to be updated.
6043 \return TRUE if operation has been completed successfully, FALSE otherwise
6044 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
6046 //================================================================================
6048 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
6049 const SMESH::long_array& theModifiedElems )
6050 throw (SALOME::SALOME_Exception)
6053 SMESH::long_array_var aNodes = new SMESH::long_array;
6054 aNodes->length( 1 );
6055 aNodes[ 0 ] = theNodeId;
6057 TPythonDump pyDump; // suppress dump by the next line
6059 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
6061 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
6065 SMESH_CATCH( SMESH::throwCorbaException );
6069 //================================================================================
6071 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6072 This method provided for convenience works as DoubleNodes() described above.
6073 \param theNodes - group of nodes to be doubled.
6074 \param theModifiedElems - group of elements to be updated.
6075 \return TRUE if operation has been completed successfully, FALSE otherwise
6076 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
6078 //================================================================================
6080 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
6081 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6082 throw (SALOME::SALOME_Exception)
6085 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6088 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6089 SMESH::long_array_var aModifiedElems;
6090 if ( !CORBA::is_nil( theModifiedElems ) )
6091 aModifiedElems = theModifiedElems->GetListOfID();
6093 aModifiedElems = new SMESH::long_array;
6095 TPythonDump pyDump; // suppress dump by the next line
6097 bool done = DoubleNodes( aNodes, aModifiedElems );
6099 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6103 SMESH_CATCH( SMESH::throwCorbaException );
6107 //================================================================================
6109 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6110 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6111 * \param theNodes - group of nodes to be doubled.
6112 * \param theModifiedElems - group of elements to be updated.
6113 * \return a new group with newly created nodes
6114 * \sa DoubleNodeGroup()
6116 //================================================================================
6118 SMESH::SMESH_Group_ptr
6119 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6120 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6121 throw (SALOME::SALOME_Exception)
6124 SMESH::SMESH_Group_var aNewGroup;
6126 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6127 return aNewGroup._retn();
6130 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6131 SMESH::long_array_var aModifiedElems;
6132 if ( !CORBA::is_nil( theModifiedElems ) )
6133 aModifiedElems = theModifiedElems->GetListOfID();
6135 aModifiedElems = new SMESH::long_array;
6136 aModifiedElems->length( 0 );
6139 TPythonDump pyDump; // suppress dump by the next line
6141 bool aResult = DoubleNodes( aNodes, aModifiedElems );
6144 // Create group with newly created nodes
6145 SMESH::long_array_var anIds = GetLastCreatedNodes();
6146 if (anIds->length() > 0) {
6147 std::string anUnindexedName (theNodes->GetName());
6148 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6149 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6150 aNewGroup->Add(anIds);
6151 pyDump << aNewGroup << " = ";
6155 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6156 << theModifiedElems << " )";
6158 return aNewGroup._retn();
6160 SMESH_CATCH( SMESH::throwCorbaException );
6164 //================================================================================
6166 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6167 This method provided for convenience works as DoubleNodes() described above.
6168 \param theNodes - list of groups of nodes to be doubled
6169 \param theModifiedElems - list of groups of elements to be updated.
6170 \return TRUE if operation has been completed successfully, FALSE otherwise
6171 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6173 //================================================================================
6175 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6176 const SMESH::ListOfGroups& theModifiedElems )
6177 throw (SALOME::SALOME_Exception)
6182 std::list< int > aNodes;
6184 for ( i = 0, n = theNodes.length(); i < n; i++ )
6186 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6187 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6189 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6190 for ( j = 0, m = aCurr->length(); j < m; j++ )
6191 aNodes.push_back( aCurr[ j ] );
6195 std::list< int > anElems;
6196 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6198 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6199 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6201 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6202 for ( j = 0, m = aCurr->length(); j < m; j++ )
6203 anElems.push_back( aCurr[ j ] );
6207 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6209 declareMeshModified( /*isReComputeSafe=*/false );
6211 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6215 SMESH_CATCH( SMESH::throwCorbaException );
6219 //================================================================================
6221 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6222 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6223 * \param theNodes - group of nodes to be doubled.
6224 * \param theModifiedElems - group of elements to be updated.
6225 * \return a new group with newly created nodes
6226 * \sa DoubleNodeGroups()
6228 //================================================================================
6230 SMESH::SMESH_Group_ptr
6231 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6232 const SMESH::ListOfGroups& theModifiedElems )
6233 throw (SALOME::SALOME_Exception)
6235 SMESH::SMESH_Group_var aNewGroup;
6237 TPythonDump pyDump; // suppress dump by the next line
6239 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6243 // Create group with newly created nodes
6244 SMESH::long_array_var anIds = GetLastCreatedNodes();
6245 if (anIds->length() > 0) {
6246 std::string anUnindexedName (theNodes[0]->GetName());
6247 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6248 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6249 aNewGroup->Add(anIds);
6250 pyDump << aNewGroup << " = ";
6254 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6255 << theModifiedElems << " )";
6257 return aNewGroup._retn();
6261 //================================================================================
6263 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6264 \param theElems - the list of elements (edges or faces) to be replicated
6265 The nodes for duplication could be found from these elements
6266 \param theNodesNot - list of nodes to NOT replicate
6267 \param theAffectedElems - the list of elements (cells and edges) to which the
6268 replicated nodes should be associated to.
6269 \return TRUE if operation has been completed successfully, FALSE otherwise
6270 \sa DoubleNodeGroup(), DoubleNodeGroups()
6272 //================================================================================
6274 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6275 const SMESH::long_array& theNodesNot,
6276 const SMESH::long_array& theAffectedElems )
6277 throw (SALOME::SALOME_Exception)
6282 SMESHDS_Mesh* aMeshDS = getMeshDS();
6283 TIDSortedElemSet anElems, aNodes, anAffected;
6284 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6285 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6286 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6288 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6290 // Update Python script
6291 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6292 << theNodesNot << ", " << theAffectedElems << " )";
6294 declareMeshModified( /*isReComputeSafe=*/false );
6297 SMESH_CATCH( SMESH::throwCorbaException );
6301 //================================================================================
6303 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6304 \param theElems - the list of elements (edges or faces) to be replicated
6305 The nodes for duplication could be found from these elements
6306 \param theNodesNot - list of nodes to NOT replicate
6307 \param theShape - shape to detect affected elements (element which geometric center
6308 located on or inside shape).
6309 The replicated nodes should be associated to affected elements.
6310 \return TRUE if operation has been completed successfully, FALSE otherwise
6311 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6313 //================================================================================
6315 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6316 const SMESH::long_array& theNodesNot,
6317 GEOM::GEOM_Object_ptr theShape )
6318 throw (SALOME::SALOME_Exception)
6324 SMESHDS_Mesh* aMeshDS = getMeshDS();
6325 TIDSortedElemSet anElems, aNodes;
6326 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6327 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6329 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6330 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6332 // Update Python script
6333 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6334 << theNodesNot << ", " << theShape << " )";
6336 declareMeshModified( /*isReComputeSafe=*/false );
6339 SMESH_CATCH( SMESH::throwCorbaException );
6343 //================================================================================
6345 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6346 \param theElems - group of of elements (edges or faces) to be replicated
6347 \param theNodesNot - group of nodes not to replicated
6348 \param theAffectedElems - group of elements to which the replicated nodes
6349 should be associated to.
6350 \return TRUE if operation has been completed successfully, FALSE otherwise
6351 \sa DoubleNodes(), DoubleNodeGroups()
6353 //================================================================================
6356 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6357 SMESH::SMESH_GroupBase_ptr theNodesNot,
6358 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6359 throw (SALOME::SALOME_Exception)
6362 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6368 SMESHDS_Mesh* aMeshDS = getMeshDS();
6369 TIDSortedElemSet anElems, aNodes, anAffected;
6370 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6371 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6372 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6374 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6376 // Update Python script
6377 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6378 << theNodesNot << ", " << theAffectedElems << " )";
6380 declareMeshModified( /*isReComputeSafe=*/false );
6383 SMESH_CATCH( SMESH::throwCorbaException );
6387 //================================================================================
6389 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6390 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6391 * \param theElems - group of of elements (edges or faces) to be replicated
6392 * \param theNodesNot - group of nodes not to replicated
6393 * \param theAffectedElems - group of elements to which the replicated nodes
6394 * should be associated to.
6395 * \return a new group with newly created elements
6396 * \sa DoubleNodeElemGroup()
6398 //================================================================================
6400 SMESH::SMESH_Group_ptr
6401 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6402 SMESH::SMESH_GroupBase_ptr theNodesNot,
6403 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6404 throw (SALOME::SALOME_Exception)
6407 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6411 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6412 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6414 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6416 << theNodesNot << ", "
6417 << theAffectedElems << " )";
6419 return elemGroup._retn();
6422 //================================================================================
6424 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6425 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6426 * \param theElems - group of of elements (edges or faces) to be replicated
6427 * \param theNodesNot - group of nodes not to replicated
6428 * \param theAffectedElems - group of elements to which the replicated nodes
6429 * should be associated to.
6430 * \return a new group with newly created elements
6431 * \sa DoubleNodeElemGroup()
6433 //================================================================================
6435 SMESH::ListOfGroups*
6436 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6437 SMESH::SMESH_GroupBase_ptr theNodesNot,
6438 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6439 CORBA::Boolean theElemGroupNeeded,
6440 CORBA::Boolean theNodeGroupNeeded)
6441 throw (SALOME::SALOME_Exception)
6444 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6445 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6446 aTwoGroups->length( 2 );
6448 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6449 return aTwoGroups._retn();
6454 SMESHDS_Mesh* aMeshDS = getMeshDS();
6455 TIDSortedElemSet anElems, aNodes, anAffected;
6456 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6457 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6458 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6461 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6463 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6469 // Create group with newly created elements
6470 CORBA::String_var elemGroupName = theElems->GetName();
6471 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6472 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6474 SMESH::long_array_var anIds = GetLastCreatedElems();
6475 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6476 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6477 aNewElemGroup->Add(anIds);
6479 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6481 SMESH::long_array_var anIds = GetLastCreatedNodes();
6482 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6483 aNewNodeGroup->Add(anIds);
6487 // Update Python script
6490 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6491 else pyDump << aNewElemGroup << ", ";
6492 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6493 else pyDump << aNewNodeGroup << " ] = ";
6495 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6496 << theNodesNot << ", "
6497 << theAffectedElems << ", "
6498 << theElemGroupNeeded << ", "
6499 << theNodeGroupNeeded <<" )";
6501 aTwoGroups[0] = aNewElemGroup._retn();
6502 aTwoGroups[1] = aNewNodeGroup._retn();
6503 return aTwoGroups._retn();
6505 SMESH_CATCH( SMESH::throwCorbaException );
6509 //================================================================================
6511 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6512 \param theElems - group of of elements (edges or faces) to be replicated
6513 \param theNodesNot - group of nodes not to replicated
6514 \param theShape - shape to detect affected elements (element which geometric center
6515 located on or inside shape).
6516 The replicated nodes should be associated to affected elements.
6517 \return TRUE if operation has been completed successfully, FALSE otherwise
6518 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6520 //================================================================================
6523 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6524 SMESH::SMESH_GroupBase_ptr theNodesNot,
6525 GEOM::GEOM_Object_ptr theShape )
6526 throw (SALOME::SALOME_Exception)
6529 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6535 SMESHDS_Mesh* aMeshDS = getMeshDS();
6536 TIDSortedElemSet anElems, aNodes, anAffected;
6537 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6538 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6540 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6541 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6544 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6546 // Update Python script
6547 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6548 << theNodesNot << ", " << theShape << " )";
6551 SMESH_CATCH( SMESH::throwCorbaException );
6555 //================================================================================
6557 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6558 * \param [in] theGrpList - groups
6559 * \param [in] theMeshDS - mesh
6560 * \param [out] theElemSet - set of elements
6561 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6563 //================================================================================
6565 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6566 SMESHDS_Mesh* theMeshDS,
6567 TIDSortedElemSet& theElemSet,
6568 const bool theIsNodeGrp)
6570 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6572 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6573 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6574 : aGrp->GetType() != SMESH::NODE ) )
6576 SMESH::long_array_var anIDs = aGrp->GetIDs();
6577 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6582 //================================================================================
6584 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6585 This method provided for convenience works as DoubleNodes() described above.
6586 \param theElems - list of groups of elements (edges or faces) to be replicated
6587 \param theNodesNot - list of groups of nodes not to replicated
6588 \param theAffectedElems - group of elements to which the replicated nodes
6589 should be associated to.
6590 \return TRUE if operation has been completed successfully, FALSE otherwise
6591 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6593 //================================================================================
6596 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6597 const SMESH::ListOfGroups& theNodesNot,
6598 const SMESH::ListOfGroups& theAffectedElems)
6599 throw (SALOME::SALOME_Exception)
6605 SMESHDS_Mesh* aMeshDS = getMeshDS();
6606 TIDSortedElemSet anElems, aNodes, anAffected;
6607 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6608 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6609 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6611 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6613 // Update Python script
6614 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6615 << &theNodesNot << ", " << &theAffectedElems << " )";
6617 declareMeshModified( /*isReComputeSafe=*/false );
6620 SMESH_CATCH( SMESH::throwCorbaException );
6624 //================================================================================
6626 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6627 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6628 \param theElems - list of groups of elements (edges or faces) to be replicated
6629 \param theNodesNot - list of groups of nodes not to replicated
6630 \param theAffectedElems - group of elements to which the replicated nodes
6631 should be associated to.
6632 * \return a new group with newly created elements
6633 * \sa DoubleNodeElemGroups()
6635 //================================================================================
6637 SMESH::SMESH_Group_ptr
6638 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6639 const SMESH::ListOfGroups& theNodesNot,
6640 const SMESH::ListOfGroups& theAffectedElems)
6641 throw (SALOME::SALOME_Exception)
6644 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6648 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6649 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6651 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6653 << theNodesNot << ", "
6654 << theAffectedElems << " )";
6656 return elemGroup._retn();
6659 //================================================================================
6661 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6662 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6663 \param theElems - list of groups of elements (edges or faces) to be replicated
6664 \param theNodesNot - list of groups of nodes not to replicated
6665 \param theAffectedElems - group of elements to which the replicated nodes
6666 should be associated to.
6667 * \return a new group with newly created elements
6668 * \sa DoubleNodeElemGroups()
6670 //================================================================================
6672 SMESH::ListOfGroups*
6673 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6674 const SMESH::ListOfGroups& theNodesNot,
6675 const SMESH::ListOfGroups& theAffectedElems,
6676 CORBA::Boolean theElemGroupNeeded,
6677 CORBA::Boolean theNodeGroupNeeded)
6678 throw (SALOME::SALOME_Exception)
6681 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6682 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6683 aTwoGroups->length( 2 );
6688 SMESHDS_Mesh* aMeshDS = getMeshDS();
6689 TIDSortedElemSet anElems, aNodes, anAffected;
6690 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6691 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6692 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6694 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6696 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6701 // Create group with newly created elements
6702 CORBA::String_var elemGroupName = theElems[0]->GetName();
6703 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6704 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6706 SMESH::long_array_var anIds = GetLastCreatedElems();
6707 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6708 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6709 aNewElemGroup->Add(anIds);
6711 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6713 SMESH::long_array_var anIds = GetLastCreatedNodes();
6714 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6715 aNewNodeGroup->Add(anIds);
6719 // Update Python script
6722 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6723 else pyDump << aNewElemGroup << ", ";
6724 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6725 else pyDump << aNewNodeGroup << " ] = ";
6727 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6728 << &theNodesNot << ", "
6729 << &theAffectedElems << ", "
6730 << theElemGroupNeeded << ", "
6731 << theNodeGroupNeeded << " )";
6733 aTwoGroups[0] = aNewElemGroup._retn();
6734 aTwoGroups[1] = aNewNodeGroup._retn();
6735 return aTwoGroups._retn();
6737 SMESH_CATCH( SMESH::throwCorbaException );
6741 //================================================================================
6743 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6744 This method provided for convenience works as DoubleNodes() described above.
6745 \param theElems - list of groups of elements (edges or faces) to be replicated
6746 \param theNodesNot - list of groups of nodes not to replicated
6747 \param theShape - shape to detect affected elements (element which geometric center
6748 located on or inside shape).
6749 The replicated nodes should be associated to affected elements.
6750 \return TRUE if operation has been completed successfully, FALSE otherwise
6751 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6753 //================================================================================
6756 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6757 const SMESH::ListOfGroups& theNodesNot,
6758 GEOM::GEOM_Object_ptr theShape )
6759 throw (SALOME::SALOME_Exception)
6765 SMESHDS_Mesh* aMeshDS = getMeshDS();
6766 TIDSortedElemSet anElems, aNodes;
6767 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6768 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6770 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6771 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6773 // Update Python script
6774 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6775 << &theNodesNot << ", " << theShape << " )";
6777 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6780 SMESH_CATCH( SMESH::throwCorbaException );
6784 //================================================================================
6786 \brief Identify the elements that will be affected by node duplication (actual
6787 duplication is not performed.
6788 This method is the first step of DoubleNodeElemGroupsInRegion.
6789 \param theElems - list of groups of elements (edges or faces) to be replicated
6790 \param theNodesNot - list of groups of nodes not to replicated
6791 \param theShape - shape to detect affected elements (element which geometric center
6792 located on or inside shape).
6793 The replicated nodes should be associated to affected elements.
6794 \return groups of affected elements
6795 \sa DoubleNodeElemGroupsInRegion()
6797 //================================================================================
6798 SMESH::ListOfGroups*
6799 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6800 const SMESH::ListOfGroups& theNodesNot,
6801 GEOM::GEOM_Object_ptr theShape )
6802 throw (SALOME::SALOME_Exception)
6805 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6806 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6807 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6808 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6812 ::SMESH_MeshEditor aMeshEditor(myMesh);
6814 SMESHDS_Mesh* aMeshDS = getMeshDS();
6815 TIDSortedElemSet anElems, aNodes;
6816 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6817 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6818 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6820 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6821 TIDSortedElemSet anAffected;
6822 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6824 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6827 if ( aResult && anAffected.size() > 0 )
6829 SMESH::long_array_var volumeIds = new SMESH::long_array;
6830 SMESH::long_array_var faceIds = new SMESH::long_array;
6831 SMESH::long_array_var edgeIds = new SMESH::long_array;
6832 volumeIds->length( anAffected.size() );
6833 faceIds ->length( anAffected.size() );
6834 edgeIds ->length( anAffected.size() );
6839 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6840 for (; eIt != anAffected.end(); ++eIt)
6842 const SMDS_MeshElement* anElem = *eIt;
6843 int elemId = anElem->GetID();
6844 switch ( anElem->GetType() ) {
6845 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6846 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6847 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6851 volumeIds->length(ivol);
6852 faceIds->length(iface);
6853 edgeIds->length(iedge);
6858 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6859 GenerateGroupName("affectedVolumes").c_str());
6860 aNewVolumeGroup->Add(volumeIds);
6861 aListOfGroups->length( nbGroups+1 );
6862 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6866 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6867 GenerateGroupName("affectedFaces").c_str());
6868 aNewFaceGroup->Add(faceIds);
6869 aListOfGroups->length( nbGroups+1 );
6870 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6874 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6875 GenerateGroupName("affectedEdges").c_str());
6876 aNewEdgeGroup->Add(edgeIds);
6877 aListOfGroups->length( nbGroups+1 );
6878 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6882 // Update Python script
6884 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6885 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6887 return aListOfGroups._retn();
6889 SMESH_CATCH( SMESH::throwCorbaException );
6893 //================================================================================
6895 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6896 The created 2D mesh elements based on nodes of free faces of boundary volumes
6897 \return TRUE if operation has been completed successfully, FALSE otherwise
6899 //================================================================================
6901 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6902 throw (SALOME::SALOME_Exception)
6907 bool aResult = getEditor().Make2DMeshFrom3D();
6909 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6911 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6914 SMESH_CATCH( SMESH::throwCorbaException );
6918 //================================================================================
6920 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6921 * The list of groups must contain at least two groups. The groups have to be disjoint:
6922 * no common element into two different groups.
6923 * The nodes of the internal faces at the boundaries of the groups are doubled.
6924 * Optionally, the internal faces are replaced by flat elements.
6925 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6926 * The flat elements are stored in groups of volumes.
6927 * These groups are named according to the position of the group in the list:
6928 * 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.
6929 * 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.
6930 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6931 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6932 * \param theDomains - list of groups of volumes
6933 * \param createJointElems - if TRUE, create the elements
6934 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6935 * the boundary between \a theDomains and the rest mesh
6936 * \return TRUE if operation has been completed successfully, FALSE otherwise
6938 //================================================================================
6941 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6942 CORBA::Boolean createJointElems,
6943 CORBA::Boolean onAllBoundaries )
6944 throw (SALOME::SALOME_Exception)
6951 SMESHDS_Mesh* aMeshDS = getMeshDS();
6953 // MESSAGE("theDomains.length = "<<theDomains.length());
6954 if ( theDomains.length() <= 1 && !onAllBoundaries )
6955 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6957 vector<TIDSortedElemSet> domains;
6958 domains.resize( theDomains.length() );
6960 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6962 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6963 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6965 // if ( aGrp->GetType() != SMESH::VOLUME )
6966 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6967 SMESH::long_array_var anIDs = aGrp->GetIDs();
6968 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6972 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6973 // TODO publish the groups of flat elements in study
6975 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6977 // Update Python script
6978 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6979 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6981 SMESH_CATCH( SMESH::throwCorbaException );
6983 myMesh_i->CreateGroupServants(); // publish created groups if any
6988 //================================================================================
6990 * \brief Double nodes on some external faces and create flat elements.
6991 * Flat elements are mainly used by some types of mechanic calculations.
6993 * Each group of the list must be constituted of faces.
6994 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6995 * @param theGroupsOfFaces - list of groups of faces
6996 * @return TRUE if operation has been completed successfully, FALSE otherwise
6998 //================================================================================
7001 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
7002 throw (SALOME::SALOME_Exception)
7007 SMESHDS_Mesh* aMeshDS = getMeshDS();
7009 vector<TIDSortedElemSet> faceGroups;
7012 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
7014 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
7015 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
7017 TIDSortedElemSet faceGroup;
7019 faceGroups.push_back(faceGroup);
7020 SMESH::long_array_var anIDs = aGrp->GetIDs();
7021 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
7025 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
7026 // TODO publish the groups of flat elements in study
7028 declareMeshModified( /*isReComputeSafe=*/ !aResult );
7030 // Update Python script
7031 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
7034 SMESH_CATCH( SMESH::throwCorbaException );
7038 //================================================================================
7040 * \brief Identify all the elements around a geom shape, get the faces delimiting
7043 * Build groups of volume to remove, groups of faces to replace on the skin of the
7044 * object, groups of faces to remove inside the object, (idem edges).
7045 * Build ordered list of nodes at the border of each group of faces to replace
7046 * (to be used to build a geom subshape).
7048 //================================================================================
7050 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
7051 GEOM::GEOM_Object_ptr theShape,
7052 const char* groupName,
7053 const SMESH::double_array& theNodesCoords,
7054 SMESH::array_of_long_array_out GroupsOfNodes)
7055 throw (SALOME::SALOME_Exception)
7060 std::vector<std::vector<int> > aListOfListOfNodes;
7061 ::SMESH_MeshEditor aMeshEditor( myMesh );
7063 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
7064 if ( !theNodeSearcher )
7065 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
7067 vector<double> nodesCoords;
7068 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
7070 nodesCoords.push_back( theNodesCoords[i] );
7073 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
7074 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
7075 nodesCoords, aListOfListOfNodes);
7077 GroupsOfNodes = new SMESH::array_of_long_array;
7078 GroupsOfNodes->length( aListOfListOfNodes.size() );
7079 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
7080 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
7082 vector<int>& aListOfNodes = *llIt;
7083 vector<int>::iterator lIt = aListOfNodes.begin();;
7084 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
7085 aGroup.length( aListOfNodes.size() );
7086 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
7087 aGroup[ j ] = (*lIt);
7089 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
7092 << ", '" << groupName << "', "
7093 << theNodesCoords << " )";
7095 SMESH_CATCH( SMESH::throwCorbaException );
7098 // issue 20749 ===================================================================
7100 * \brief Creates missing boundary elements
7101 * \param elements - elements whose boundary is to be checked
7102 * \param dimension - defines type of boundary elements to create
7103 * \param groupName - a name of group to store created boundary elements in,
7104 * "" means not to create the group
7105 * \param meshName - a name of new mesh to store created boundary elements in,
7106 * "" means not to create the new mesh
7107 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
7108 * \param toCopyExistingBondary - if true, not only new but also pre-existing
7109 * boundary elements will be copied into the new mesh
7110 * \param group - returns the create group, if any
7111 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7113 // ================================================================================
7115 SMESH::SMESH_Mesh_ptr
7116 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7117 SMESH::Bnd_Dimension dim,
7118 const char* groupName,
7119 const char* meshName,
7120 CORBA::Boolean toCopyElements,
7121 CORBA::Boolean toCopyExistingBondary,
7122 SMESH::SMESH_Group_out group)
7123 throw (SALOME::SALOME_Exception)
7128 if ( dim > SMESH::BND_1DFROM2D )
7129 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7131 SMESHDS_Mesh* aMeshDS = getMeshDS();
7133 SMESH::SMESH_Mesh_var mesh_var;
7134 SMESH::SMESH_Group_var group_var;
7138 TIDSortedElemSet elements;
7139 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7140 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7144 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7145 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7147 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7149 // group of new boundary elements
7150 SMESH_Group* smesh_group = 0;
7151 if ( strlen(groupName) )
7153 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7154 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7155 smesh_group = group_i->GetSmeshGroup();
7159 getEditor().MakeBoundaryMesh( elements,
7160 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7164 toCopyExistingBondary);
7167 smesh_mesh->GetMeshDS()->Modified();
7170 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7172 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7173 if ( mesh_var->_is_nil() )
7174 pyDump << myMesh_i->_this() << ", ";
7176 pyDump << mesh_var << ", ";
7177 if ( group_var->_is_nil() )
7178 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7180 pyDump << group_var << " = ";
7181 pyDump << this << ".MakeBoundaryMesh( "
7183 << "SMESH." << dimName[int(dim)] << ", "
7184 << "'" << groupName << "', "
7185 << "'" << meshName<< "', "
7186 << toCopyElements << ", "
7187 << toCopyExistingBondary << ")";
7189 group = group_var._retn();
7190 return mesh_var._retn();
7192 SMESH_CATCH( SMESH::throwCorbaException );
7193 return SMESH::SMESH_Mesh::_nil();
7196 //================================================================================
7198 * \brief Creates missing boundary elements
7199 * \param dimension - defines type of boundary elements to create
7200 * \param groupName - a name of group to store all boundary elements in,
7201 * "" means not to create the group
7202 * \param meshName - a name of a new mesh, which is a copy of the initial
7203 * mesh + created boundary elements; "" means not to create the new mesh
7204 * \param toCopyAll - if true, the whole initial mesh will be copied into
7205 * the new mesh else only boundary elements will be copied into the new mesh
7206 * \param groups - optional groups of elements to make boundary around
7207 * \param mesh - returns the mesh where elements were added to
7208 * \param group - returns the created group, if any
7209 * \retval long - number of added boundary elements
7211 //================================================================================
7213 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7214 const char* groupName,
7215 const char* meshName,
7216 CORBA::Boolean toCopyAll,
7217 const SMESH::ListOfIDSources& groups,
7218 SMESH::SMESH_Mesh_out mesh,
7219 SMESH::SMESH_Group_out group)
7220 throw (SALOME::SALOME_Exception)
7225 if ( dim > SMESH::BND_1DFROM2D )
7226 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7228 // separate groups belonging to this and other mesh
7229 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7230 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7231 groupsOfThisMesh ->length( groups.length() );
7232 groupsOfOtherMesh->length( groups.length() );
7233 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7234 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7236 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7237 if ( !m->_is_nil() && myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7238 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7240 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7241 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7242 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7244 groupsOfThisMesh->length( nbGroups );
7245 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7250 if ( nbGroupsOfOtherMesh > 0 )
7252 // process groups belonging to another mesh
7253 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7254 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7255 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7256 groupsOfOtherMesh, mesh, group );
7259 SMESH::SMESH_Mesh_var mesh_var;
7260 SMESH::SMESH_Group_var group_var;
7263 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7264 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7268 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7270 /*toCopyGroups=*/false,
7271 /*toKeepIDs=*/true);
7273 mesh_var = makeMesh(meshName);
7275 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7276 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7279 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7280 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7282 // group of boundary elements
7283 SMESH_Group* smesh_group = 0;
7284 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7285 if ( strlen( groupName ))
7287 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7288 group_var = mesh_i->CreateGroup( groupType, groupName );
7289 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7290 smesh_group = group_i->GetSmeshGroup();
7293 TIDSortedElemSet elements;
7295 if ( groups.length() > 0 )
7297 for ( int i = 0; i < nbGroups; ++i )
7300 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7302 SMESH::Bnd_Dimension bdim =
7303 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7304 nbAdded += getEditor().MakeBoundaryMesh( elements,
7305 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7308 /*toCopyElements=*/false,
7309 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7310 /*toAddExistingBondary=*/true,
7311 /*aroundElements=*/true);
7317 nbAdded += getEditor().MakeBoundaryMesh( elements,
7318 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7321 /*toCopyElements=*/false,
7322 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7323 /*toAddExistingBondary=*/true);
7325 tgtMesh->GetMeshDS()->Modified();
7327 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7329 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7330 pyDump << "nbAdded, ";
7331 if ( mesh_var->_is_nil() )
7332 pyDump << myMesh_i->_this() << ", ";
7334 pyDump << mesh_var << ", ";
7335 if ( group_var->_is_nil() )
7336 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7338 pyDump << group_var << " = ";
7339 pyDump << this << ".MakeBoundaryElements( "
7340 << "SMESH." << dimName[int(dim)] << ", "
7341 << "'" << groupName << "', "
7342 << "'" << meshName<< "', "
7343 << toCopyAll << ", "
7346 mesh = mesh_var._retn();
7347 group = group_var._retn();
7350 SMESH_CATCH( SMESH::throwCorbaException );
7354 //================================================================================
7356 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7357 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7358 * plane passing through pairs of points specified by each PolySegment structure.
7359 * If there are several paths connecting a pair of points, the shortest path is
7360 * selected by the module. Position of the cutting plane is defined by the two
7361 * points and an optional vector lying on the plane specified by a PolySegment.
7362 * By default the vector is defined by Mesh module as following. A middle point
7363 * of the two given points is computed. The middle point is projected to the mesh.
7364 * The vector goes from the middle point to the projection point. In case of planar
7365 * mesh, the vector is normal to the mesh.
7366 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7367 * Return the used vector and position of the middle point.
7368 * \param [in] groupName - optional name of a group where created mesh segments will
7371 //================================================================================
7373 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7374 const char* theGroupName)
7375 throw (SALOME::SALOME_Exception)
7377 if ( theSegments.length() == 0 )
7378 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7379 if ( myMesh->NbFaces() == 0 )
7380 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7383 initData(/*deleteSearchers=*/false);
7385 SMESHDS_Group* groupDS = 0;
7386 SMESHDS_Mesh* meshDS = getMeshDS();
7387 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7389 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7390 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7391 while ( faceIt->more() )
7392 tmpMesh->Copy( faceIt->next() );
7393 meshDS = tmpMesh->GetMeshDS();
7395 else if ( theGroupName[0] ) // find/create a group of segments
7397 // SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7398 // while ( !groupDS && grpIt->more() )
7400 // SMESH_Group* group = grpIt->next();
7401 // if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7402 // strcmp( group->GetName(), theGroupName ) == 0 )
7404 // groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7409 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7411 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7412 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7416 // convert input polySegments
7417 SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() );
7418 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7420 SMESH::PolySegment& segIn = theSegments[ i ];
7421 SMESH_MeshAlgos::PolySegment& segOut = segments[ i ];
7422 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7423 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7424 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7425 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7426 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7429 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7432 segOut.myVector.SetCoord( segIn.vector.PS.x,
7434 segIn.vector.PS.z );
7437 // get a static ElementSearcher
7438 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7439 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7440 if ( !theElementSearcher )
7441 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7444 std::vector<const SMDS_MeshElement*> newEdges;
7445 std::vector<const SMDS_MeshNode*> newNodes;
7446 SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes,
7447 groupDS ? &groupDS->SMDSGroup() : 0,
7448 theElementSearcher );
7450 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ).
7452 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ).
7453 assign( newNodes.begin(), newNodes.end() );
7456 if ( myIsPreviewMode )
7458 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7460 SMESH::PolySegment& segOut = theSegments[ i ];
7461 SMESH_MeshAlgos::PolySegment& segIn = segments[ i ];
7462 segOut.vector.PS.x = segIn.myVector.X();
7463 segOut.vector.PS.y = segIn.myVector.Y();
7464 segOut.vector.PS.z = segIn.myVector.Z();
7469 TPythonDump() << "_segments = []";
7470 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7472 SMESH::PolySegment& segIn = theSegments[ i ];
7473 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7474 << segIn.node1ID1 << ", "
7475 << segIn.node1ID2 << ", "
7476 << segIn.node2ID1 << ", "
7477 << segIn.node2ID2 << ", "
7478 << "smeshBuilder.MakeDirStruct( "
7479 << segIn.vector.PS.x << ", "
7480 << segIn.vector.PS.y << ", "
7481 << segIn.vector.PS.z << ")))";
7483 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7486 SMESH_CATCH( SMESH::throwCorbaException );
7490 //================================================================================
7492 * \brief Create a slot of given width around given 1D elements lying on a triangle mesh.
7493 * The slot is consrtucted by cutting faces by cylindrical surfaces made
7494 * around each segment. Segments are expected to be created by MakePolyLine().
7495 * \return Edges located at the slot boundary
7497 //================================================================================
7499 SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments,
7500 CORBA::Double theWidth)
7501 throw (SALOME::SALOME_Exception)
7503 if ( CORBA::is_nil( theSegments ) ||
7504 theSegments->GetType() != SMESH::EDGE )
7505 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7506 if ( myMesh->NbFaces() == 0 )
7507 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7509 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
7512 initData(/*deleteSearchers=*/false);
7514 SMESHDS_Mesh* meshDS = getMeshDS();
7516 std::vector< SMESH_MeshAlgos::Edge > edges =
7517 SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ),
7520 resultEdges->length( edges.size() );
7521 for ( size_t i = 0; i < edges.size(); ++i )
7523 resultEdges[ i ].node1 = edges[i]._node1->GetID();
7524 resultEdges[ i ].node2 = edges[i]._node2->GetID();
7525 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
7529 SMESH_CATCH( SMESH::throwCorbaException );
7531 TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed
7533 return resultEdges._retn();