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();
5623 vector<const SMDS_MeshNode*> aNodes(nbn);
5624 for ( int i = 0; i < nbn; i++ ) {
5625 const SMDS_MeshNode* aNode = getMeshDS()->FindNode( newIDs[ i ]);
5628 aNodes[ i ] = aNode;
5630 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5631 << ide << ", " << newIDs << " )";
5633 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], aNodes.size() );
5635 declareMeshModified( /*isReComputeSafe=*/ !res );
5639 SMESH_CATCH( SMESH::throwCorbaException );
5643 //=======================================================================
5645 * \brief Makes a part of the mesh quadratic or bi-quadratic
5647 //=======================================================================
5649 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5650 CORBA::Boolean theToBiQuad,
5651 SMESH::SMESH_IDSource_ptr theObject)
5652 throw (SALOME::SALOME_Exception)
5657 TIDSortedElemSet elems;
5659 if ( !( elemsOK = CORBA::is_nil( theObject )))
5661 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5662 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5666 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5667 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5669 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5670 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5672 declareMeshModified( /*isReComputeSafe=*/false );
5675 SMESH_CATCH( SMESH::throwCorbaException );
5678 //=======================================================================
5679 //function : ConvertFromQuadratic
5681 //=======================================================================
5683 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5684 throw (SALOME::SALOME_Exception)
5689 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5690 TPythonDump() << this << ".ConvertFromQuadratic()";
5691 declareMeshModified( /*isReComputeSafe=*/!isDone );
5694 SMESH_CATCH( SMESH::throwCorbaException );
5698 //=======================================================================
5699 //function : ConvertToQuadratic
5701 //=======================================================================
5703 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5704 throw (SALOME::SALOME_Exception)
5706 convertToQuadratic( theForce3d, false );
5707 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5710 //================================================================================
5712 * \brief Makes a part of the mesh quadratic
5714 //================================================================================
5716 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5717 SMESH::SMESH_IDSource_ptr theObject)
5718 throw (SALOME::SALOME_Exception)
5720 convertToQuadratic( theForce3d, false, theObject );
5721 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5724 //================================================================================
5726 * \brief Makes a part of the mesh bi-quadratic
5728 //================================================================================
5730 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5731 SMESH::SMESH_IDSource_ptr theObject)
5732 throw (SALOME::SALOME_Exception)
5734 convertToQuadratic( theForce3d, true, theObject );
5735 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5738 //================================================================================
5740 * \brief Makes a part of the mesh linear
5742 //================================================================================
5744 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5745 throw (SALOME::SALOME_Exception)
5752 TIDSortedElemSet elems;
5753 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5755 if ( elems.empty() )
5757 ConvertFromQuadratic();
5759 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5761 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5765 getEditor().ConvertFromQuadratic(elems);
5768 declareMeshModified( /*isReComputeSafe=*/false );
5770 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5772 SMESH_CATCH( SMESH::throwCorbaException );
5775 //=======================================================================
5776 //function : makeMesh
5777 //purpose : create a named imported mesh
5778 //=======================================================================
5780 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5782 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5783 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5784 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5785 gen->SetName( meshSO, theMeshName, "Mesh" );
5786 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5788 return mesh._retn();
5791 //=======================================================================
5792 //function : dumpGroupsList
5794 //=======================================================================
5796 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5797 const SMESH::ListOfGroups * theGroupList)
5799 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5800 if ( isDumpGroupList )
5801 theDumpPython << theGroupList << " = ";
5804 //================================================================================
5806 \brief Generates the unique group name.
5807 \param thePrefix name prefix
5810 //================================================================================
5812 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5814 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5815 set<std::string> groupNames;
5817 // Get existing group names
5818 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5819 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5820 if (CORBA::is_nil(aGroup))
5823 CORBA::String_var name = aGroup->GetName();
5824 groupNames.insert( name.in() );
5828 std::string name = thePrefix;
5831 while (!groupNames.insert(name).second)
5832 name = SMESH_Comment( thePrefix ) << "_" << index++;
5837 //================================================================================
5839 * \brief Prepare SMESH_IDSource for work
5841 //================================================================================
5843 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5845 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5847 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5848 filter->SetMesh( mesh );
5851 //================================================================================
5853 * \brief Retrieve elements of given type from SMESH_IDSource
5855 //================================================================================
5857 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5858 const SMESHDS_Mesh* theMeshDS,
5859 TIDSortedElemSet& theElemSet,
5860 const SMDSAbs_ElementType theType,
5861 const bool emptyIfIsMesh,
5862 IDSource_Error* error)
5865 if ( error ) *error = IDSource_OK;
5867 if ( CORBA::is_nil( theIDSource ))
5869 if ( error ) *error = IDSource_INVALID;
5872 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5874 if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
5875 *error = IDSource_EMPTY;
5878 if ( getMeshDS() == theMeshDS ) // check if theIDSource belongs to myMesh
5880 SMESH::SMESH_Mesh_var mesh = theIDSource->GetMesh();
5881 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5882 if ( mesh_i && mesh_i != myMesh_i )
5885 *error = IDSource_INVALID;
5889 prepareIdSource( theIDSource );
5890 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5891 if ( anIDs->length() == 0 )
5893 if ( error ) *error = IDSource_EMPTY;
5896 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5897 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5899 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5901 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5905 if ( error ) *error = IDSource_INVALID;
5911 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5912 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5914 if ( error ) *error = IDSource_INVALID;
5921 //================================================================================
5923 * \brief Duplicates given elements, i.e. creates new elements based on the
5924 * same nodes as the given ones.
5925 * \param theElements - container of elements to duplicate.
5926 * \param theGroupName - a name of group to contain the generated elements.
5927 * If a group with such a name already exists, the new elements
5928 * are added to the existing group, else a new group is created.
5929 * If \a theGroupName is empty, new elements are not added
5931 * \return a group where the new elements are added. NULL if theGroupName == "".
5934 //================================================================================
5936 SMESH::SMESH_Group_ptr
5937 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5938 const char* theGroupName)
5939 throw (SALOME::SALOME_Exception)
5941 SMESH::SMESH_Group_var newGroup;
5948 TIDSortedElemSet elems;
5949 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5951 getEditor().DoubleElements( elems );
5953 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5956 SMESH::ElementType type =
5957 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5958 // find existing group
5959 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5960 for ( size_t i = 0; i < groups->length(); ++i )
5961 if ( groups[i]->GetType() == type )
5963 CORBA::String_var name = groups[i]->GetName();
5964 if ( strcmp( name, theGroupName ) == 0 ) {
5965 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5969 // create a new group
5970 if ( newGroup->_is_nil() )
5971 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5973 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5975 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5976 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5977 for ( size_t i = 0; i < aSeq.size(); i++ )
5978 groupDS->SMDSGroup().Add( aSeq[i] );
5983 if ( !newGroup->_is_nil() )
5984 pyDump << newGroup << " = ";
5985 pyDump << this << ".DoubleElements( "
5986 << theElements << ", " << "'" << theGroupName <<"')";
5988 SMESH_CATCH( SMESH::throwCorbaException );
5990 return newGroup._retn();
5993 //================================================================================
5995 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5996 \param theNodes - identifiers of nodes to be doubled
5997 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5998 nodes. If list of element identifiers is empty then nodes are doubled but
5999 they not assigned to elements
6000 \return TRUE if operation has been completed successfully, FALSE otherwise
6001 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
6003 //================================================================================
6005 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
6006 const SMESH::long_array& theModifiedElems )
6007 throw (SALOME::SALOME_Exception)
6012 list< int > aListOfNodes;
6014 for ( i = 0, n = theNodes.length(); i < n; i++ )
6015 aListOfNodes.push_back( theNodes[ i ] );
6017 list< int > aListOfElems;
6018 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6019 aListOfElems.push_back( theModifiedElems[ i ] );
6021 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
6023 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6025 // Update Python script
6026 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
6030 SMESH_CATCH( SMESH::throwCorbaException );
6034 //================================================================================
6036 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6037 This method provided for convenience works as DoubleNodes() described above.
6038 \param theNodeId - identifier of node to be doubled.
6039 \param theModifiedElems - identifiers of elements to be updated.
6040 \return TRUE if operation has been completed successfully, FALSE otherwise
6041 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
6043 //================================================================================
6045 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
6046 const SMESH::long_array& theModifiedElems )
6047 throw (SALOME::SALOME_Exception)
6050 SMESH::long_array_var aNodes = new SMESH::long_array;
6051 aNodes->length( 1 );
6052 aNodes[ 0 ] = theNodeId;
6054 TPythonDump pyDump; // suppress dump by the next line
6056 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
6058 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
6062 SMESH_CATCH( SMESH::throwCorbaException );
6066 //================================================================================
6068 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6069 This method provided for convenience works as DoubleNodes() described above.
6070 \param theNodes - group of nodes to be doubled.
6071 \param theModifiedElems - group of elements to be updated.
6072 \return TRUE if operation has been completed successfully, FALSE otherwise
6073 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
6075 //================================================================================
6077 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
6078 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6079 throw (SALOME::SALOME_Exception)
6082 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6085 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6086 SMESH::long_array_var aModifiedElems;
6087 if ( !CORBA::is_nil( theModifiedElems ) )
6088 aModifiedElems = theModifiedElems->GetListOfID();
6090 aModifiedElems = new SMESH::long_array;
6092 TPythonDump pyDump; // suppress dump by the next line
6094 bool done = DoubleNodes( aNodes, aModifiedElems );
6096 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6100 SMESH_CATCH( SMESH::throwCorbaException );
6104 //================================================================================
6106 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6107 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6108 * \param theNodes - group of nodes to be doubled.
6109 * \param theModifiedElems - group of elements to be updated.
6110 * \return a new group with newly created nodes
6111 * \sa DoubleNodeGroup()
6113 //================================================================================
6115 SMESH::SMESH_Group_ptr
6116 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6117 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6118 throw (SALOME::SALOME_Exception)
6121 SMESH::SMESH_Group_var aNewGroup;
6123 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6124 return aNewGroup._retn();
6127 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6128 SMESH::long_array_var aModifiedElems;
6129 if ( !CORBA::is_nil( theModifiedElems ) )
6130 aModifiedElems = theModifiedElems->GetListOfID();
6132 aModifiedElems = new SMESH::long_array;
6133 aModifiedElems->length( 0 );
6136 TPythonDump pyDump; // suppress dump by the next line
6138 bool aResult = DoubleNodes( aNodes, aModifiedElems );
6141 // Create group with newly created nodes
6142 SMESH::long_array_var anIds = GetLastCreatedNodes();
6143 if (anIds->length() > 0) {
6144 std::string anUnindexedName (theNodes->GetName());
6145 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6146 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6147 aNewGroup->Add(anIds);
6148 pyDump << aNewGroup << " = ";
6152 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6153 << theModifiedElems << " )";
6155 return aNewGroup._retn();
6157 SMESH_CATCH( SMESH::throwCorbaException );
6161 //================================================================================
6163 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6164 This method provided for convenience works as DoubleNodes() described above.
6165 \param theNodes - list of groups of nodes to be doubled
6166 \param theModifiedElems - list of groups of elements to be updated.
6167 \return TRUE if operation has been completed successfully, FALSE otherwise
6168 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6170 //================================================================================
6172 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6173 const SMESH::ListOfGroups& theModifiedElems )
6174 throw (SALOME::SALOME_Exception)
6179 std::list< int > aNodes;
6181 for ( i = 0, n = theNodes.length(); i < n; i++ )
6183 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6184 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6186 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6187 for ( j = 0, m = aCurr->length(); j < m; j++ )
6188 aNodes.push_back( aCurr[ j ] );
6192 std::list< int > anElems;
6193 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6195 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6196 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6198 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6199 for ( j = 0, m = aCurr->length(); j < m; j++ )
6200 anElems.push_back( aCurr[ j ] );
6204 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6206 declareMeshModified( /*isReComputeSafe=*/false );
6208 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6212 SMESH_CATCH( SMESH::throwCorbaException );
6216 //================================================================================
6218 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6219 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6220 * \param theNodes - group of nodes to be doubled.
6221 * \param theModifiedElems - group of elements to be updated.
6222 * \return a new group with newly created nodes
6223 * \sa DoubleNodeGroups()
6225 //================================================================================
6227 SMESH::SMESH_Group_ptr
6228 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6229 const SMESH::ListOfGroups& theModifiedElems )
6230 throw (SALOME::SALOME_Exception)
6232 SMESH::SMESH_Group_var aNewGroup;
6234 TPythonDump pyDump; // suppress dump by the next line
6236 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6240 // Create group with newly created nodes
6241 SMESH::long_array_var anIds = GetLastCreatedNodes();
6242 if (anIds->length() > 0) {
6243 std::string anUnindexedName (theNodes[0]->GetName());
6244 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6245 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6246 aNewGroup->Add(anIds);
6247 pyDump << aNewGroup << " = ";
6251 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6252 << theModifiedElems << " )";
6254 return aNewGroup._retn();
6258 //================================================================================
6260 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6261 \param theElems - the list of elements (edges or faces) to be replicated
6262 The nodes for duplication could be found from these elements
6263 \param theNodesNot - list of nodes to NOT replicate
6264 \param theAffectedElems - the list of elements (cells and edges) to which the
6265 replicated nodes should be associated to.
6266 \return TRUE if operation has been completed successfully, FALSE otherwise
6267 \sa DoubleNodeGroup(), DoubleNodeGroups()
6269 //================================================================================
6271 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6272 const SMESH::long_array& theNodesNot,
6273 const SMESH::long_array& theAffectedElems )
6274 throw (SALOME::SALOME_Exception)
6279 SMESHDS_Mesh* aMeshDS = getMeshDS();
6280 TIDSortedElemSet anElems, aNodes, anAffected;
6281 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6282 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6283 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6285 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6287 // Update Python script
6288 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6289 << theNodesNot << ", " << theAffectedElems << " )";
6291 declareMeshModified( /*isReComputeSafe=*/false );
6294 SMESH_CATCH( SMESH::throwCorbaException );
6298 //================================================================================
6300 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6301 \param theElems - the list of elements (edges or faces) to be replicated
6302 The nodes for duplication could be found from these elements
6303 \param theNodesNot - list of nodes to NOT replicate
6304 \param theShape - shape to detect affected elements (element which geometric center
6305 located on or inside shape).
6306 The replicated nodes should be associated to affected elements.
6307 \return TRUE if operation has been completed successfully, FALSE otherwise
6308 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6310 //================================================================================
6312 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6313 const SMESH::long_array& theNodesNot,
6314 GEOM::GEOM_Object_ptr theShape )
6315 throw (SALOME::SALOME_Exception)
6321 SMESHDS_Mesh* aMeshDS = getMeshDS();
6322 TIDSortedElemSet anElems, aNodes;
6323 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6324 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6326 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6327 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6329 // Update Python script
6330 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6331 << theNodesNot << ", " << theShape << " )";
6333 declareMeshModified( /*isReComputeSafe=*/false );
6336 SMESH_CATCH( SMESH::throwCorbaException );
6340 //================================================================================
6342 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6343 \param theElems - group of of elements (edges or faces) to be replicated
6344 \param theNodesNot - group of nodes not to replicated
6345 \param theAffectedElems - group of elements to which the replicated nodes
6346 should be associated to.
6347 \return TRUE if operation has been completed successfully, FALSE otherwise
6348 \sa DoubleNodes(), DoubleNodeGroups()
6350 //================================================================================
6353 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6354 SMESH::SMESH_GroupBase_ptr theNodesNot,
6355 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6356 throw (SALOME::SALOME_Exception)
6359 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6365 SMESHDS_Mesh* aMeshDS = getMeshDS();
6366 TIDSortedElemSet anElems, aNodes, anAffected;
6367 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6368 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6369 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6371 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6373 // Update Python script
6374 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6375 << theNodesNot << ", " << theAffectedElems << " )";
6377 declareMeshModified( /*isReComputeSafe=*/false );
6380 SMESH_CATCH( SMESH::throwCorbaException );
6384 //================================================================================
6386 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6387 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6388 * \param theElems - group of of elements (edges or faces) to be replicated
6389 * \param theNodesNot - group of nodes not to replicated
6390 * \param theAffectedElems - group of elements to which the replicated nodes
6391 * should be associated to.
6392 * \return a new group with newly created elements
6393 * \sa DoubleNodeElemGroup()
6395 //================================================================================
6397 SMESH::SMESH_Group_ptr
6398 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6399 SMESH::SMESH_GroupBase_ptr theNodesNot,
6400 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6401 throw (SALOME::SALOME_Exception)
6404 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6408 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6409 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6411 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6413 << theNodesNot << ", "
6414 << theAffectedElems << " )";
6416 return elemGroup._retn();
6419 //================================================================================
6421 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6422 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6423 * \param theElems - group of of elements (edges or faces) to be replicated
6424 * \param theNodesNot - group of nodes not to replicated
6425 * \param theAffectedElems - group of elements to which the replicated nodes
6426 * should be associated to.
6427 * \return a new group with newly created elements
6428 * \sa DoubleNodeElemGroup()
6430 //================================================================================
6432 SMESH::ListOfGroups*
6433 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6434 SMESH::SMESH_GroupBase_ptr theNodesNot,
6435 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6436 CORBA::Boolean theElemGroupNeeded,
6437 CORBA::Boolean theNodeGroupNeeded)
6438 throw (SALOME::SALOME_Exception)
6441 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6442 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6443 aTwoGroups->length( 2 );
6445 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6446 return aTwoGroups._retn();
6451 SMESHDS_Mesh* aMeshDS = getMeshDS();
6452 TIDSortedElemSet anElems, aNodes, anAffected;
6453 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6454 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6455 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6458 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6460 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6466 // Create group with newly created elements
6467 CORBA::String_var elemGroupName = theElems->GetName();
6468 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6469 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6471 SMESH::long_array_var anIds = GetLastCreatedElems();
6472 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6473 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6474 aNewElemGroup->Add(anIds);
6476 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6478 SMESH::long_array_var anIds = GetLastCreatedNodes();
6479 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6480 aNewNodeGroup->Add(anIds);
6484 // Update Python script
6487 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6488 else pyDump << aNewElemGroup << ", ";
6489 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6490 else pyDump << aNewNodeGroup << " ] = ";
6492 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6493 << theNodesNot << ", "
6494 << theAffectedElems << ", "
6495 << theElemGroupNeeded << ", "
6496 << theNodeGroupNeeded <<" )";
6498 aTwoGroups[0] = aNewElemGroup._retn();
6499 aTwoGroups[1] = aNewNodeGroup._retn();
6500 return aTwoGroups._retn();
6502 SMESH_CATCH( SMESH::throwCorbaException );
6506 //================================================================================
6508 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6509 \param theElems - group of of elements (edges or faces) to be replicated
6510 \param theNodesNot - group of nodes not to replicated
6511 \param theShape - shape to detect affected elements (element which geometric center
6512 located on or inside shape).
6513 The replicated nodes should be associated to affected elements.
6514 \return TRUE if operation has been completed successfully, FALSE otherwise
6515 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6517 //================================================================================
6520 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6521 SMESH::SMESH_GroupBase_ptr theNodesNot,
6522 GEOM::GEOM_Object_ptr theShape )
6523 throw (SALOME::SALOME_Exception)
6526 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6532 SMESHDS_Mesh* aMeshDS = getMeshDS();
6533 TIDSortedElemSet anElems, aNodes, anAffected;
6534 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6535 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6537 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6538 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6541 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6543 // Update Python script
6544 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6545 << theNodesNot << ", " << theShape << " )";
6548 SMESH_CATCH( SMESH::throwCorbaException );
6552 //================================================================================
6554 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6555 * \param [in] theGrpList - groups
6556 * \param [in] theMeshDS - mesh
6557 * \param [out] theElemSet - set of elements
6558 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6560 //================================================================================
6562 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6563 SMESHDS_Mesh* theMeshDS,
6564 TIDSortedElemSet& theElemSet,
6565 const bool theIsNodeGrp)
6567 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6569 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6570 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6571 : aGrp->GetType() != SMESH::NODE ) )
6573 SMESH::long_array_var anIDs = aGrp->GetIDs();
6574 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6579 //================================================================================
6581 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6582 This method provided for convenience works as DoubleNodes() described above.
6583 \param theElems - list of groups of elements (edges or faces) to be replicated
6584 \param theNodesNot - list of groups of nodes not to replicated
6585 \param theAffectedElems - group of elements to which the replicated nodes
6586 should be associated to.
6587 \return TRUE if operation has been completed successfully, FALSE otherwise
6588 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6590 //================================================================================
6593 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6594 const SMESH::ListOfGroups& theNodesNot,
6595 const SMESH::ListOfGroups& theAffectedElems)
6596 throw (SALOME::SALOME_Exception)
6602 SMESHDS_Mesh* aMeshDS = getMeshDS();
6603 TIDSortedElemSet anElems, aNodes, anAffected;
6604 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6605 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6606 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6608 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6610 // Update Python script
6611 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6612 << &theNodesNot << ", " << &theAffectedElems << " )";
6614 declareMeshModified( /*isReComputeSafe=*/false );
6617 SMESH_CATCH( SMESH::throwCorbaException );
6621 //================================================================================
6623 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6624 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6625 \param theElems - list of groups of elements (edges or faces) to be replicated
6626 \param theNodesNot - list of groups of nodes not to replicated
6627 \param theAffectedElems - group of elements to which the replicated nodes
6628 should be associated to.
6629 * \return a new group with newly created elements
6630 * \sa DoubleNodeElemGroups()
6632 //================================================================================
6634 SMESH::SMESH_Group_ptr
6635 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6636 const SMESH::ListOfGroups& theNodesNot,
6637 const SMESH::ListOfGroups& theAffectedElems)
6638 throw (SALOME::SALOME_Exception)
6641 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6645 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6646 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6648 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6650 << theNodesNot << ", "
6651 << theAffectedElems << " )";
6653 return elemGroup._retn();
6656 //================================================================================
6658 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6659 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6660 \param theElems - list of groups of elements (edges or faces) to be replicated
6661 \param theNodesNot - list of groups of nodes not to replicated
6662 \param theAffectedElems - group of elements to which the replicated nodes
6663 should be associated to.
6664 * \return a new group with newly created elements
6665 * \sa DoubleNodeElemGroups()
6667 //================================================================================
6669 SMESH::ListOfGroups*
6670 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6671 const SMESH::ListOfGroups& theNodesNot,
6672 const SMESH::ListOfGroups& theAffectedElems,
6673 CORBA::Boolean theElemGroupNeeded,
6674 CORBA::Boolean theNodeGroupNeeded)
6675 throw (SALOME::SALOME_Exception)
6678 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6679 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6680 aTwoGroups->length( 2 );
6685 SMESHDS_Mesh* aMeshDS = getMeshDS();
6686 TIDSortedElemSet anElems, aNodes, anAffected;
6687 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6688 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6689 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6691 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6693 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6698 // Create group with newly created elements
6699 CORBA::String_var elemGroupName = theElems[0]->GetName();
6700 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6701 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6703 SMESH::long_array_var anIds = GetLastCreatedElems();
6704 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6705 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6706 aNewElemGroup->Add(anIds);
6708 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6710 SMESH::long_array_var anIds = GetLastCreatedNodes();
6711 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6712 aNewNodeGroup->Add(anIds);
6716 // Update Python script
6719 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6720 else pyDump << aNewElemGroup << ", ";
6721 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6722 else pyDump << aNewNodeGroup << " ] = ";
6724 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6725 << &theNodesNot << ", "
6726 << &theAffectedElems << ", "
6727 << theElemGroupNeeded << ", "
6728 << theNodeGroupNeeded << " )";
6730 aTwoGroups[0] = aNewElemGroup._retn();
6731 aTwoGroups[1] = aNewNodeGroup._retn();
6732 return aTwoGroups._retn();
6734 SMESH_CATCH( SMESH::throwCorbaException );
6738 //================================================================================
6740 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6741 This method provided for convenience works as DoubleNodes() described above.
6742 \param theElems - list of groups of elements (edges or faces) to be replicated
6743 \param theNodesNot - list of groups of nodes not to replicated
6744 \param theShape - shape to detect affected elements (element which geometric center
6745 located on or inside shape).
6746 The replicated nodes should be associated to affected elements.
6747 \return TRUE if operation has been completed successfully, FALSE otherwise
6748 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6750 //================================================================================
6753 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6754 const SMESH::ListOfGroups& theNodesNot,
6755 GEOM::GEOM_Object_ptr theShape )
6756 throw (SALOME::SALOME_Exception)
6762 SMESHDS_Mesh* aMeshDS = getMeshDS();
6763 TIDSortedElemSet anElems, aNodes;
6764 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6765 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6767 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6768 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6770 // Update Python script
6771 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6772 << &theNodesNot << ", " << theShape << " )";
6774 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6777 SMESH_CATCH( SMESH::throwCorbaException );
6781 //================================================================================
6783 \brief Identify the elements that will be affected by node duplication (actual
6784 duplication is not performed.
6785 This method is the first step of DoubleNodeElemGroupsInRegion.
6786 \param theElems - list of groups of elements (edges or faces) to be replicated
6787 \param theNodesNot - list of groups of nodes not to replicated
6788 \param theShape - shape to detect affected elements (element which geometric center
6789 located on or inside shape).
6790 The replicated nodes should be associated to affected elements.
6791 \return groups of affected elements
6792 \sa DoubleNodeElemGroupsInRegion()
6794 //================================================================================
6795 SMESH::ListOfGroups*
6796 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6797 const SMESH::ListOfGroups& theNodesNot,
6798 GEOM::GEOM_Object_ptr theShape )
6799 throw (SALOME::SALOME_Exception)
6802 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6803 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6804 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6805 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6809 ::SMESH_MeshEditor aMeshEditor(myMesh);
6811 SMESHDS_Mesh* aMeshDS = getMeshDS();
6812 TIDSortedElemSet anElems, aNodes;
6813 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6814 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6815 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6817 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6818 TIDSortedElemSet anAffected;
6819 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6821 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6824 if ( aResult && anAffected.size() > 0 )
6826 SMESH::long_array_var volumeIds = new SMESH::long_array;
6827 SMESH::long_array_var faceIds = new SMESH::long_array;
6828 SMESH::long_array_var edgeIds = new SMESH::long_array;
6829 volumeIds->length( anAffected.size() );
6830 faceIds ->length( anAffected.size() );
6831 edgeIds ->length( anAffected.size() );
6836 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6837 for (; eIt != anAffected.end(); ++eIt)
6839 const SMDS_MeshElement* anElem = *eIt;
6840 int elemId = anElem->GetID();
6841 switch ( anElem->GetType() ) {
6842 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6843 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6844 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6848 volumeIds->length(ivol);
6849 faceIds->length(iface);
6850 edgeIds->length(iedge);
6855 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6856 GenerateGroupName("affectedVolumes").c_str());
6857 aNewVolumeGroup->Add(volumeIds);
6858 aListOfGroups->length( nbGroups+1 );
6859 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6863 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6864 GenerateGroupName("affectedFaces").c_str());
6865 aNewFaceGroup->Add(faceIds);
6866 aListOfGroups->length( nbGroups+1 );
6867 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6871 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6872 GenerateGroupName("affectedEdges").c_str());
6873 aNewEdgeGroup->Add(edgeIds);
6874 aListOfGroups->length( nbGroups+1 );
6875 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6879 // Update Python script
6881 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6882 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6884 return aListOfGroups._retn();
6886 SMESH_CATCH( SMESH::throwCorbaException );
6890 //================================================================================
6892 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6893 The created 2D mesh elements based on nodes of free faces of boundary volumes
6894 \return TRUE if operation has been completed successfully, FALSE otherwise
6896 //================================================================================
6898 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6899 throw (SALOME::SALOME_Exception)
6904 bool aResult = getEditor().Make2DMeshFrom3D();
6906 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6908 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6911 SMESH_CATCH( SMESH::throwCorbaException );
6915 //================================================================================
6917 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6918 * The list of groups must contain at least two groups. The groups have to be disjoint:
6919 * no common element into two different groups.
6920 * The nodes of the internal faces at the boundaries of the groups are doubled.
6921 * Optionally, the internal faces are replaced by flat elements.
6922 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6923 * The flat elements are stored in groups of volumes.
6924 * These groups are named according to the position of the group in the list:
6925 * 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.
6926 * 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.
6927 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6928 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6929 * \param theDomains - list of groups of volumes
6930 * \param createJointElems - if TRUE, create the elements
6931 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6932 * the boundary between \a theDomains and the rest mesh
6933 * \return TRUE if operation has been completed successfully, FALSE otherwise
6935 //================================================================================
6938 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6939 CORBA::Boolean createJointElems,
6940 CORBA::Boolean onAllBoundaries )
6941 throw (SALOME::SALOME_Exception)
6948 SMESHDS_Mesh* aMeshDS = getMeshDS();
6950 // MESSAGE("theDomains.length = "<<theDomains.length());
6951 if ( theDomains.length() <= 1 && !onAllBoundaries )
6952 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6954 vector<TIDSortedElemSet> domains;
6955 domains.resize( theDomains.length() );
6957 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6959 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6960 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6962 // if ( aGrp->GetType() != SMESH::VOLUME )
6963 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6964 SMESH::long_array_var anIDs = aGrp->GetIDs();
6965 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6969 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6970 // TODO publish the groups of flat elements in study
6972 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6974 // Update Python script
6975 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6976 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6978 SMESH_CATCH( SMESH::throwCorbaException );
6980 myMesh_i->CreateGroupServants(); // publish created groups if any
6985 //================================================================================
6987 * \brief Double nodes on some external faces and create flat elements.
6988 * Flat elements are mainly used by some types of mechanic calculations.
6990 * Each group of the list must be constituted of faces.
6991 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6992 * @param theGroupsOfFaces - list of groups of faces
6993 * @return TRUE if operation has been completed successfully, FALSE otherwise
6995 //================================================================================
6998 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6999 throw (SALOME::SALOME_Exception)
7004 SMESHDS_Mesh* aMeshDS = getMeshDS();
7006 vector<TIDSortedElemSet> faceGroups;
7009 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
7011 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
7012 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
7014 TIDSortedElemSet faceGroup;
7016 faceGroups.push_back(faceGroup);
7017 SMESH::long_array_var anIDs = aGrp->GetIDs();
7018 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
7022 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
7023 // TODO publish the groups of flat elements in study
7025 declareMeshModified( /*isReComputeSafe=*/ !aResult );
7027 // Update Python script
7028 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
7031 SMESH_CATCH( SMESH::throwCorbaException );
7035 //================================================================================
7037 * \brief Identify all the elements around a geom shape, get the faces delimiting
7040 * Build groups of volume to remove, groups of faces to replace on the skin of the
7041 * object, groups of faces to remove inside the object, (idem edges).
7042 * Build ordered list of nodes at the border of each group of faces to replace
7043 * (to be used to build a geom subshape).
7045 //================================================================================
7047 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
7048 GEOM::GEOM_Object_ptr theShape,
7049 const char* groupName,
7050 const SMESH::double_array& theNodesCoords,
7051 SMESH::array_of_long_array_out GroupsOfNodes)
7052 throw (SALOME::SALOME_Exception)
7057 std::vector<std::vector<int> > aListOfListOfNodes;
7058 ::SMESH_MeshEditor aMeshEditor( myMesh );
7060 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
7061 if ( !theNodeSearcher )
7062 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
7064 vector<double> nodesCoords;
7065 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
7067 nodesCoords.push_back( theNodesCoords[i] );
7070 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
7071 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
7072 nodesCoords, aListOfListOfNodes);
7074 GroupsOfNodes = new SMESH::array_of_long_array;
7075 GroupsOfNodes->length( aListOfListOfNodes.size() );
7076 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
7077 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
7079 vector<int>& aListOfNodes = *llIt;
7080 vector<int>::iterator lIt = aListOfNodes.begin();;
7081 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
7082 aGroup.length( aListOfNodes.size() );
7083 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
7084 aGroup[ j ] = (*lIt);
7086 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
7089 << ", '" << groupName << "', "
7090 << theNodesCoords << " )";
7092 SMESH_CATCH( SMESH::throwCorbaException );
7095 // issue 20749 ===================================================================
7097 * \brief Creates missing boundary elements
7098 * \param elements - elements whose boundary is to be checked
7099 * \param dimension - defines type of boundary elements to create
7100 * \param groupName - a name of group to store created boundary elements in,
7101 * "" means not to create the group
7102 * \param meshName - a name of new mesh to store created boundary elements in,
7103 * "" means not to create the new mesh
7104 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
7105 * \param toCopyExistingBondary - if true, not only new but also pre-existing
7106 * boundary elements will be copied into the new mesh
7107 * \param group - returns the create group, if any
7108 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7110 // ================================================================================
7112 SMESH::SMESH_Mesh_ptr
7113 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7114 SMESH::Bnd_Dimension dim,
7115 const char* groupName,
7116 const char* meshName,
7117 CORBA::Boolean toCopyElements,
7118 CORBA::Boolean toCopyExistingBondary,
7119 SMESH::SMESH_Group_out group)
7120 throw (SALOME::SALOME_Exception)
7125 if ( dim > SMESH::BND_1DFROM2D )
7126 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7128 SMESHDS_Mesh* aMeshDS = getMeshDS();
7130 SMESH::SMESH_Mesh_var mesh_var;
7131 SMESH::SMESH_Group_var group_var;
7135 TIDSortedElemSet elements;
7136 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7137 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7141 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7142 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7144 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7146 // group of new boundary elements
7147 SMESH_Group* smesh_group = 0;
7148 if ( strlen(groupName) )
7150 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7151 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7152 smesh_group = group_i->GetSmeshGroup();
7156 getEditor().MakeBoundaryMesh( elements,
7157 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7161 toCopyExistingBondary);
7164 smesh_mesh->GetMeshDS()->Modified();
7167 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7169 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7170 if ( mesh_var->_is_nil() )
7171 pyDump << myMesh_i->_this() << ", ";
7173 pyDump << mesh_var << ", ";
7174 if ( group_var->_is_nil() )
7175 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7177 pyDump << group_var << " = ";
7178 pyDump << this << ".MakeBoundaryMesh( "
7180 << "SMESH." << dimName[int(dim)] << ", "
7181 << "'" << groupName << "', "
7182 << "'" << meshName<< "', "
7183 << toCopyElements << ", "
7184 << toCopyExistingBondary << ")";
7186 group = group_var._retn();
7187 return mesh_var._retn();
7189 SMESH_CATCH( SMESH::throwCorbaException );
7190 return SMESH::SMESH_Mesh::_nil();
7193 //================================================================================
7195 * \brief Creates missing boundary elements
7196 * \param dimension - defines type of boundary elements to create
7197 * \param groupName - a name of group to store all boundary elements in,
7198 * "" means not to create the group
7199 * \param meshName - a name of a new mesh, which is a copy of the initial
7200 * mesh + created boundary elements; "" means not to create the new mesh
7201 * \param toCopyAll - if true, the whole initial mesh will be copied into
7202 * the new mesh else only boundary elements will be copied into the new mesh
7203 * \param groups - optional groups of elements to make boundary around
7204 * \param mesh - returns the mesh where elements were added to
7205 * \param group - returns the created group, if any
7206 * \retval long - number of added boundary elements
7208 //================================================================================
7210 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7211 const char* groupName,
7212 const char* meshName,
7213 CORBA::Boolean toCopyAll,
7214 const SMESH::ListOfIDSources& groups,
7215 SMESH::SMESH_Mesh_out mesh,
7216 SMESH::SMESH_Group_out group)
7217 throw (SALOME::SALOME_Exception)
7222 if ( dim > SMESH::BND_1DFROM2D )
7223 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7225 // separate groups belonging to this and other mesh
7226 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7227 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7228 groupsOfThisMesh ->length( groups.length() );
7229 groupsOfOtherMesh->length( groups.length() );
7230 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7231 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7233 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7234 if ( !m->_is_nil() && myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7235 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7237 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7238 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7239 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7241 groupsOfThisMesh->length( nbGroups );
7242 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7247 if ( nbGroupsOfOtherMesh > 0 )
7249 // process groups belonging to another mesh
7250 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7251 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7252 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7253 groupsOfOtherMesh, mesh, group );
7256 SMESH::SMESH_Mesh_var mesh_var;
7257 SMESH::SMESH_Group_var group_var;
7260 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7261 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7265 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7267 /*toCopyGroups=*/false,
7268 /*toKeepIDs=*/true);
7270 mesh_var = makeMesh(meshName);
7272 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7273 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7276 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7277 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7279 // group of boundary elements
7280 SMESH_Group* smesh_group = 0;
7281 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7282 if ( strlen( groupName ))
7284 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7285 group_var = mesh_i->CreateGroup( groupType, groupName );
7286 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7287 smesh_group = group_i->GetSmeshGroup();
7290 TIDSortedElemSet elements;
7292 if ( groups.length() > 0 )
7294 for ( int i = 0; i < nbGroups; ++i )
7297 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7299 SMESH::Bnd_Dimension bdim =
7300 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7301 nbAdded += getEditor().MakeBoundaryMesh( elements,
7302 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7305 /*toCopyElements=*/false,
7306 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7307 /*toAddExistingBondary=*/true,
7308 /*aroundElements=*/true);
7314 nbAdded += getEditor().MakeBoundaryMesh( elements,
7315 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7318 /*toCopyElements=*/false,
7319 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7320 /*toAddExistingBondary=*/true);
7322 tgtMesh->GetMeshDS()->Modified();
7324 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7326 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7327 pyDump << "nbAdded, ";
7328 if ( mesh_var->_is_nil() )
7329 pyDump << myMesh_i->_this() << ", ";
7331 pyDump << mesh_var << ", ";
7332 if ( group_var->_is_nil() )
7333 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7335 pyDump << group_var << " = ";
7336 pyDump << this << ".MakeBoundaryElements( "
7337 << "SMESH." << dimName[int(dim)] << ", "
7338 << "'" << groupName << "', "
7339 << "'" << meshName<< "', "
7340 << toCopyAll << ", "
7343 mesh = mesh_var._retn();
7344 group = group_var._retn();
7347 SMESH_CATCH( SMESH::throwCorbaException );
7351 //================================================================================
7353 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7354 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7355 * plane passing through pairs of points specified by each PolySegment structure.
7356 * If there are several paths connecting a pair of points, the shortest path is
7357 * selected by the module. Position of the cutting plane is defined by the two
7358 * points and an optional vector lying on the plane specified by a PolySegment.
7359 * By default the vector is defined by Mesh module as following. A middle point
7360 * of the two given points is computed. The middle point is projected to the mesh.
7361 * The vector goes from the middle point to the projection point. In case of planar
7362 * mesh, the vector is normal to the mesh.
7363 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7364 * Return the used vector and position of the middle point.
7365 * \param [in] groupName - optional name of a group where created mesh segments will
7368 //================================================================================
7370 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7371 const char* theGroupName)
7372 throw (SALOME::SALOME_Exception)
7374 if ( theSegments.length() == 0 )
7375 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7376 if ( myMesh->NbFaces() == 0 )
7377 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7380 initData(/*deleteSearchers=*/false);
7382 SMESHDS_Group* groupDS = 0;
7383 SMESHDS_Mesh* meshDS = getMeshDS();
7384 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7386 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7387 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7388 while ( faceIt->more() )
7389 tmpMesh->Copy( faceIt->next() );
7390 meshDS = tmpMesh->GetMeshDS();
7392 else if ( theGroupName[0] ) // find/create a group of segments
7394 // SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7395 // while ( !groupDS && grpIt->more() )
7397 // SMESH_Group* group = grpIt->next();
7398 // if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7399 // strcmp( group->GetName(), theGroupName ) == 0 )
7401 // groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7406 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7408 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7409 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7413 // convert input polySegments
7414 SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() );
7415 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7417 SMESH::PolySegment& segIn = theSegments[ i ];
7418 SMESH_MeshAlgos::PolySegment& segOut = segments[ i ];
7419 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7420 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7421 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7422 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7423 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7426 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7429 segOut.myVector.SetCoord( segIn.vector.PS.x,
7431 segIn.vector.PS.z );
7434 // get a static ElementSearcher
7435 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7436 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7437 if ( !theElementSearcher )
7438 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7441 std::vector<const SMDS_MeshElement*> newEdges;
7442 std::vector<const SMDS_MeshNode*> newNodes;
7443 SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes,
7444 groupDS ? &groupDS->SMDSGroup() : 0,
7445 theElementSearcher );
7447 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ).
7449 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ).
7450 assign( newNodes.begin(), newNodes.end() );
7453 if ( myIsPreviewMode )
7455 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7457 SMESH::PolySegment& segOut = theSegments[ i ];
7458 SMESH_MeshAlgos::PolySegment& segIn = segments[ i ];
7459 segOut.vector.PS.x = segIn.myVector.X();
7460 segOut.vector.PS.y = segIn.myVector.Y();
7461 segOut.vector.PS.z = segIn.myVector.Z();
7466 TPythonDump() << "_segments = []";
7467 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7469 SMESH::PolySegment& segIn = theSegments[ i ];
7470 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7471 << segIn.node1ID1 << ", "
7472 << segIn.node1ID2 << ", "
7473 << segIn.node2ID1 << ", "
7474 << segIn.node2ID2 << ", "
7475 << "smeshBuilder.MakeDirStruct( "
7476 << segIn.vector.PS.x << ", "
7477 << segIn.vector.PS.y << ", "
7478 << segIn.vector.PS.z << ")))";
7480 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7483 SMESH_CATCH( SMESH::throwCorbaException );
7487 //================================================================================
7489 * \brief Create a slot of given width around given 1D elements lying on a triangle mesh.
7490 * The slot is constructed by cutting faces by cylindrical surfaces made
7491 * around each segment. Segments are expected to be created by MakePolyLine().
7492 * \return Edges located at the slot boundary
7494 //================================================================================
7496 SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments,
7497 CORBA::Double theWidth)
7498 throw (SALOME::SALOME_Exception)
7500 if ( CORBA::is_nil( theSegments ) ||
7501 theSegments->GetType() != SMESH::EDGE )
7502 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7503 if ( myMesh->NbFaces() == 0 )
7504 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7506 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
7509 initData(/*deleteSearchers=*/false);
7511 SMESHDS_Mesh* meshDS = getMeshDS();
7513 // get standalone face groups to be updated
7514 std::vector< SMDS_MeshGroup* > faceGroups;
7515 const std::set<SMESHDS_GroupBase*>& allGroups = meshDS->GetGroups();
7516 std::set<SMESHDS_GroupBase*>::const_iterator grIt = allGroups.begin();
7517 for ( ; grIt != allGroups.end(); ++grIt )
7518 if ( const SMESHDS_Group* gr = dynamic_cast< const SMESHDS_Group* >( *grIt ))
7519 if ( gr->GetType() == SMDSAbs_Face )
7520 faceGroups.push_back( & const_cast< SMESHDS_Group* >( gr )->SMDSGroup() );
7522 std::vector< SMESH_MeshAlgos::Edge > edges =
7523 SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ),
7524 theWidth, meshDS, faceGroups );
7526 resultEdges->length( edges.size() );
7527 for ( size_t i = 0; i < edges.size(); ++i )
7529 resultEdges[ i ].node1 = edges[i]._node1->GetID();
7530 resultEdges[ i ].node2 = edges[i]._node2->GetID();
7531 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
7535 SMESH_CATCH( SMESH::throwCorbaException );
7537 TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed
7539 return resultEdges._retn();