1 // Copyright (C) 2007-2020 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] )))
1074 INFOS("Polygon without nodes is forbidden");
1078 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1080 // Update Python script
1081 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1083 declareMeshModified( /*isReComputeSafe=*/false );
1084 return elem ? elem->GetID() : 0;
1086 SMESH_CATCH( SMESH::throwCorbaException );
1090 //=============================================================================
1092 * AddQuadPolygonalFace
1094 //=============================================================================
1096 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1097 throw (SALOME::SALOME_Exception)
1102 int NbNodes = IDsOfNodes.length();
1103 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1104 for (int i = 0; i < NbNodes; i++)
1105 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1109 INFOS("Polygon without nodes is forbidden");
1113 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1115 // Update Python script
1116 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1118 declareMeshModified( /*isReComputeSafe=*/false );
1119 return elem ? elem->GetID() : 0;
1121 SMESH_CATCH( SMESH::throwCorbaException );
1125 //=============================================================================
1127 * Create volume, either linear and quadratic (this is determed
1128 * by number of given nodes)
1130 //=============================================================================
1132 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1133 throw (SALOME::SALOME_Exception)
1138 int NbNodes = IDsOfNodes.length();
1139 vector< const SMDS_MeshNode*> n(NbNodes);
1140 for(int i=0;i<NbNodes;i++)
1141 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1143 SMDS_MeshElement* elem = 0;
1146 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1147 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1148 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1149 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1150 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1151 n[6],n[7],n[8],n[9]);
1153 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1154 n[6],n[7],n[8],n[9],n[10],n[11]);
1156 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1157 n[7],n[8],n[9],n[10],n[11],n[12]);
1159 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1160 n[9],n[10],n[11],n[12],n[13],n[14]);
1162 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1163 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1164 n[15],n[16],n[17],n[18],n[19]);
1166 case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1167 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1170 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1171 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1172 n[15],n[16],n[17],n[18],n[19],
1173 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1177 // Update Python script
1178 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1180 declareMeshModified( /*isReComputeSafe=*/false );
1181 return elem ? elem->GetID() : 0;
1183 SMESH_CATCH( SMESH::throwCorbaException );
1187 //=============================================================================
1189 * AddPolyhedralVolume
1191 //=============================================================================
1192 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1193 const SMESH::long_array & Quantities)
1194 throw (SALOME::SALOME_Exception)
1199 int NbNodes = IDsOfNodes.length();
1200 std::vector<const SMDS_MeshNode*> n (NbNodes);
1201 for (int i = 0; i < NbNodes; i++)
1203 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1204 if (!aNode) return 0;
1208 int NbFaces = Quantities.length();
1209 std::vector<int> q (NbFaces);
1210 for (int j = 0; j < NbFaces; j++)
1211 q[j] = Quantities[j];
1213 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1215 // Update Python script
1216 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1217 << IDsOfNodes << ", " << Quantities << " )";
1219 declareMeshModified( /*isReComputeSafe=*/false );
1220 return elem ? elem->GetID() : 0;
1222 SMESH_CATCH( SMESH::throwCorbaException );
1226 //=============================================================================
1228 * AddPolyhedralVolumeByFaces
1230 //=============================================================================
1232 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1233 throw (SALOME::SALOME_Exception)
1238 int NbFaces = IdsOfFaces.length();
1239 std::vector<const SMDS_MeshNode*> poly_nodes;
1240 std::vector<int> quantities (NbFaces);
1242 for (int i = 0; i < NbFaces; i++) {
1243 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1244 quantities[i] = aFace->NbNodes();
1246 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1247 while (It->more()) {
1248 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1252 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1254 // Update Python script
1255 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1256 << IdsOfFaces << " )";
1258 declareMeshModified( /*isReComputeSafe=*/false );
1259 return elem ? elem->GetID() : 0;
1261 SMESH_CATCH( SMESH::throwCorbaException );
1265 //=============================================================================
1267 // \brief Create 0D elements on all nodes of the given object.
1268 // \param theObject object on whose nodes 0D elements will be created.
1269 // \param theGroupName optional name of a group to add 0D elements created
1270 // and/or found on nodes of \a theObject.
1271 // \param DuplicateElements to add one more 0D element to a node or not.
1272 // \return an object (a new group or a temporary SMESH_IDSource) holding
1273 // ids of new and/or found 0D elements.
1275 //=============================================================================
1277 SMESH::SMESH_IDSource_ptr
1278 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1279 const char* theGroupName,
1280 CORBA::Boolean theDuplicateElements)
1281 throw (SALOME::SALOME_Exception)
1286 SMESH::SMESH_IDSource_var result;
1289 TIDSortedElemSet elements, elems0D;
1290 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1291 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1293 SMESH::long_array_var newElems = new SMESH::long_array;
1294 newElems->length( elems0D.size() );
1295 TIDSortedElemSet::iterator eIt = elems0D.begin();
1296 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1297 newElems[ i ] = (*eIt)->GetID();
1299 SMESH::SMESH_GroupBase_var groupToFill;
1300 if ( theGroupName && strlen( theGroupName ))
1302 // Get existing group named theGroupName
1303 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1304 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1305 SMESH::SMESH_GroupBase_var group = groups[i];
1306 if ( !group->_is_nil() ) {
1307 CORBA::String_var name = group->GetName();
1308 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1309 groupToFill = group;
1314 if ( groupToFill->_is_nil() )
1315 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1316 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1317 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1320 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1322 group_i->Add( newElems );
1323 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1324 pyDump << groupToFill;
1328 result = MakeIDSource( newElems, SMESH::ELEM0D );
1329 pyDump << "elem0DIDs";
1332 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1333 << theObject << ", '" << theGroupName << "' )";
1335 return result._retn();
1337 SMESH_CATCH( SMESH::throwCorbaException );
1341 //=============================================================================
1343 * \brief Bind a node to a vertex
1344 * \param NodeID - node ID
1345 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1346 * \retval boolean - false if NodeID or VertexID is invalid
1348 //=============================================================================
1350 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1351 throw (SALOME::SALOME_Exception)
1355 SMESHDS_Mesh * mesh = getMeshDS();
1356 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1358 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1360 if ( mesh->MaxShapeIndex() < VertexID )
1361 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1363 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1364 if ( shape.ShapeType() != TopAbs_VERTEX )
1365 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1367 mesh->SetNodeOnVertex( node, VertexID );
1369 myMesh->SetIsModified( true );
1371 SMESH_CATCH( SMESH::throwCorbaException );
1374 //=============================================================================
1376 * \brief Store node position on an edge
1377 * \param NodeID - node ID
1378 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1379 * \param paramOnEdge - parameter on edge where the node is located
1380 * \retval boolean - false if any parameter is invalid
1382 //=============================================================================
1384 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1385 CORBA::Double paramOnEdge)
1386 throw (SALOME::SALOME_Exception)
1390 SMESHDS_Mesh * mesh = getMeshDS();
1391 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1393 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1395 if ( mesh->MaxShapeIndex() < EdgeID )
1396 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1398 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1399 if ( shape.ShapeType() != TopAbs_EDGE )
1400 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1403 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1404 if ( paramOnEdge < f || paramOnEdge > l )
1406 SMESH_Comment txt("Invalid paramOnEdge. It must vary in range [ ");
1407 txt << f << ", " << l << " ]";
1408 THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM);
1410 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1412 myMesh->SetIsModified( true );
1414 SMESH_CATCH( SMESH::throwCorbaException );
1417 //=============================================================================
1419 * \brief Store node position on a face
1420 * \param NodeID - node ID
1421 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1422 * \param u - U parameter on face where the node is located
1423 * \param v - V parameter on face where the node is located
1424 * \retval boolean - false if any parameter is invalid
1426 //=============================================================================
1428 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1429 CORBA::Double u, CORBA::Double v)
1430 throw (SALOME::SALOME_Exception)
1433 SMESHDS_Mesh * mesh = getMeshDS();
1434 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1436 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1438 if ( mesh->MaxShapeIndex() < FaceID )
1439 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1441 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1442 if ( shape.ShapeType() != TopAbs_FACE )
1443 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1445 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1446 bool isOut = ( u < surf.FirstUParameter() ||
1447 u > surf.LastUParameter() ||
1448 v < surf.FirstVParameter() ||
1449 v > surf.LastVParameter() );
1452 SMESH_Comment txt("Invalid UV. U must vary in range [ ");
1453 txt << surf.FirstUParameter() << ", " << surf.LastUParameter() << " ], ";
1454 txt << "V must vary in range [ ";
1455 txt << surf.FirstVParameter() << ", " << surf.LastVParameter() << " ]";
1456 THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM);
1459 mesh->SetNodeOnFace( node, FaceID, u, v );
1460 myMesh->SetIsModified( true );
1462 SMESH_CATCH( SMESH::throwCorbaException );
1465 //=============================================================================
1467 * \brief Bind a node to a solid
1468 * \param NodeID - node ID
1469 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1470 * \retval boolean - false if NodeID or SolidID is invalid
1472 //=============================================================================
1474 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1475 throw (SALOME::SALOME_Exception)
1478 SMESHDS_Mesh * mesh = getMeshDS();
1479 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1481 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1483 if ( mesh->MaxShapeIndex() < SolidID )
1484 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1486 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1487 if ( shape.ShapeType() != TopAbs_SOLID &&
1488 shape.ShapeType() != TopAbs_SHELL)
1489 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1491 mesh->SetNodeInVolume( node, SolidID );
1493 SMESH_CATCH( SMESH::throwCorbaException );
1496 //=============================================================================
1498 * \brief Bind an element to a shape
1499 * \param ElementID - element ID
1500 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1502 //=============================================================================
1504 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1505 CORBA::Long ShapeID)
1506 throw (SALOME::SALOME_Exception)
1509 SMESHDS_Mesh * mesh = getMeshDS();
1510 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1512 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1514 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1515 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1517 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1518 if ( shape.ShapeType() != TopAbs_EDGE &&
1519 shape.ShapeType() != TopAbs_FACE &&
1520 shape.ShapeType() != TopAbs_SOLID &&
1521 shape.ShapeType() != TopAbs_SHELL )
1522 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1524 mesh->SetMeshElementOnShape( elem, ShapeID );
1526 myMesh->SetIsModified( true );
1528 SMESH_CATCH( SMESH::throwCorbaException );
1531 //=============================================================================
1535 //=============================================================================
1537 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1538 CORBA::Long NodeID2)
1539 throw (SALOME::SALOME_Exception)
1544 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1545 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1549 // Update Python script
1550 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1551 << NodeID1 << ", " << NodeID2 << " )";
1553 int ret = getEditor().InverseDiag ( n1, n2 );
1555 declareMeshModified( /*isReComputeSafe=*/false );
1558 SMESH_CATCH( SMESH::throwCorbaException );
1562 //=============================================================================
1566 //=============================================================================
1568 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1569 CORBA::Long NodeID2)
1570 throw (SALOME::SALOME_Exception)
1575 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1576 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1580 // Update Python script
1581 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1582 << NodeID1 << ", " << NodeID2 << " )";
1585 bool stat = getEditor().DeleteDiag ( n1, n2 );
1587 declareMeshModified( /*isReComputeSafe=*/!stat );
1591 SMESH_CATCH( SMESH::throwCorbaException );
1595 //=============================================================================
1599 //=============================================================================
1601 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1602 throw (SALOME::SALOME_Exception)
1607 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1609 CORBA::Long index = IDsOfElements[i];
1610 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1612 getEditor().Reorient( elem );
1614 // Update Python script
1615 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1617 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1620 SMESH_CATCH( SMESH::throwCorbaException );
1624 //=============================================================================
1628 //=============================================================================
1630 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1631 throw (SALOME::SALOME_Exception)
1636 TPythonDump aTPythonDump; // suppress dump in Reorient()
1638 prepareIdSource( theObject );
1640 SMESH::long_array_var anElementsId = theObject->GetIDs();
1641 CORBA::Boolean isDone = Reorient(anElementsId);
1643 // Update Python script
1644 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1646 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1649 SMESH_CATCH( SMESH::throwCorbaException );
1653 //=======================================================================
1654 //function : Reorient2D
1655 //purpose : Reorient faces contained in \a the2Dgroup.
1656 // the2Dgroup - the mesh or its part to reorient
1657 // theDirection - desired direction of normal of \a theFace
1658 // theFace - ID of face whose orientation is checked.
1659 // It can be < 1 then \a thePoint is used to find a face.
1660 // thePoint - is used to find a face if \a theFace < 1.
1661 // return number of reoriented elements.
1662 //=======================================================================
1664 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1665 const SMESH::DirStruct& theDirection,
1666 CORBA::Long theFace,
1667 const SMESH::PointStruct& thePoint)
1668 throw (SALOME::SALOME_Exception)
1671 initData(/*deleteSearchers=*/false);
1673 TIDSortedElemSet elements;
1674 IDSource_Error error;
1675 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1676 if ( error == IDSource_EMPTY )
1678 if ( error == IDSource_INVALID )
1679 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1682 const SMDS_MeshElement* face = 0;
1685 face = getMeshDS()->FindElement( theFace );
1687 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1688 if ( face->GetType() != SMDSAbs_Face )
1689 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1693 // create theElementSearcher if needed
1694 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1695 if ( !theElementSearcher )
1697 if ( elements.empty() ) // search in the whole mesh
1699 if ( myMesh->NbFaces() == 0 )
1700 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1702 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1706 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1707 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1709 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1713 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1714 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1717 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1718 if ( !elements.empty() && !elements.count( face ))
1719 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1722 const SMESH::PointStruct * P = &theDirection.PS;
1723 gp_Vec dirVec( P->x, P->y, P->z );
1724 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1725 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1727 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1730 declareMeshModified( /*isReComputeSafe=*/false );
1732 TPythonDump() << this << ".Reorient2D( "
1733 << the2Dgroup << ", "
1734 << theDirection << ", "
1736 << thePoint << " )";
1740 SMESH_CATCH( SMESH::throwCorbaException );
1744 //=======================================================================
1745 //function : Reorient2DBy3D
1746 //purpose : Reorient faces basing on orientation of adjacent volumes.
1747 //=======================================================================
1749 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1750 SMESH::SMESH_IDSource_ptr volumeGroup,
1751 CORBA::Boolean outsideNormal)
1752 throw (SALOME::SALOME_Exception)
1757 TIDSortedElemSet volumes;
1758 IDSource_Error volsError;
1759 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1762 for ( size_t i = 0; i < faceGroups.length(); ++i )
1764 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1766 TIDSortedElemSet faces;
1767 IDSource_Error error;
1768 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1769 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1770 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1771 if ( error == IDSource_OK && volsError != IDSource_OK )
1772 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1774 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1776 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1781 declareMeshModified( /*isReComputeSafe=*/false );
1783 TPythonDump() << this << ".Reorient2DBy3D( "
1784 << faceGroups << ", "
1785 << volumeGroup << ", "
1786 << outsideNormal << " )";
1790 SMESH_CATCH( SMESH::throwCorbaException );
1794 //=============================================================================
1796 * \brief Fuse neighbour triangles into quadrangles.
1798 //=============================================================================
1800 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1801 SMESH::NumericalFunctor_ptr Criterion,
1802 CORBA::Double MaxAngle)
1803 throw (SALOME::SALOME_Exception)
1808 SMESHDS_Mesh* aMesh = getMeshDS();
1809 TIDSortedElemSet faces,copyFaces;
1810 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1811 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1812 TIDSortedElemSet* workElements = & faces;
1814 if ( myIsPreviewMode ) {
1815 SMDSAbs_ElementType select = SMDSAbs_Face;
1816 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1817 workElements = & copyFaces;
1820 SMESH::NumericalFunctor_i* aNumericalFunctor =
1821 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1822 SMESH::Controls::NumericalFunctorPtr aCrit;
1823 if ( !aNumericalFunctor )
1824 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1826 aCrit = aNumericalFunctor->GetNumericalFunctor();
1828 if ( !myIsPreviewMode ) {
1829 // Update Python script
1830 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1831 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1834 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1836 declareMeshModified( /*isReComputeSafe=*/!stat );
1839 SMESH_CATCH( SMESH::throwCorbaException );
1843 //=============================================================================
1845 * \brief Fuse neighbour triangles into quadrangles.
1847 //=============================================================================
1849 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1850 SMESH::NumericalFunctor_ptr Criterion,
1851 CORBA::Double MaxAngle)
1852 throw (SALOME::SALOME_Exception)
1857 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1859 prepareIdSource( theObject );
1860 SMESH::long_array_var anElementsId = theObject->GetIDs();
1861 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1863 if ( !myIsPreviewMode ) {
1864 SMESH::NumericalFunctor_i* aNumericalFunctor =
1865 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1867 // Update Python script
1868 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1869 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1874 SMESH_CATCH( SMESH::throwCorbaException );
1878 //=============================================================================
1880 * \brief Split quadrangles into triangles.
1882 //=============================================================================
1884 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1885 SMESH::NumericalFunctor_ptr Criterion)
1886 throw (SALOME::SALOME_Exception)
1891 SMESHDS_Mesh* aMesh = getMeshDS();
1892 TIDSortedElemSet faces;
1893 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1895 SMESH::NumericalFunctor_i* aNumericalFunctor =
1896 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1897 SMESH::Controls::NumericalFunctorPtr aCrit;
1898 if ( !aNumericalFunctor )
1899 aCrit.reset( new SMESH::Controls::AspectRatio() );
1901 aCrit = aNumericalFunctor->GetNumericalFunctor();
1904 // Update Python script
1905 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1907 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1909 declareMeshModified( /*isReComputeSafe=*/false );
1912 SMESH_CATCH( SMESH::throwCorbaException );
1916 //=============================================================================
1918 * \brief Split quadrangles into triangles.
1920 //=============================================================================
1922 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1923 SMESH::NumericalFunctor_ptr Criterion)
1924 throw (SALOME::SALOME_Exception)
1929 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1931 prepareIdSource( theObject );
1932 SMESH::long_array_var anElementsId = theObject->GetIDs();
1933 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1935 SMESH::NumericalFunctor_i* aNumericalFunctor =
1936 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1938 // Update Python script
1939 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1941 declareMeshModified( /*isReComputeSafe=*/false );
1944 SMESH_CATCH( SMESH::throwCorbaException );
1948 //================================================================================
1950 * \brief Split each of quadrangles into 4 triangles.
1951 * \param [in] theObject - theQuads Container of quadrangles to split.
1953 //================================================================================
1955 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1956 throw (SALOME::SALOME_Exception)
1961 TIDSortedElemSet faces;
1962 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1964 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1966 getEditor().QuadTo4Tri( faces );
1967 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1969 SMESH_CATCH( SMESH::throwCorbaException );
1972 //=============================================================================
1974 * \brief Split quadrangles into triangles.
1976 //=============================================================================
1978 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1979 CORBA::Boolean Diag13)
1980 throw (SALOME::SALOME_Exception)
1985 SMESHDS_Mesh* aMesh = getMeshDS();
1986 TIDSortedElemSet faces;
1987 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1989 // Update Python script
1990 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1991 << IDsOfElements << ", " << Diag13 << " )";
1993 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1995 declareMeshModified( /*isReComputeSafe=*/ !stat );
1998 SMESH_CATCH( SMESH::throwCorbaException );
2002 //=============================================================================
2004 * \brief Split quadrangles into triangles.
2006 //=============================================================================
2008 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
2009 CORBA::Boolean Diag13)
2010 throw (SALOME::SALOME_Exception)
2015 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2017 prepareIdSource( theObject );
2018 SMESH::long_array_var anElementsId = theObject->GetIDs();
2019 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2021 // Update Python script
2022 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2023 << theObject << ", " << Diag13 << " )";
2025 declareMeshModified( /*isReComputeSafe=*/!isDone );
2028 SMESH_CATCH( SMESH::throwCorbaException );
2033 //=============================================================================
2035 * Find better splitting of the given quadrangle.
2036 * \param IDOfQuad ID of the quadrangle to be split.
2037 * \param Criterion A criterion to choose a diagonal for splitting.
2038 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2039 * diagonal is better, 0 if error occurs.
2041 //=============================================================================
2043 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2044 SMESH::NumericalFunctor_ptr Criterion)
2045 throw (SALOME::SALOME_Exception)
2050 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2051 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2053 SMESH::NumericalFunctor_i* aNumericalFunctor =
2054 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2055 SMESH::Controls::NumericalFunctorPtr aCrit;
2056 if (aNumericalFunctor)
2057 aCrit = aNumericalFunctor->GetNumericalFunctor();
2059 aCrit.reset(new SMESH::Controls::AspectRatio());
2061 int id = getEditor().BestSplit(quad, aCrit);
2062 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2066 SMESH_CATCH( SMESH::throwCorbaException );
2070 //================================================================================
2072 * \brief Split volumic elements into tetrahedrons
2074 //================================================================================
2076 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2077 CORBA::Short methodFlags)
2078 throw (SALOME::SALOME_Exception)
2083 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2084 const int noneFacet = -1;
2085 prepareIdSource( elems );
2086 if ( SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME ))
2087 while ( volIt->more() )
2088 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2090 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2091 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2093 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2094 << elems << ", " << methodFlags << " )";
2096 SMESH_CATCH( SMESH::throwCorbaException );
2099 //================================================================================
2101 * \brief Split hexahedra into triangular prisms
2102 * \param elems - elements to split
2103 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2104 * to split into triangles
2105 * \param methodFlags - flags passing splitting method:
2106 * 1 - split the hexahedron into 2 prisms
2107 * 2 - split the hexahedron into 4 prisms
2109 //================================================================================
2111 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2112 const SMESH::PointStruct & startHexPoint,
2113 const SMESH::DirStruct& facetToSplitNormal,
2114 CORBA::Short methodFlags,
2115 CORBA::Boolean allDomains)
2116 throw (SALOME::SALOME_Exception)
2120 prepareIdSource( elems );
2122 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2125 gp_Dir( facetToSplitNormal.PS.x,
2126 facetToSplitNormal.PS.y,
2127 facetToSplitNormal.PS.z ));
2128 TIDSortedElemSet elemSet;
2129 prepareIdSource( elems );
2130 SMESH::long_array_var anElementsId = elems->GetIDs();
2131 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2132 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2134 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2135 while ( !elemSet.empty() )
2137 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2141 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2142 for ( ; ef != elemFacets.end(); ++ef )
2143 elemSet.erase( ef->first );
2146 if ( methodFlags == 2 )
2147 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2149 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2151 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2152 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2154 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2156 << startHexPoint << ", "
2157 << facetToSplitNormal<< ", "
2158 << methodFlags<< ", "
2159 << allDomains << " )";
2161 SMESH_CATCH( SMESH::throwCorbaException );
2164 //================================================================================
2166 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2167 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2168 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2169 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2170 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2171 * will be split in order to keep the mesh conformal.
2172 * \param elems - elements to split
2174 //================================================================================
2176 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2177 throw (SALOME::SALOME_Exception)
2182 TIDSortedElemSet elemSet;
2183 for ( size_t i = 0; i < theElems.length(); ++i )
2185 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2186 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2187 if ( mesh->GetId() != myMesh_i->GetId() )
2188 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2190 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2192 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2194 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2196 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2197 << theElems << " )";
2199 SMESH_CATCH( SMESH::throwCorbaException );
2202 //=======================================================================
2205 //=======================================================================
2208 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2209 const SMESH::long_array & IDsOfFixedNodes,
2210 CORBA::Long MaxNbOfIterations,
2211 CORBA::Double MaxAspectRatio,
2212 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2213 throw (SALOME::SALOME_Exception)
2215 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2216 MaxAspectRatio, Method, false );
2220 //=======================================================================
2221 //function : SmoothParametric
2223 //=======================================================================
2226 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2227 const SMESH::long_array & IDsOfFixedNodes,
2228 CORBA::Long MaxNbOfIterations,
2229 CORBA::Double MaxAspectRatio,
2230 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2231 throw (SALOME::SALOME_Exception)
2233 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2234 MaxAspectRatio, Method, true );
2238 //=======================================================================
2239 //function : SmoothObject
2241 //=======================================================================
2244 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2245 const SMESH::long_array & IDsOfFixedNodes,
2246 CORBA::Long MaxNbOfIterations,
2247 CORBA::Double MaxAspectRatio,
2248 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2249 throw (SALOME::SALOME_Exception)
2251 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2252 MaxAspectRatio, Method, false);
2256 //=======================================================================
2257 //function : SmoothParametricObject
2259 //=======================================================================
2262 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2263 const SMESH::long_array & IDsOfFixedNodes,
2264 CORBA::Long MaxNbOfIterations,
2265 CORBA::Double MaxAspectRatio,
2266 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2267 throw (SALOME::SALOME_Exception)
2269 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2270 MaxAspectRatio, Method, true);
2274 //=============================================================================
2278 //=============================================================================
2281 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2282 const SMESH::long_array & IDsOfFixedNodes,
2283 CORBA::Long MaxNbOfIterations,
2284 CORBA::Double MaxAspectRatio,
2285 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2287 throw (SALOME::SALOME_Exception)
2292 SMESHDS_Mesh* aMesh = getMeshDS();
2294 TIDSortedElemSet elements;
2295 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2297 set<const SMDS_MeshNode*> fixedNodes;
2298 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2299 CORBA::Long index = IDsOfFixedNodes[i];
2300 const SMDS_MeshNode * node = aMesh->FindNode(index);
2302 fixedNodes.insert( node );
2304 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2305 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2306 method = ::SMESH_MeshEditor::CENTROIDAL;
2308 getEditor().Smooth(elements, fixedNodes, method,
2309 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2311 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2313 // Update Python script
2314 TPythonDump() << "isDone = " << this << "."
2315 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2316 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2317 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2318 << "SMESH.SMESH_MeshEditor."
2319 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2320 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2324 SMESH_CATCH( SMESH::throwCorbaException );
2328 //=============================================================================
2332 //=============================================================================
2335 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2336 const SMESH::long_array & IDsOfFixedNodes,
2337 CORBA::Long MaxNbOfIterations,
2338 CORBA::Double MaxAspectRatio,
2339 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2341 throw (SALOME::SALOME_Exception)
2346 TPythonDump aTPythonDump; // suppress dump in smooth()
2348 prepareIdSource( theObject );
2349 SMESH::long_array_var anElementsId = theObject->GetIDs();
2350 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2351 MaxAspectRatio, Method, IsParametric);
2353 // Update Python script
2354 aTPythonDump << "isDone = " << this << "."
2355 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2356 << theObject << ", " << IDsOfFixedNodes << ", "
2357 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2358 << "SMESH.SMESH_MeshEditor."
2359 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2360 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2364 SMESH_CATCH( SMESH::throwCorbaException );
2368 //=============================================================================
2372 //=============================================================================
2374 void SMESH_MeshEditor_i::RenumberNodes()
2375 throw (SALOME::SALOME_Exception)
2378 // Update Python script
2379 TPythonDump() << this << ".RenumberNodes()";
2381 getMeshDS()->Renumber( true );
2383 SMESH_CATCH( SMESH::throwCorbaException );
2386 //=============================================================================
2390 //=============================================================================
2392 void SMESH_MeshEditor_i::RenumberElements()
2393 throw (SALOME::SALOME_Exception)
2396 // Update Python script
2397 TPythonDump() << this << ".RenumberElements()";
2399 getMeshDS()->Renumber( false );
2401 SMESH_CATCH( SMESH::throwCorbaException );
2404 //=======================================================================
2406 * \brief Return groups by their IDs
2408 //=======================================================================
2410 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2411 throw (SALOME::SALOME_Exception)
2416 myMesh_i->CreateGroupServants();
2417 return myMesh_i->GetGroups( *groupIDs );
2419 SMESH_CATCH( SMESH::throwCorbaException );
2423 //=======================================================================
2424 //function : RotationSweepObjects
2426 //=======================================================================
2428 SMESH::ListOfGroups*
2429 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2430 const SMESH::ListOfIDSources & theEdges,
2431 const SMESH::ListOfIDSources & theFaces,
2432 const SMESH::AxisStruct & theAxis,
2433 CORBA::Double theAngleInRadians,
2434 CORBA::Long theNbOfSteps,
2435 CORBA::Double theTolerance,
2436 const bool theMakeGroups)
2437 throw (SALOME::SALOME_Exception)
2442 TIDSortedElemSet elemsNodes[2];
2443 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2444 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2445 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2447 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2448 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2449 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2450 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2452 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2453 bool makeWalls=true;
2454 if ( myIsPreviewMode )
2456 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2457 TPreviewMesh * tmpMesh = getPreviewMesh();
2458 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2459 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2460 workElements = & copyElements[0];
2461 //makeWalls = false; -- faces are needed for preview
2464 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2466 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2467 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2469 ::SMESH_MeshEditor::PGroupIDs groupIds =
2470 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2471 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2473 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2475 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2477 if ( !myIsPreviewMode )
2479 dumpGroupsList( aPythonDump, aGroups );
2480 aPythonDump << this<< ".RotationSweepObjects( "
2485 << TVar( theAngleInRadians ) << ", "
2486 << TVar( theNbOfSteps ) << ", "
2487 << TVar( theTolerance ) << ", "
2488 << theMakeGroups << " )";
2492 getPreviewMesh()->Remove( SMDSAbs_Volume );
2495 return aGroups ? aGroups : new SMESH::ListOfGroups;
2497 SMESH_CATCH( SMESH::throwCorbaException );
2501 namespace MeshEditor_I
2504 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2506 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2508 bool myIsExtrusionByNormal;
2510 static int makeFlags( CORBA::Boolean MakeGroups,
2511 CORBA::Boolean ScaleVariation = false,
2512 CORBA::Boolean AngleVariation = false,
2513 CORBA::Boolean ByAverageNormal = false,
2514 CORBA::Boolean UseInputElemsOnly = false,
2515 CORBA::Long Flags = 0,
2516 CORBA::Boolean MakeBoundary = true )
2518 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2519 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2520 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2521 if ( ScaleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2522 if ( AngleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION;
2523 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2527 ExtrusionParams(const SMESH::DirStruct & theDir,
2528 CORBA::Long theNbOfSteps,
2529 const SMESH::double_array & theScaleFactors,
2530 CORBA::Boolean theScaleVariation,
2531 const SMESH::double_array & theAngles,
2532 CORBA::Boolean theAngleVariation,
2533 const SMESH::double_array & theBasePoint,
2534 CORBA::Boolean theMakeGroups):
2535 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2539 toList( theScaleFactors ),
2540 toList( theAngles ),
2541 TBasePoint( theBasePoint ),
2542 makeFlags( theMakeGroups, theScaleVariation, theAngleVariation )),
2543 myIsExtrusionByNormal( false )
2547 ExtrusionParams(const SMESH::DirStruct & theDir,
2548 CORBA::Long theNbOfSteps,
2549 CORBA::Boolean theMakeGroups,
2550 CORBA::Long theExtrFlags,
2551 CORBA::Double theSewTolerance):
2552 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2556 std::list<double>(),
2557 std::list<double>(),
2559 makeFlags( theMakeGroups, false, false, false, false,
2560 theExtrFlags, false ),
2562 myIsExtrusionByNormal( false )
2565 // params for extrusion by normal
2566 ExtrusionParams(CORBA::Double theStepSize,
2567 CORBA::Long theNbOfSteps,
2568 CORBA::Short theDim,
2569 CORBA::Boolean theByAverageNormal,
2570 CORBA::Boolean theUseInputElemsOnly,
2571 CORBA::Boolean theMakeGroups ):
2572 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2574 makeFlags( theMakeGroups, false, false,
2575 theByAverageNormal, theUseInputElemsOnly ),
2577 myIsExtrusionByNormal( true )
2583 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2586 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2588 std::list<double> scales;
2589 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2590 scales.push_back( theScaleFactors[i] );
2596 // structure used to convert SMESH::double_array to gp_XYZ*
2600 TBasePoint( const SMESH::double_array & theBasePoint )
2603 if ( theBasePoint.length() == 3 )
2605 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2609 operator const gp_XYZ*() const { return pp; }
2614 //=======================================================================
2616 * \brief Generate dim+1 elements by extrusion of elements along vector
2617 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2618 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2619 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2620 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2621 * \param [in] nbOfSteps - number of elements to generate from one element
2622 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2623 * corresponding to groups the input elements included in.
2624 * \return ListOfGroups - new groups created if \a toMakeGroups is true
2626 //=======================================================================
2628 SMESH::ListOfGroups*
2629 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2630 const SMESH::ListOfIDSources & theEdges,
2631 const SMESH::ListOfIDSources & theFaces,
2632 const SMESH::DirStruct & theStepVector,
2633 CORBA::Long theNbOfSteps,
2634 CORBA::Boolean theToMakeGroups,
2635 const SMESH::double_array & theScaleFactors,
2636 CORBA::Boolean theScalesVariation,
2637 const SMESH::double_array & theBasePoint,
2638 const SMESH::double_array & theAngles,
2639 CORBA::Boolean theAnglesVariation)
2640 throw (SALOME::SALOME_Exception)
2645 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, theScalesVariation,
2646 theAngles, theAnglesVariation, theBasePoint, theToMakeGroups );
2648 TIDSortedElemSet elemsNodes[2];
2649 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2650 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2651 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2653 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2654 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2655 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2656 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2658 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2659 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2660 if ( myIsPreviewMode )
2662 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2663 // previewType = SMDSAbs_Edge;
2665 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2666 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2667 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2668 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2669 workElements = & copyElements[0];
2671 params.SetNoGroups();
2673 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2675 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2676 ::SMESH_MeshEditor::PGroupIDs groupIds =
2677 getEditor().ExtrusionSweep( workElements, params, aHistory );
2679 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2681 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2683 if ( !myIsPreviewMode )
2685 dumpGroupsList( aPythonDump, aGroups );
2686 aPythonDump << this<< ".ExtrusionSweepObjects( "
2690 << theStepVector << ", "
2691 << TVar( theNbOfSteps ) << ", "
2692 << theToMakeGroups << ", "
2693 << TVar( theScaleFactors ) << ", "
2694 << theScalesVariation << ", "
2695 << TVar( theBasePoint ) << ", "
2696 << TVar( theAngles ) << ", "
2697 << theAnglesVariation << " )";
2701 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2704 return aGroups ? aGroups : new SMESH::ListOfGroups;
2706 SMESH_CATCH( SMESH::throwCorbaException );
2710 //=======================================================================
2711 //function : ExtrusionByNormal
2713 //=======================================================================
2715 SMESH::ListOfGroups*
2716 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2717 CORBA::Double stepSize,
2718 CORBA::Long nbOfSteps,
2719 CORBA::Boolean byAverageNormal,
2720 CORBA::Boolean useInputElemsOnly,
2721 CORBA::Boolean makeGroups,
2723 throw (SALOME::SALOME_Exception)
2728 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2730 ExtrusionParams params( stepSize, nbOfSteps, dim,
2731 byAverageNormal, useInputElemsOnly, makeGroups );
2733 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2734 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2736 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2737 if (( elemTypes->length() == 1 ) &&
2738 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2739 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2742 TIDSortedElemSet elemsNodes[2];
2743 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2744 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2746 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2747 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2748 if ( myIsPreviewMode )
2750 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2751 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2752 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2753 workElements = & copyElements[0];
2755 params.SetNoGroups();
2758 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2759 ::SMESH_MeshEditor::PGroupIDs groupIds =
2760 getEditor().ExtrusionSweep( workElements, params, aHistory );
2762 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2764 if (!myIsPreviewMode) {
2765 dumpGroupsList(aPythonDump, aGroups);
2766 aPythonDump << this << ".ExtrusionByNormal( " << objects
2767 << ", " << TVar( stepSize )
2768 << ", " << TVar( nbOfSteps )
2769 << ", " << byAverageNormal
2770 << ", " << useInputElemsOnly
2771 << ", " << makeGroups
2777 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2780 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2782 return aGroups ? aGroups : new SMESH::ListOfGroups;
2784 SMESH_CATCH( SMESH::throwCorbaException );
2788 //=======================================================================
2789 //function : AdvancedExtrusion
2791 //=======================================================================
2793 SMESH::ListOfGroups*
2794 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2795 const SMESH::DirStruct & theStepVector,
2796 CORBA::Long theNbOfSteps,
2797 CORBA::Long theExtrFlags,
2798 CORBA::Double theSewTolerance,
2799 CORBA::Boolean theMakeGroups)
2800 throw (SALOME::SALOME_Exception)
2805 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2807 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2808 theExtrFlags, theSewTolerance );
2810 TIDSortedElemSet elemsNodes[2];
2811 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2813 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2814 ::SMESH_MeshEditor::PGroupIDs groupIds =
2815 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2817 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2819 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2821 if ( !myIsPreviewMode ) {
2822 dumpGroupsList(aPythonDump, aGroups);
2823 aPythonDump << this << ".AdvancedExtrusion( "
2824 << theIDsOfElements << ", "
2825 << theStepVector << ", "
2826 << theNbOfSteps << ", "
2827 << theExtrFlags << ", "
2828 << theSewTolerance << ", "
2829 << theMakeGroups << " )";
2833 getPreviewMesh()->Remove( SMDSAbs_Volume );
2836 return aGroups ? aGroups : new SMESH::ListOfGroups;
2838 SMESH_CATCH( SMESH::throwCorbaException );
2842 //================================================================================
2844 * \brief Convert extrusion error to IDL enum
2846 //================================================================================
2850 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2852 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2856 RETCASE( EXTR_NO_ELEMENTS );
2857 RETCASE( EXTR_PATH_NOT_EDGE );
2858 RETCASE( EXTR_BAD_PATH_SHAPE );
2859 RETCASE( EXTR_BAD_STARTING_NODE );
2860 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2861 RETCASE( EXTR_CANT_GET_TANGENT );
2863 return SMESH::SMESH_MeshEditor::EXTR_OK;
2867 //=======================================================================
2868 //function : extrusionAlongPath
2870 //=======================================================================
2871 SMESH::ListOfGroups*
2872 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2873 const SMESH::ListOfIDSources & theEdges,
2874 const SMESH::ListOfIDSources & theFaces,
2875 SMESH::SMESH_IDSource_ptr thePathObject,
2876 GEOM::GEOM_Object_ptr thePathShape,
2877 CORBA::Long theNodeStart,
2878 CORBA::Boolean theHasAngles,
2879 const SMESH::double_array & theAngles,
2880 CORBA::Boolean theAnglesVariation,
2881 CORBA::Boolean theHasRefPoint,
2882 const SMESH::PointStruct & theRefPoint,
2884 const SMESH::double_array & theScaleFactors,
2885 CORBA::Boolean theScalesVariation,
2886 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2887 throw (SALOME::SALOME_Exception)
2892 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2894 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2895 if ( thePathObject->_is_nil() )
2896 return aGroups._retn();
2899 SMDS_ElemIteratorPtr pathEdgesIterator;
2901 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathObject );
2902 if ( !CORBA::is_nil( thePathShape ) && aMeshImp )
2904 // get a sub-mesh of thePathShape
2905 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2906 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2908 return aGroups._retn();
2910 if ( !aSubMesh->GetSubMeshDS() )
2912 SMESHDS_Mesh * meshDS = aMeshImp->GetImpl().GetMeshDS();
2913 meshDS->AddCompoundSubmesh( aShape, TopAbs_EDGE );
2914 if ( !aSubMesh->GetSubMeshDS() )
2915 return aGroups._retn();
2917 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2918 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2919 if ( !pathEdgesIterator->more() ||
2920 pathEdgesIterator->next()->GetType() != SMDSAbs_Edge )
2921 return aGroups._retn();
2923 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2927 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2928 prepareIdSource( thePathObject );
2929 pathEdgesIterator = SMESH_Mesh_i::GetElements( thePathObject, SMESH::EDGE );
2930 if ( !pathEdgesIterator || !pathEdgesIterator->more() )
2931 return aGroups._retn();
2936 SMESH::SMESH_Mesh_var pathMesh = thePathObject->GetMesh();
2937 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( pathMesh );
2941 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2942 const SMDS_MeshNode* nodeStart = aMeshImp->GetImpl().GetMeshDS()->FindNode( theNodeStart );
2944 return aGroups._retn();
2947 TIDSortedElemSet elemsNodes[2];
2948 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2949 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2950 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2952 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2953 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2954 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2955 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2957 list<double> angles = ExtrusionParams::toList( theAngles );
2958 list<double> scales = ExtrusionParams::toList( theScaleFactors );
2960 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2961 const gp_Pnt *refPntPtr = theHasRefPoint ? &refPnt : 0;
2963 int nbOldGroups = myMesh->NbGroup();
2965 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2966 if ( myIsPreviewMode )
2968 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2969 TPreviewMesh * tmpMesh = getPreviewMesh();
2970 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2971 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2972 workElements = & copyElements[0];
2973 theMakeGroups = false;
2976 ::SMESH_MeshEditor::Extrusion_Error error =
2977 getEditor().ExtrusionAlongTrack( workElements,
2978 &(aMeshImp->GetImpl()), pathEdgesIterator, nodeStart,
2979 angles, theAnglesVariation,
2980 scales, theScalesVariation,
2981 refPntPtr, theMakeGroups );
2983 declareMeshModified( /*isReComputeSafe=*/true );
2984 theError = convExtrError( error );
2986 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2987 if ( theMakeGroups ) {
2988 list<int> groupIDs = myMesh->GetGroupIds();
2989 list<int>::iterator newBegin = groupIDs.begin();
2990 std::advance( newBegin, nbOldGroups ); // skip old groups
2991 groupIDs.erase( groupIDs.begin(), newBegin );
2992 aGroups = getGroups( & groupIDs );
2993 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2996 if ( !myIsPreviewMode ) {
2997 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2998 else aPythonDump << "(_noGroups, error) = ";
2999 aPythonDump << this << ".ExtrusionAlongPathObjects( "
3003 << thePathObject << ", "
3004 << thePathShape << ", "
3005 << theNodeStart << ", "
3006 << theHasAngles << ", "
3007 << TVar( theAngles ) << ", "
3008 << theAnglesVariation << ", "
3009 << theHasRefPoint << ", "
3010 << "SMESH.PointStruct( "
3011 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3012 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3013 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
3014 << theMakeGroups << ", "
3015 << TVar( theScaleFactors ) << ", "
3016 << theScalesVariation << " )";
3020 getPreviewMesh()->Remove( SMDSAbs_Volume );
3023 return aGroups._retn();
3025 SMESH_CATCH( SMESH::throwCorbaException );
3029 //================================================================================
3031 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
3032 * of given angles along path steps
3033 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
3034 * which proceeds the extrusion
3035 * \param PathShape is shape(edge); as the mesh can be complex, the edge
3036 * is used to define the sub-mesh for the path
3038 //================================================================================
3040 SMESH::double_array*
3041 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
3042 GEOM::GEOM_Object_ptr thePathShape,
3043 const SMESH::double_array & theAngles)
3045 SMESH::double_array_var aResult = new SMESH::double_array();
3046 int nbAngles = theAngles.length();
3047 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3049 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3050 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3051 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3052 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3053 return aResult._retn();
3054 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3055 if ( nbSteps == nbAngles )
3057 aResult.inout() = theAngles;
3061 aResult->length( nbSteps );
3062 double rAn2St = double( nbAngles ) / double( nbSteps );
3063 double angPrev = 0, angle;
3064 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3066 double angCur = rAn2St * ( iSt+1 );
3067 double angCurFloor = floor( angCur );
3068 double angPrevFloor = floor( angPrev );
3069 if ( angPrevFloor == angCurFloor )
3070 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3073 int iP = int( angPrevFloor );
3074 double angPrevCeil = ceil(angPrev);
3075 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3077 int iC = int( angCurFloor );
3078 if ( iC < nbAngles )
3079 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3081 iP = int( angPrevCeil );
3083 angle += theAngles[ iC ];
3085 aResult[ iSt ] = angle;
3090 // Update Python script
3091 TPythonDump() << "rotAngles = " << theAngles;
3092 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3093 << thePathMesh << ", "
3094 << thePathShape << ", "
3097 return aResult._retn();
3100 //=======================================================================
3103 //=======================================================================
3105 SMESH::ListOfGroups*
3106 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3107 const SMESH::AxisStruct & theAxis,
3108 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3109 CORBA::Boolean theCopy,
3111 ::SMESH_Mesh* theTargetMesh)
3112 throw (SALOME::SALOME_Exception)
3117 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3118 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3120 if ( theTargetMesh )
3124 switch ( theMirrorType ) {
3125 case SMESH::SMESH_MeshEditor::POINT:
3126 aTrsf.SetMirror( P );
3128 case SMESH::SMESH_MeshEditor::AXIS:
3129 aTrsf.SetMirror( gp_Ax1( P, V ));
3132 aTrsf.SetMirror( gp_Ax2( P, V ));
3135 TIDSortedElemSet copyElements;
3136 TIDSortedElemSet* workElements = & theElements;
3138 if ( myIsPreviewMode )
3140 TPreviewMesh * tmpMesh = getPreviewMesh();
3141 tmpMesh->Copy( theElements, copyElements);
3142 if ( !theCopy && !theTargetMesh )
3144 TIDSortedElemSet elemsAround, elemsAroundCopy;
3145 getElementsAround( theElements, getMeshDS(), elemsAround );
3146 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3148 workElements = & copyElements;
3149 theMakeGroups = false;
3152 ::SMESH_MeshEditor::PGroupIDs groupIds =
3153 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3155 if ( !myIsPreviewMode )
3157 if ( theTargetMesh )
3158 theTargetMesh->GetMeshDS()->Modified();
3160 declareMeshModified( /*isReComputeSafe=*/false );
3163 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3165 SMESH_CATCH( SMESH::throwCorbaException );
3169 //=======================================================================
3172 //=======================================================================
3174 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3175 const SMESH::AxisStruct & theAxis,
3176 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3177 CORBA::Boolean theCopy)
3178 throw (SALOME::SALOME_Exception)
3180 if ( !myIsPreviewMode ) {
3181 TPythonDump() << this << ".Mirror( "
3182 << theIDsOfElements << ", "
3184 << mirrorTypeName(theMirrorType) << ", "
3187 if ( theIDsOfElements.length() > 0 )
3189 TIDSortedElemSet elements;
3190 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3191 mirror(elements, theAxis, theMirrorType, theCopy, false);
3196 //=======================================================================
3197 //function : MirrorObject
3199 //=======================================================================
3201 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3202 const SMESH::AxisStruct & theAxis,
3203 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3204 CORBA::Boolean theCopy)
3205 throw (SALOME::SALOME_Exception)
3207 if ( !myIsPreviewMode ) {
3208 TPythonDump() << this << ".MirrorObject( "
3209 << theObject << ", "
3211 << mirrorTypeName(theMirrorType) << ", "
3214 TIDSortedElemSet elements;
3216 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3218 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3219 mirror(elements, theAxis, theMirrorType, theCopy, false);
3222 //=======================================================================
3223 //function : MirrorMakeGroups
3225 //=======================================================================
3227 SMESH::ListOfGroups*
3228 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3229 const SMESH::AxisStruct& theMirror,
3230 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3231 throw (SALOME::SALOME_Exception)
3233 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3235 SMESH::ListOfGroups * aGroups = 0;
3236 if ( theIDsOfElements.length() > 0 )
3238 TIDSortedElemSet elements;
3239 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3240 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3242 if (!myIsPreviewMode) {
3243 dumpGroupsList(aPythonDump, aGroups);
3244 aPythonDump << this << ".MirrorMakeGroups( "
3245 << theIDsOfElements << ", "
3246 << theMirror << ", "
3247 << mirrorTypeName(theMirrorType) << " )";
3252 //=======================================================================
3253 //function : MirrorObjectMakeGroups
3255 //=======================================================================
3257 SMESH::ListOfGroups*
3258 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3259 const SMESH::AxisStruct& theMirror,
3260 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3261 throw (SALOME::SALOME_Exception)
3263 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3265 SMESH::ListOfGroups * aGroups = 0;
3266 TIDSortedElemSet elements;
3267 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3268 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3270 if (!myIsPreviewMode)
3272 dumpGroupsList(aPythonDump,aGroups);
3273 aPythonDump << this << ".MirrorObjectMakeGroups( "
3274 << theObject << ", "
3275 << theMirror << ", "
3276 << mirrorTypeName(theMirrorType) << " )";
3281 //=======================================================================
3282 //function : MirrorMakeMesh
3284 //=======================================================================
3286 SMESH::SMESH_Mesh_ptr
3287 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3288 const SMESH::AxisStruct& theMirror,
3289 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3290 CORBA::Boolean theCopyGroups,
3291 const char* theMeshName)
3292 throw (SALOME::SALOME_Exception)
3294 SMESH_Mesh_i* mesh_i;
3295 SMESH::SMESH_Mesh_var mesh;
3296 { // open new scope to dump "MakeMesh" command
3297 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3299 TPythonDump pydump; // to prevent dump at mesh creation
3301 mesh = makeMesh( theMeshName );
3302 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3303 if (mesh_i && theIDsOfElements.length() > 0 )
3305 TIDSortedElemSet elements;
3306 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3307 mirror(elements, theMirror, theMirrorType,
3308 false, theCopyGroups, & mesh_i->GetImpl());
3309 mesh_i->CreateGroupServants();
3312 if (!myIsPreviewMode) {
3313 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3314 << theIDsOfElements << ", "
3315 << theMirror << ", "
3316 << mirrorTypeName(theMirrorType) << ", "
3317 << theCopyGroups << ", '"
3318 << theMeshName << "' )";
3323 if (!myIsPreviewMode && mesh_i)
3324 mesh_i->GetGroups();
3326 return mesh._retn();
3329 //=======================================================================
3330 //function : MirrorObjectMakeMesh
3332 //=======================================================================
3334 SMESH::SMESH_Mesh_ptr
3335 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3336 const SMESH::AxisStruct& theMirror,
3337 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3338 CORBA::Boolean theCopyGroups,
3339 const char* theMeshName)
3340 throw (SALOME::SALOME_Exception)
3342 SMESH_Mesh_i* mesh_i;
3343 SMESH::SMESH_Mesh_var mesh;
3344 { // open new scope to dump "MakeMesh" command
3345 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3347 TPythonDump pydump; // to prevent dump at mesh creation
3349 mesh = makeMesh( theMeshName );
3350 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3351 TIDSortedElemSet elements;
3353 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3355 mirror(elements, theMirror, theMirrorType,
3356 false, theCopyGroups, & mesh_i->GetImpl());
3357 mesh_i->CreateGroupServants();
3359 if (!myIsPreviewMode) {
3360 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3361 << theObject << ", "
3362 << theMirror << ", "
3363 << mirrorTypeName(theMirrorType) << ", "
3364 << theCopyGroups << ", '"
3365 << theMeshName << "' )";
3370 if (!myIsPreviewMode && mesh_i)
3371 mesh_i->GetGroups();
3373 return mesh._retn();
3376 //=======================================================================
3377 //function : translate
3379 //=======================================================================
3381 SMESH::ListOfGroups*
3382 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3383 const SMESH::DirStruct & theVector,
3384 CORBA::Boolean theCopy,
3386 ::SMESH_Mesh* theTargetMesh)
3387 throw (SALOME::SALOME_Exception)
3392 if ( theTargetMesh )
3396 const SMESH::PointStruct * P = &theVector.PS;
3397 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3399 TIDSortedElemSet copyElements;
3400 TIDSortedElemSet* workElements = &theElements;
3402 if ( myIsPreviewMode )
3404 TPreviewMesh * tmpMesh = getPreviewMesh();
3405 tmpMesh->Copy( theElements, copyElements);
3406 if ( !theCopy && !theTargetMesh )
3408 TIDSortedElemSet elemsAround, elemsAroundCopy;
3409 getElementsAround( theElements, getMeshDS(), elemsAround );
3410 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3412 workElements = & copyElements;
3413 theMakeGroups = false;
3416 ::SMESH_MeshEditor::PGroupIDs groupIds =
3417 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3419 if ( !myIsPreviewMode )
3421 if ( theTargetMesh )
3422 theTargetMesh->GetMeshDS()->Modified();
3424 declareMeshModified( /*isReComputeSafe=*/false );
3427 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3429 SMESH_CATCH( SMESH::throwCorbaException );
3433 //=======================================================================
3434 //function : Translate
3436 //=======================================================================
3438 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3439 const SMESH::DirStruct & theVector,
3440 CORBA::Boolean theCopy)
3441 throw (SALOME::SALOME_Exception)
3443 if (!myIsPreviewMode) {
3444 TPythonDump() << this << ".Translate( "
3445 << theIDsOfElements << ", "
3446 << theVector << ", "
3449 if (theIDsOfElements.length()) {
3450 TIDSortedElemSet elements;
3451 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3452 translate(elements, theVector, theCopy, false);
3456 //=======================================================================
3457 //function : TranslateObject
3459 //=======================================================================
3461 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3462 const SMESH::DirStruct & theVector,
3463 CORBA::Boolean theCopy)
3464 throw (SALOME::SALOME_Exception)
3466 if (!myIsPreviewMode) {
3467 TPythonDump() << this << ".TranslateObject( "
3468 << theObject << ", "
3469 << theVector << ", "
3472 TIDSortedElemSet elements;
3474 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3476 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3477 translate(elements, theVector, theCopy, false);
3480 //=======================================================================
3481 //function : TranslateMakeGroups
3483 //=======================================================================
3485 SMESH::ListOfGroups*
3486 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3487 const SMESH::DirStruct& theVector)
3488 throw (SALOME::SALOME_Exception)
3490 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3492 SMESH::ListOfGroups * aGroups = 0;
3493 if (theIDsOfElements.length()) {
3494 TIDSortedElemSet elements;
3495 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3496 aGroups = translate(elements,theVector,true,true);
3498 if (!myIsPreviewMode) {
3499 dumpGroupsList(aPythonDump, aGroups);
3500 aPythonDump << this << ".TranslateMakeGroups( "
3501 << theIDsOfElements << ", "
3502 << theVector << " )";
3507 //=======================================================================
3508 //function : TranslateObjectMakeGroups
3510 //=======================================================================
3512 SMESH::ListOfGroups*
3513 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3514 const SMESH::DirStruct& theVector)
3515 throw (SALOME::SALOME_Exception)
3517 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3519 SMESH::ListOfGroups * aGroups = 0;
3520 TIDSortedElemSet elements;
3521 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3522 aGroups = translate(elements, theVector, true, true);
3524 if (!myIsPreviewMode) {
3525 dumpGroupsList(aPythonDump, aGroups);
3526 aPythonDump << this << ".TranslateObjectMakeGroups( "
3527 << theObject << ", "
3528 << theVector << " )";
3533 //=======================================================================
3534 //function : TranslateMakeMesh
3536 //=======================================================================
3538 SMESH::SMESH_Mesh_ptr
3539 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3540 const SMESH::DirStruct& theVector,
3541 CORBA::Boolean theCopyGroups,
3542 const char* theMeshName)
3543 throw (SALOME::SALOME_Exception)
3545 SMESH_Mesh_i* mesh_i;
3546 SMESH::SMESH_Mesh_var mesh;
3548 { // open new scope to dump "MakeMesh" command
3549 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3551 TPythonDump pydump; // to prevent dump at mesh creation
3553 mesh = makeMesh( theMeshName );
3554 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3556 if ( mesh_i && theIDsOfElements.length() )
3558 TIDSortedElemSet elements;
3559 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3560 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3561 mesh_i->CreateGroupServants();
3564 if ( !myIsPreviewMode ) {
3565 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3566 << theIDsOfElements << ", "
3567 << theVector << ", "
3568 << theCopyGroups << ", '"
3569 << theMeshName << "' )";
3574 if (!myIsPreviewMode && mesh_i)
3575 mesh_i->GetGroups();
3577 return mesh._retn();
3580 //=======================================================================
3581 //function : TranslateObjectMakeMesh
3583 //=======================================================================
3585 SMESH::SMESH_Mesh_ptr
3586 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3587 const SMESH::DirStruct& theVector,
3588 CORBA::Boolean theCopyGroups,
3589 const char* theMeshName)
3590 throw (SALOME::SALOME_Exception)
3593 SMESH_Mesh_i* mesh_i;
3594 SMESH::SMESH_Mesh_var mesh;
3595 { // open new scope to dump "MakeMesh" command
3596 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3598 TPythonDump pydump; // to prevent dump at mesh creation
3599 mesh = makeMesh( theMeshName );
3600 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3602 TIDSortedElemSet elements;
3604 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3606 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3607 mesh_i->CreateGroupServants();
3609 if ( !myIsPreviewMode ) {
3610 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3611 << theObject << ", "
3612 << theVector << ", "
3613 << theCopyGroups << ", '"
3614 << theMeshName << "' )";
3619 if (!myIsPreviewMode && mesh_i)
3620 mesh_i->GetGroups();
3622 return mesh._retn();
3624 SMESH_CATCH( SMESH::throwCorbaException );
3628 //=======================================================================
3631 //=======================================================================
3633 SMESH::ListOfGroups*
3634 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3635 const SMESH::AxisStruct & theAxis,
3636 CORBA::Double theAngle,
3637 CORBA::Boolean theCopy,
3639 ::SMESH_Mesh* theTargetMesh)
3640 throw (SALOME::SALOME_Exception)
3645 if ( theTargetMesh )
3648 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3649 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3652 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3654 TIDSortedElemSet copyElements;
3655 TIDSortedElemSet* workElements = &theElements;
3656 if ( myIsPreviewMode ) {
3657 TPreviewMesh * tmpMesh = getPreviewMesh();
3658 tmpMesh->Copy( theElements, copyElements );
3659 if ( !theCopy && !theTargetMesh )
3661 TIDSortedElemSet elemsAround, elemsAroundCopy;
3662 getElementsAround( theElements, getMeshDS(), elemsAround );
3663 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3665 workElements = ©Elements;
3666 theMakeGroups = false;
3669 ::SMESH_MeshEditor::PGroupIDs groupIds =
3670 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3672 if ( !myIsPreviewMode)
3674 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3675 else declareMeshModified( /*isReComputeSafe=*/false );
3678 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3680 SMESH_CATCH( SMESH::throwCorbaException );
3684 //=======================================================================
3687 //=======================================================================
3689 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3690 const SMESH::AxisStruct & theAxis,
3691 CORBA::Double theAngle,
3692 CORBA::Boolean theCopy)
3693 throw (SALOME::SALOME_Exception)
3695 if (!myIsPreviewMode) {
3696 TPythonDump() << this << ".Rotate( "
3697 << theIDsOfElements << ", "
3699 << TVar( theAngle ) << ", "
3702 if (theIDsOfElements.length() > 0)
3704 TIDSortedElemSet elements;
3705 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3706 rotate(elements,theAxis,theAngle,theCopy,false);
3710 //=======================================================================
3711 //function : RotateObject
3713 //=======================================================================
3715 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3716 const SMESH::AxisStruct & theAxis,
3717 CORBA::Double theAngle,
3718 CORBA::Boolean theCopy)
3719 throw (SALOME::SALOME_Exception)
3721 if ( !myIsPreviewMode ) {
3722 TPythonDump() << this << ".RotateObject( "
3723 << theObject << ", "
3725 << TVar( theAngle ) << ", "
3728 TIDSortedElemSet elements;
3729 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3730 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3731 rotate(elements,theAxis,theAngle,theCopy,false);
3734 //=======================================================================
3735 //function : RotateMakeGroups
3737 //=======================================================================
3739 SMESH::ListOfGroups*
3740 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3741 const SMESH::AxisStruct& theAxis,
3742 CORBA::Double theAngle)
3743 throw (SALOME::SALOME_Exception)
3745 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3747 SMESH::ListOfGroups * aGroups = 0;
3748 if (theIDsOfElements.length() > 0)
3750 TIDSortedElemSet elements;
3751 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3752 aGroups = rotate(elements,theAxis,theAngle,true,true);
3754 if (!myIsPreviewMode) {
3755 dumpGroupsList(aPythonDump, aGroups);
3756 aPythonDump << this << ".RotateMakeGroups( "
3757 << theIDsOfElements << ", "
3759 << TVar( theAngle ) << " )";
3764 //=======================================================================
3765 //function : RotateObjectMakeGroups
3767 //=======================================================================
3769 SMESH::ListOfGroups*
3770 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3771 const SMESH::AxisStruct& theAxis,
3772 CORBA::Double theAngle)
3773 throw (SALOME::SALOME_Exception)
3775 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3777 SMESH::ListOfGroups * aGroups = 0;
3778 TIDSortedElemSet elements;
3779 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3780 aGroups = rotate(elements, theAxis, theAngle, true, true);
3782 if (!myIsPreviewMode) {
3783 dumpGroupsList(aPythonDump, aGroups);
3784 aPythonDump << this << ".RotateObjectMakeGroups( "
3785 << theObject << ", "
3787 << TVar( theAngle ) << " )";
3792 //=======================================================================
3793 //function : RotateMakeMesh
3795 //=======================================================================
3797 SMESH::SMESH_Mesh_ptr
3798 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3799 const SMESH::AxisStruct& theAxis,
3800 CORBA::Double theAngleInRadians,
3801 CORBA::Boolean theCopyGroups,
3802 const char* theMeshName)
3803 throw (SALOME::SALOME_Exception)
3806 SMESH::SMESH_Mesh_var mesh;
3807 SMESH_Mesh_i* mesh_i;
3809 { // open new scope to dump "MakeMesh" command
3810 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3812 TPythonDump pydump; // to prevent dump at mesh creation
3814 mesh = makeMesh( theMeshName );
3815 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3817 if ( mesh_i && theIDsOfElements.length() > 0 )
3819 TIDSortedElemSet elements;
3820 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3821 rotate(elements, theAxis, theAngleInRadians,
3822 false, theCopyGroups, & mesh_i->GetImpl());
3823 mesh_i->CreateGroupServants();
3825 if ( !myIsPreviewMode ) {
3826 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3827 << theIDsOfElements << ", "
3829 << TVar( theAngleInRadians ) << ", "
3830 << theCopyGroups << ", '"
3831 << theMeshName << "' )";
3836 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3837 mesh_i->GetGroups();
3839 return mesh._retn();
3841 SMESH_CATCH( SMESH::throwCorbaException );
3845 //=======================================================================
3846 //function : RotateObjectMakeMesh
3848 //=======================================================================
3850 SMESH::SMESH_Mesh_ptr
3851 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3852 const SMESH::AxisStruct& theAxis,
3853 CORBA::Double theAngleInRadians,
3854 CORBA::Boolean theCopyGroups,
3855 const char* theMeshName)
3856 throw (SALOME::SALOME_Exception)
3859 SMESH::SMESH_Mesh_var mesh;
3860 SMESH_Mesh_i* mesh_i;
3862 {// open new scope to dump "MakeMesh" command
3863 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3865 TPythonDump pydump; // to prevent dump at mesh creation
3866 mesh = makeMesh( theMeshName );
3867 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3869 TIDSortedElemSet elements;
3871 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3873 rotate(elements, theAxis, theAngleInRadians,
3874 false, theCopyGroups, & mesh_i->GetImpl());
3875 mesh_i->CreateGroupServants();
3877 if ( !myIsPreviewMode ) {
3878 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3879 << theObject << ", "
3881 << TVar( theAngleInRadians ) << ", "
3882 << theCopyGroups << ", '"
3883 << theMeshName << "' )";
3888 if (!myIsPreviewMode && mesh_i)
3889 mesh_i->GetGroups();
3891 return mesh._retn();
3893 SMESH_CATCH( SMESH::throwCorbaException );
3897 //=======================================================================
3900 //=======================================================================
3902 SMESH::ListOfGroups*
3903 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3904 const SMESH::PointStruct& thePoint,
3905 const SMESH::double_array& theScaleFact,
3906 CORBA::Boolean theCopy,
3908 ::SMESH_Mesh* theTargetMesh)
3909 throw (SALOME::SALOME_Exception)
3913 if ( theScaleFact.length() < 1 )
3914 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3915 if ( theScaleFact.length() == 2 )
3916 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3918 if ( theTargetMesh )
3921 TIDSortedElemSet elements;
3922 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3923 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3928 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3929 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3933 // fight against orthogonalization
3934 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3935 // 0, S[1], 0, thePoint.y * (1-S[1]),
3936 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3937 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3938 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3939 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3940 loc.SetCoord( thePoint.x * (1-S[0]),
3941 thePoint.y * (1-S[1]),
3942 thePoint.z * (1-S[2]));
3943 M.SetDiagonal( S[0], S[1], S[2] );
3945 TIDSortedElemSet copyElements;
3946 TIDSortedElemSet* workElements = &elements;
3947 if ( myIsPreviewMode )
3949 TPreviewMesh * tmpMesh = getPreviewMesh();
3950 tmpMesh->Copy( elements, copyElements);
3951 if ( !theCopy && !theTargetMesh )
3953 TIDSortedElemSet elemsAround, elemsAroundCopy;
3954 getElementsAround( elements, getMeshDS(), elemsAround );
3955 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3957 workElements = & copyElements;
3958 theMakeGroups = false;
3961 ::SMESH_MeshEditor::PGroupIDs groupIds =
3962 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3964 if ( !myIsPreviewMode )
3966 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3967 else declareMeshModified( /*isReComputeSafe=*/false );
3969 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3971 SMESH_CATCH( SMESH::throwCorbaException );
3975 //=======================================================================
3978 //=======================================================================
3980 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3981 const SMESH::PointStruct& thePoint,
3982 const SMESH::double_array& theScaleFact,
3983 CORBA::Boolean theCopy)
3984 throw (SALOME::SALOME_Exception)
3986 if ( !myIsPreviewMode ) {
3987 TPythonDump() << this << ".Scale( "
3988 << theObject << ", "
3990 << TVar( theScaleFact ) << ", "
3993 scale(theObject, thePoint, theScaleFact, theCopy, false);
3997 //=======================================================================
3998 //function : ScaleMakeGroups
4000 //=======================================================================
4002 SMESH::ListOfGroups*
4003 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
4004 const SMESH::PointStruct& thePoint,
4005 const SMESH::double_array& theScaleFact)
4006 throw (SALOME::SALOME_Exception)
4008 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4010 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
4011 if (!myIsPreviewMode) {
4012 dumpGroupsList(aPythonDump, aGroups);
4013 aPythonDump << this << ".Scale("
4016 << TVar( theScaleFact ) << ",True,True)";
4022 //=======================================================================
4023 //function : ScaleMakeMesh
4025 //=======================================================================
4027 SMESH::SMESH_Mesh_ptr
4028 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4029 const SMESH::PointStruct& thePoint,
4030 const SMESH::double_array& theScaleFact,
4031 CORBA::Boolean theCopyGroups,
4032 const char* theMeshName)
4033 throw (SALOME::SALOME_Exception)
4035 SMESH_Mesh_i* mesh_i;
4036 SMESH::SMESH_Mesh_var mesh;
4037 { // open new scope to dump "MakeMesh" command
4038 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4040 TPythonDump pydump; // to prevent dump at mesh creation
4041 mesh = makeMesh( theMeshName );
4042 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4046 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4047 mesh_i->CreateGroupServants();
4049 if ( !myIsPreviewMode )
4050 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4051 << theObject << ", "
4053 << TVar( theScaleFact ) << ", "
4054 << theCopyGroups << ", '"
4055 << theMeshName << "' )";
4059 if (!myIsPreviewMode && mesh_i)
4060 mesh_i->GetGroups();
4062 return mesh._retn();
4065 //================================================================================
4067 * \brief Make an offset mesh from a source 2D mesh
4068 * \param [inout] theObject - source mesh. New elements are added to this mesh
4069 * if \a theMeshName is empty.
4070 * \param [in] theValue - offset value
4071 * \param [in] theCopyGroups - to generate groups
4072 * \param [in] theMeshName - optional name of a new mesh
4073 * \param [out] theGroups - new groups
4074 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
4076 //================================================================================
4078 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4079 CORBA::Double theValue,
4080 CORBA::Boolean theCopyGroups,
4081 CORBA::Boolean theCopyElements,
4082 const char* theMeshName,
4083 SMESH::ListOfGroups_out theGroups)
4084 throw (SALOME::SALOME_Exception)
4089 SMESHDS_Mesh* aMeshDS = getMeshDS();
4091 SMESH::SMESH_Mesh_var mesh_var;
4092 ::SMESH_MeshEditor::PGroupIDs groupIds;
4096 TIDSortedElemSet elements, copyElements;
4097 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4098 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4101 SMESH_Mesh* tgtMesh = 0;
4102 if ( myIsPreviewMode )
4104 TPreviewMesh * tmpMesh = getPreviewMesh();
4106 tmpMesh->Copy( elements, copyElements );
4107 elements.swap( copyElements );
4108 theCopyGroups = false;
4109 theCopyElements = false;
4114 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4115 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4116 tgtMesh = & mesh_i->GetImpl();
4118 groupIds = getEditor().Offset( elements, theValue, tgtMesh,
4119 theCopyGroups, theCopyElements, !myIsPreviewMode );
4121 tgtMesh->GetMeshDS()->Modified();
4124 if ( myIsPreviewMode )
4126 //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4130 if ( *theMeshName && mesh_var->NbFaces() == 0 )
4132 // new mesh empty, remove it
4133 SALOMEDS::Study_var study = SMESH_Gen_i::getStudyServant();
4134 SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
4135 SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::ObjectToSObject( mesh_var );
4136 builder->RemoveObjectWithChildren( meshSO );
4137 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4139 if ( !groupIds ) // nothing changed in the current mesh
4140 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4142 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4144 // result of Offset() is a tuple (mesh, groups)
4145 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4146 else pyDump << mesh_var << ", ";
4147 pyDump << theGroups << " = " << this << ".Offset( "
4148 << theObject << ", "
4150 << theCopyGroups << ", "
4151 << theCopyElements << ", "
4152 << "'" << theMeshName<< "')";
4155 return mesh_var._retn();
4157 SMESH_CATCH( SMESH::throwCorbaException );
4158 return SMESH::SMESH_Mesh::_nil();
4161 //=======================================================================
4162 //function : findCoincidentNodes
4164 //=======================================================================
4166 void SMESH_MeshEditor_i::
4167 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4168 CORBA::Double Tolerance,
4169 SMESH::array_of_long_array_out GroupsOfNodes,
4170 CORBA::Boolean SeparateCornersAndMedium)
4172 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4173 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4175 GroupsOfNodes = new SMESH::array_of_long_array;
4176 GroupsOfNodes->length( aListOfListOfNodes.size() );
4177 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4178 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4180 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4181 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4182 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4183 aGroup.length( aListOfNodes.size() );
4184 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4185 aGroup[ j ] = (*lIt)->GetID();
4189 //=======================================================================
4190 //function : FindCoincidentNodes
4192 //=======================================================================
4194 void SMESH_MeshEditor_i::
4195 FindCoincidentNodes (CORBA::Double Tolerance,
4196 SMESH::array_of_long_array_out GroupsOfNodes,
4197 CORBA::Boolean SeparateCornersAndMedium)
4198 throw (SALOME::SALOME_Exception)
4203 TIDSortedNodeSet nodes; // no input nodes
4204 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4206 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4207 << Tolerance << ", "
4208 << SeparateCornersAndMedium << " )";
4210 SMESH_CATCH( SMESH::throwCorbaException );
4213 //=======================================================================
4214 //function : FindCoincidentNodesOnPart
4216 //=======================================================================
4218 void SMESH_MeshEditor_i::
4219 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4220 CORBA::Double Tolerance,
4221 SMESH::array_of_long_array_out GroupsOfNodes,
4222 CORBA::Boolean SeparateCornersAndMedium)
4223 throw (SALOME::SALOME_Exception)
4228 TIDSortedNodeSet nodes;
4229 prepareIdSource( theObject );
4230 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4232 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4234 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4236 << Tolerance << ", "
4237 << SeparateCornersAndMedium << " )";
4239 SMESH_CATCH( SMESH::throwCorbaException );
4242 //================================================================================
4244 * \brief Finds nodes coincident with Tolerance within Objects excluding nodes within
4245 * ExceptSubMeshOrGroups
4247 //================================================================================
4249 void SMESH_MeshEditor_i::
4250 FindCoincidentNodesOnPartBut(const SMESH::ListOfIDSources& theObjects,
4251 CORBA::Double theTolerance,
4252 SMESH::array_of_long_array_out theGroupsOfNodes,
4253 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4254 CORBA::Boolean theSeparateCornersAndMedium)
4255 throw (SALOME::SALOME_Exception)
4260 TIDSortedNodeSet nodes;
4261 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4263 prepareIdSource( theObjects[i] );
4264 idSourceToNodeSet( theObjects[i], getMeshDS(), nodes );
4266 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4268 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4270 while ( nodeIt->more() )
4271 nodes.erase( cast2Node( nodeIt->next() ));
4273 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4275 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4276 << theObjects <<", "
4277 << theTolerance << ", "
4278 << theExceptSubMeshOrGroups << ", "
4279 << theSeparateCornersAndMedium << " )";
4281 SMESH_CATCH( SMESH::throwCorbaException );
4284 //=======================================================================
4285 //function : MergeNodes
4287 //=======================================================================
4289 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4290 const SMESH::ListOfIDSources& NodesToKeep,
4291 CORBA::Boolean AvoidMakingHoles)
4292 throw (SALOME::SALOME_Exception)
4297 SMESHDS_Mesh* aMesh = getMeshDS();
4299 TPythonDump aTPythonDump;
4300 aTPythonDump << this << ".MergeNodes([";
4302 TIDSortedNodeSet setOfNodesToKeep;
4303 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4305 prepareIdSource( NodesToKeep[i] );
4306 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ))
4307 while ( nodeIt->more() )
4308 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4311 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4312 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4314 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4315 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4316 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4317 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4319 CORBA::Long index = aNodeGroup[ j ];
4320 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4322 if ( setOfNodesToKeep.count( node ))
4323 aListOfNodes.push_front( node );
4325 aListOfNodes.push_back( node );
4328 if ( aListOfNodes.size() < 2 )
4329 aListOfListOfNodes.pop_back();
4331 if ( i > 0 ) aTPythonDump << ", ";
4332 aTPythonDump << aNodeGroup;
4335 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4337 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4339 declareMeshModified( /*isReComputeSafe=*/false );
4341 SMESH_CATCH( SMESH::throwCorbaException );
4344 //=======================================================================
4345 //function : FindEqualElements
4347 //=======================================================================
4349 void SMESH_MeshEditor_i::FindEqualElements(const SMESH::ListOfIDSources& theObjects,
4350 const SMESH::ListOfIDSources& theExceptObjects,
4351 SMESH::array_of_long_array_out theGroupsOfElementsID)
4352 throw (SALOME::SALOME_Exception)
4357 theGroupsOfElementsID = new SMESH::array_of_long_array;
4359 TIDSortedElemSet elems;
4360 bool hasOkObject = false;
4361 bool emptyIfIsMesh= ( theObjects.length() == 1 && theExceptObjects.length() == 0 );
4363 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4365 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( theObjects[i] );
4366 if ( !( !group->_is_nil() && group->GetType() == SMESH::NODE ))
4367 if ( idSourceToSet( theObjects[i], getMeshDS(), elems, SMDSAbs_All, emptyIfIsMesh ))
4373 for ( CORBA::ULong i = 0; i < theExceptObjects.length(); ++i )
4375 if ( SMDS_ElemIteratorPtr elemIt = myMesh_i->GetElements( theExceptObjects[i], SMESH::ALL ))
4376 while ( elemIt->more() )
4377 elems.erase( elemIt->next() );
4380 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4381 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4383 theGroupsOfElementsID->length( aListOfListOfElementsID.size() );
4385 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4386 aListOfListOfElementsID.begin();
4387 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4389 SMESH::long_array& aGroup = (*theGroupsOfElementsID)[ j ];
4390 list<int>& listOfIDs = *arraysIt;
4391 aGroup.length( listOfIDs.size() );
4392 list<int>::iterator idIt = listOfIDs.begin();
4393 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4394 aGroup[ k ] = *idIt;
4397 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4398 << theObjects << ", "
4399 << theExceptObjects << " )";
4402 SMESH_CATCH( SMESH::throwCorbaException );
4405 //=======================================================================
4406 //function : MergeElements
4408 //=======================================================================
4410 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& theGroupsOfElementsID,
4411 const SMESH::ListOfIDSources& theElementsToKeep)
4412 throw (SALOME::SALOME_Exception)
4417 TPythonDump aTPythonDump;
4418 aTPythonDump << this << ".MergeElements( [";
4420 NCollection_Map< int > idsToKeep;
4421 for ( CORBA::ULong i = 0; i < theElementsToKeep.length(); i++ )
4423 if ( CORBA::is_nil( theElementsToKeep[i] ))
4425 SMESH::array_of_ElementType_var elemTypes = theElementsToKeep[i]->GetTypes();
4426 if ( elemTypes->length() == 1 && elemTypes[0] == SMESH::NODE )
4428 SMESH::long_array_var elementsId = theElementsToKeep[i]->GetIDs();
4429 for ( CORBA::ULong j = 0; j < elementsId->length(); ++j )
4430 idsToKeep.Add( elementsId[ j ]);
4433 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4435 for ( CORBA::ULong i = 0; i < theGroupsOfElementsID.length(); i++ )
4437 const SMESH::long_array& anElemsIDGroup = theGroupsOfElementsID[ i ];
4438 aListOfListOfElementsID.push_back( list< int >() );
4439 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4440 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ )
4442 CORBA::Long id = anElemsIDGroup[ j ];
4443 if ( idsToKeep.Contains( id )) aListOfElemsID.push_front( id );
4444 else aListOfElemsID.push_back( id );
4446 if ( aListOfElemsID.size() < 2 )
4447 aListOfListOfElementsID.pop_back();
4448 if ( i > 0 ) aTPythonDump << ", ";
4449 aTPythonDump << anElemsIDGroup;
4452 getEditor().MergeElements(aListOfListOfElementsID);
4454 declareMeshModified( /*isReComputeSafe=*/true );
4456 aTPythonDump << "], " << theElementsToKeep << " )";
4458 SMESH_CATCH( SMESH::throwCorbaException );
4461 //=======================================================================
4462 //function : MergeEqualElements
4464 //=======================================================================
4466 void SMESH_MeshEditor_i::MergeEqualElements()
4467 throw (SALOME::SALOME_Exception)
4472 getEditor().MergeEqualElements();
4474 declareMeshModified( /*isReComputeSafe=*/true );
4476 TPythonDump() << this << ".MergeEqualElements()";
4478 SMESH_CATCH( SMESH::throwCorbaException );
4481 //=============================================================================
4483 * Move the node to a given point
4485 //=============================================================================
4487 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4491 throw (SALOME::SALOME_Exception)
4494 initData(/*deleteSearchers=*/false);
4496 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4500 if ( theNodeSearcher )
4501 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4503 if ( myIsPreviewMode ) // make preview data
4505 // in a preview mesh, make edges linked to a node
4506 TPreviewMesh& tmpMesh = *getPreviewMesh();
4507 TIDSortedElemSet linkedNodes;
4508 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4509 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4510 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4511 for ( ; nIt != linkedNodes.end(); ++nIt )
4513 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4514 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4518 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4519 // fill preview data
4521 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4522 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4524 getMeshDS()->MoveNode(node, x, y, z);
4526 if ( !myIsPreviewMode )
4528 // Update Python script
4529 TPythonDump() << "isDone = " << this << ".MoveNode( "
4530 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4531 declareMeshModified( /*isReComputeSafe=*/false );
4534 SMESH_CATCH( SMESH::throwCorbaException );
4539 //================================================================================
4541 * \brief Return ID of node closest to a given point
4543 //================================================================================
4545 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4548 throw (SALOME::SALOME_Exception)
4551 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4553 if ( !theNodeSearcher ) {
4554 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4557 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4558 return node->GetID();
4560 SMESH_CATCH( SMESH::throwCorbaException );
4564 //================================================================================
4566 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4567 * move the node closest to the point to point's location and return ID of the node
4569 //================================================================================
4571 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4574 CORBA::Long theNodeID)
4575 throw (SALOME::SALOME_Exception)
4578 // We keep theNodeSearcher until any mesh modification:
4579 // 1) initData() deletes theNodeSearcher at any edition,
4580 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4582 initData(/*deleteSearchers=*/false);
4584 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4586 int nodeID = theNodeID;
4587 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4588 if ( !node ) // preview moving node
4590 if ( !theNodeSearcher ) {
4591 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4594 node = theNodeSearcher->FindClosestTo( p );
4597 nodeID = node->GetID();
4598 if ( myIsPreviewMode ) // make preview data
4600 // in a preview mesh, make edges linked to a node
4601 TPreviewMesh tmpMesh = *getPreviewMesh();
4602 TIDSortedElemSet linkedNodes;
4603 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4604 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4605 for ( ; nIt != linkedNodes.end(); ++nIt )
4607 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4608 tmpMesh.Copy( &edge );
4611 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4613 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4614 // fill preview data
4616 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4618 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4622 getMeshDS()->MoveNode(node, x, y, z);
4626 if ( !myIsPreviewMode )
4628 TPythonDump() << "nodeID = " << this
4629 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4630 << ", " << nodeID << " )";
4632 declareMeshModified( /*isReComputeSafe=*/false );
4637 SMESH_CATCH( SMESH::throwCorbaException );
4641 //=======================================================================
4643 * Return elements of given type where the given point is IN or ON.
4645 * 'ALL' type means elements of any type excluding nodes
4647 //=======================================================================
4649 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4652 SMESH::ElementType type)
4653 throw (SALOME::SALOME_Exception)
4656 SMESH::long_array_var res = new SMESH::long_array;
4657 vector< const SMDS_MeshElement* > foundElems;
4659 theSearchersDeleter.Set( myMesh );
4660 if ( !theElementSearcher ) {
4661 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4663 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4664 SMDSAbs_ElementType( type ),
4666 res->length( foundElems.size() );
4667 for ( size_t i = 0; i < foundElems.size(); ++i )
4668 res[i] = foundElems[i]->GetID();
4672 SMESH_CATCH( SMESH::throwCorbaException );
4676 //=======================================================================
4677 //function : FindAmongElementsByPoint
4678 //purpose : Searching among the given elements, return elements of given type
4679 // where the given point is IN or ON.
4680 // 'ALL' type means elements of any type excluding nodes
4681 //=======================================================================
4684 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4688 SMESH::ElementType type)
4689 throw (SALOME::SALOME_Exception)
4692 SMESH::long_array_var res = new SMESH::long_array;
4694 prepareIdSource( elementIDs );
4695 if ( type != SMESH::NODE )
4697 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4698 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4699 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4700 type != types[0] ) // but search of elements of dim > 0
4704 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4705 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4706 if ( mesh_i != myMesh_i )
4708 SMESH::SMESH_MeshEditor_var editor=
4709 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4710 return editor->FindAmongElementsByPoint( elementIDs, x,y,z, type );
4713 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4714 return FindElementsByPoint( x,y,z, type );
4716 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4718 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4719 if ( !theElementSearcher )
4721 // create a searcher from elementIDs
4722 SMDS_ElemIteratorPtr elemIt;
4723 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( elementIDs ))
4725 //prepareIdSource( elementIDs );
4726 elemIt = myMesh_i->GetElements( elementIDs, type );
4730 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4733 vector< const SMDS_MeshElement* > foundElems;
4735 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4736 SMDSAbs_ElementType( type ),
4738 res->length( foundElems.size() );
4739 for ( size_t i = 0; i < foundElems.size(); ++i )
4740 res[i] = foundElems[i]->GetID();
4744 SMESH_CATCH( SMESH::throwCorbaException );
4748 //=======================================================================
4749 //function : ProjectPoint
4750 //purpose : Project a point to a mesh object.
4751 // Return ID of an element of given type where the given point is projected
4752 // and coordinates of the projection point.
4753 // In the case if nothing found, return -1 and []
4754 //=======================================================================
4756 CORBA::Long SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
4759 SMESH::ElementType type,
4760 SMESH::SMESH_IDSource_ptr meshObject,
4761 SMESH::double_array_out projecton)
4762 throw (SALOME::SALOME_Exception)
4764 if ( CORBA::is_nil( meshObject ))
4765 THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
4769 SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
4770 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4771 if ( mesh_i != myMesh_i )
4773 SMESH::SMESH_MeshEditor_var editor=
4774 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4775 return editor->ProjectPoint( x,y,z, type, meshObject, projecton );
4779 theSearchersDeleter.Set( myMesh, getPartIOR( meshObject, type ));
4780 if ( !theElementSearcher )
4782 // create a searcher from meshObject
4784 SMDS_ElemIteratorPtr elemIt;
4785 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
4787 prepareIdSource( meshObject );
4788 elemIt = myMesh_i->GetElements( meshObject, type );
4792 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4795 const SMDS_MeshElement* elem = 0;
4796 gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
4797 SMDSAbs_ElementType( type ),
4800 projecton = new SMESH::double_array();
4801 if ( elem && !elem->IsNull() )
4803 projecton->length( 3 );
4804 projecton[0] = pProj.X();
4805 projecton[1] = pProj.Y();
4806 projecton[2] = pProj.Z();
4807 return elem->GetID();
4810 SMESH_CATCH( SMESH::throwCorbaException );
4814 //=======================================================================
4815 //function : GetPointState
4816 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4817 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4818 //=======================================================================
4820 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4823 throw (SALOME::SALOME_Exception)
4826 theSearchersDeleter.Set( myMesh );
4827 if ( !theElementSearcher ) {
4828 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4830 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4832 SMESH_CATCH( SMESH::throwCorbaException );
4836 //=======================================================================
4837 //function : IsManifold
4838 //purpose : Check if a 2D mesh is manifold
4839 //=======================================================================
4841 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4842 throw (SALOME::SALOME_Exception)
4844 bool isManifold = true;
4847 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4848 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4850 /*closedOnly=*/true,
4852 SMESH_CATCH( SMESH::throwCorbaException );
4857 //=======================================================================
4858 //function : IsCoherentOrientation2D
4859 //purpose : Check if orientation of 2D elements is coherent
4860 //=======================================================================
4862 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4863 throw (SALOME::SALOME_Exception)
4865 bool isGoodOri = true;
4868 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4869 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4871 /*closedOnly=*/true,
4874 SMESH_CATCH( SMESH::throwCorbaException );
4879 //=======================================================================
4880 //function : Get1DBranches
4881 //purpose : Partition given 1D elements into groups of contiguous edges.
4882 // A node where number of meeting edges != 2 is a group end.
4883 // An optional startNode is used to orient groups it belongs to.
4884 //return : a list of edge groups and a list of corresponding node groups.
4885 // If a group is closed, the first and last nodes of the group are same.
4886 //=======================================================================
4888 SMESH::array_of_long_array*
4889 SMESH_MeshEditor_i::Get1DBranches( SMESH::SMESH_IDSource_ptr theEdges,
4890 CORBA::Long theStartNode,
4891 SMESH::array_of_long_array_out theNodeGroups )
4892 throw (SALOME::SALOME_Exception)
4894 if ( CORBA::is_nil( theEdges ))
4895 THROW_SALOME_CORBA_EXCEPTION("Get1DBranches(): NULL group given", SALOME::BAD_PARAM);
4897 SMESH::array_of_long_array_var edgeGroupArray = new SMESH::array_of_long_array;
4898 theNodeGroups = new SMESH::array_of_long_array;
4902 prepareIdSource( theEdges );
4904 SMESH_MeshAlgos::TElemGroupVector edgeBranches;
4905 SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
4906 SMESH_MeshAlgos::Get1DBranches( SMESH_Mesh_i::GetElements( theEdges, SMESH::EDGE ),
4909 getMeshDS()->FindNode( theStartNode ));
4911 edgeGroupArray->length( edgeBranches.size() );
4912 for ( size_t iG = 0; iG < edgeBranches.size(); ++iG )
4914 edgeGroupArray[ iG ].length( edgeBranches[ iG ].size() );
4915 for ( size_t i = 0; i < edgeBranches[ iG ].size(); ++i )
4916 edgeGroupArray[ iG ][ i ] = edgeBranches[ iG ][ i ]->GetID();
4919 theNodeGroups->length( nodeBranches.size() );
4920 for ( size_t iG = 0; iG < nodeBranches.size(); ++iG )
4922 theNodeGroups[ iG ].length( nodeBranches[ iG ].size() );
4923 for ( size_t i = 0; i < nodeBranches[ iG ].size(); ++i )
4924 theNodeGroups[ iG ][ i ] = nodeBranches[ iG ][ i ]->GetID();
4927 SMESH_CATCH( SMESH::throwCorbaException );
4929 return edgeGroupArray._retn();
4932 //=======================================================================
4933 //function : FindSharpEdges
4934 //purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
4935 //=======================================================================
4937 SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
4938 CORBA::Boolean theAddExisting)
4939 throw (SALOME::SALOME_Exception)
4941 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
4946 std::vector< SMESH_MeshAlgos::Edge > edges =
4947 SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
4949 if ( myIsPreviewMode ) // fill a preview mesh with edges
4951 TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
4952 SMDS_Mesh* meshDS = mesh->GetMeshDS();
4953 for ( size_t i = 0; i < edges.size(); ++i )
4955 SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
4956 SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4957 SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
4958 if ( edges[i]._medium )
4960 xyz1.Set( edges[i]._medium );
4961 SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4962 mesh->GetMeshDS()->AddEdge( n1, n2, nm );
4966 mesh->GetMeshDS()->AddEdge( n1, n2 );
4972 resultEdges->length( edges.size() );
4973 for ( size_t i = 0; i < edges.size(); ++i )
4975 resultEdges[ i ].node1 = edges[i]._node1->GetID();
4976 resultEdges[ i ].node2 = edges[i]._node2->GetID();
4977 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
4980 SMESH_CATCH( SMESH::throwCorbaException );
4981 return resultEdges._retn();
4984 //=======================================================================
4985 //function : FindFreeBorders
4986 //purpose : Returns all or only closed FreeBorder's.
4987 //=======================================================================
4989 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4990 throw (SALOME::SALOME_Exception)
4992 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4995 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4996 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4998 resBorders->length( foundFreeBordes.size() );
4999 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
5001 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
5002 SMESH::FreeBorder& bordOut = resBorders[i];
5003 bordOut.nodeIDs.length( bordNodes.size() );
5004 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
5005 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
5008 SMESH_CATCH( SMESH::throwCorbaException );
5010 return resBorders._retn();
5013 //=======================================================================
5014 //function : FillHole
5015 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
5016 //=======================================================================
5018 SMESH::SMESH_Group_ptr
5019 SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole,
5020 const char* theGroupName)
5021 throw (SALOME::SALOME_Exception)
5025 if ( theHole.nodeIDs.length() < 4 )
5026 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
5027 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
5028 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
5029 "First and last nodes must be same", SALOME::BAD_PARAM);
5031 SMESH_MeshAlgos::TFreeBorder bordNodes;
5032 bordNodes.resize( theHole.nodeIDs.length() );
5033 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
5035 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
5036 if ( !bordNodes[ iN ] )
5037 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
5038 << " does not exist", SALOME::BAD_PARAM);
5043 // prepare a preview mesh
5044 MeshEditor_I::TPreviewMesh* previewMesh = 0;
5045 SMDS_Mesh* meshDS = getMeshDS();
5046 if ( myIsPreviewMode )
5048 // copy faces sharing nodes of theHole
5049 TIDSortedElemSet holeFaces;
5050 previewMesh = getPreviewMesh( SMDSAbs_Face );
5051 for ( size_t i = 0; i < bordNodes.size(); ++i )
5053 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
5054 while ( fIt->more() )
5056 const SMDS_MeshElement* face = fIt->next();
5057 if ( holeFaces.insert( face ).second )
5058 previewMesh->Copy( face );
5060 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
5061 ASSERT( bordNodes[i] );
5063 meshDS = previewMesh->GetMeshDS();
5067 std::vector<const SMDS_MeshElement*> newFaces;
5068 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
5070 if ( myIsPreviewMode )
5073 previewMesh->Clear();
5074 for ( size_t i = 0; i < newFaces.size(); ++i )
5075 previewMesh->Copy( newFaces[i] );
5079 // return new faces via a group
5080 SMESH::SMESH_Group_var group;
5081 if ( theGroupName && theGroupName[0] && !newFaces.empty() )
5083 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5084 for ( CORBA::ULong i = 0; i < groups->length(); ++i )
5086 SMESH::SMESH_GroupBase_var g = groups[ i ];
5087 if ( g->GetType() != SMESH::FACE ) continue;
5088 SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g );
5089 if ( standalone->_is_nil() ) continue;
5090 CORBA::String_var name = g->GetName();
5091 if ( strcmp( theGroupName, name.in() ) == 0 )
5097 if ( group->_is_nil() )
5098 group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName );
5100 if ( !group->_is_nil() )
5102 SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group );
5103 SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() );
5104 for ( size_t i = 0; i < newFaces.size(); ++i )
5105 grpDS->Add( newFaces[ i ]);
5110 getEditor().ClearLastCreated();
5111 SMESH_SequenceOfElemPtr& aSeq =
5112 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
5113 aSeq.swap( newFaces );
5116 if ( group->_is_nil() ) pyDump << "_group = ";
5117 else pyDump << group << " = ";
5118 pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
5120 return group._retn();
5123 SMESH_CATCH( SMESH::throwCorbaException );
5125 return SMESH::SMESH_Group::_nil();
5128 //=======================================================================
5129 //function : convError
5131 //=======================================================================
5133 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5135 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5139 RETCASE( SEW_BORDER1_NOT_FOUND );
5140 RETCASE( SEW_BORDER2_NOT_FOUND );
5141 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5142 RETCASE( SEW_BAD_SIDE_NODES );
5143 RETCASE( SEW_VOLUMES_TO_SPLIT );
5144 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5145 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5146 RETCASE( SEW_BAD_SIDE1_NODES );
5147 RETCASE( SEW_BAD_SIDE2_NODES );
5148 RETCASE( SEW_INTERNAL_ERROR );
5150 return SMESH::SMESH_MeshEditor::SEW_OK;
5153 //=======================================================================
5155 * Returns groups of FreeBorder's coincident within the given tolerance.
5156 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
5157 * to free borders being compared is used.
5159 //=======================================================================
5161 SMESH::CoincidentFreeBorders*
5162 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
5164 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
5168 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
5169 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
5171 // copy free borders
5172 aCFB->borders.length( cfb._borders.size() );
5173 for ( size_t i = 0; i < cfb._borders.size(); ++i )
5175 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
5176 SMESH::FreeBorder& aBRD = aCFB->borders[i];
5177 aBRD.nodeIDs.length( nodes.size() );
5178 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5179 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
5182 // copy coincident parts
5183 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
5184 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
5186 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
5187 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
5188 aGRP.length( grp.size() );
5189 for ( size_t iP = 0; iP < grp.size(); ++iP )
5191 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
5192 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5193 aPART.border = part._border;
5194 aPART.node1 = part._node1;
5195 aPART.node2 = part._node2;
5196 aPART.nodeLast = part._nodeLast;
5199 SMESH_CATCH( SMESH::doNothing );
5201 TPythonDump() << "CoincidentFreeBorders = "
5202 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
5204 return aCFB._retn();
5207 //=======================================================================
5209 * Sew FreeBorder's of each group
5211 //=======================================================================
5213 CORBA::Short SMESH_MeshEditor_i::
5214 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
5215 CORBA::Boolean createPolygons,
5216 CORBA::Boolean createPolyhedra)
5217 throw (SALOME::SALOME_Exception)
5219 CORBA::Short nbSewed = 0;
5221 SMESH_MeshAlgos::TFreeBorderVec groups;
5222 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
5224 // check the input and collect nodes
5225 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
5227 borderNodes.clear();
5228 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
5229 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
5231 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5232 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
5233 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
5235 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
5237 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
5238 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
5239 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
5240 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
5241 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
5242 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5244 // do not keep these nodes for further sewing as nodes can be removed by the sewing
5245 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
5246 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
5247 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
5249 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
5251 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
5253 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5255 borderNodes.push_back( n1 );
5256 borderNodes.push_back( n2 );
5257 borderNodes.push_back( n3 );
5259 groups.push_back( borderNodes );
5262 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
5263 // to get nodes that replace other nodes during merge we create 0D elements
5264 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
5267 vector< const SMDS_MeshElement* > tmp0Delems;
5268 for ( size_t i = 0; i < groups.size(); ++i )
5270 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5271 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5273 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
5275 tmp0Delems.push_back( it0D->next() );
5277 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
5281 // cout << endl << "INIT" << endl;
5282 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5284 // cout << i << " ";
5285 // if ( i % 3 == 0 ) cout << "^ ";
5286 // tmp0Delems[i]->GetNode(0)->Print( cout );
5291 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
5293 for ( size_t i = 0; i < groups.size(); ++i )
5295 bool isBordToBord = true;
5296 bool groupSewed = false;
5297 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5298 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
5300 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
5301 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
5302 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
5304 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
5305 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
5306 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
5308 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
5311 // TIDSortedElemSet emptySet, avoidSet;
5312 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
5314 // cout << "WRONG 2nd 1" << endl;
5315 // n0->Print( cout );
5316 // n1->Print( cout );
5318 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
5320 // cout << "WRONG 2nd 2" << endl;
5321 // n3->Print( cout );
5322 // n4->Print( cout );
5325 if ( !isBordToBord )
5327 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5328 n2 = 0; // and n2 is not used
5330 // 1st border moves to 2nd
5331 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5333 /*2ndIsFreeBorder=*/ isBordToBord,
5334 createPolygons, createPolyhedra);
5335 groupSewed = ( res == ok );
5337 isBordToBord = false;
5338 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5339 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5341 // cout << t << " ";
5342 // if ( t % 3 == 0 ) cout << "^ ";
5343 // tmp0Delems[t]->GetNode(0)->Print( cout );
5346 i0D += nodes.size();
5347 nbSewed += groupSewed;
5350 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5351 << freeBorders << ", "
5352 << createPolygons << ", "
5353 << createPolyhedra << " )";
5355 SMESH_CATCH( SMESH::doNothing );
5357 declareMeshModified( /*isReComputeSafe=*/false );
5359 // remove tmp 0D elements
5361 set< const SMDS_MeshElement* > removed0D;
5362 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5364 if ( removed0D.insert( tmp0Delems[i] ).second )
5365 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5367 SMESH_CATCH( SMESH::throwCorbaException );
5372 //=======================================================================
5373 //function : SewFreeBorders
5375 //=======================================================================
5377 SMESH::SMESH_MeshEditor::Sew_Error
5378 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5379 CORBA::Long SecondNodeID1,
5380 CORBA::Long LastNodeID1,
5381 CORBA::Long FirstNodeID2,
5382 CORBA::Long SecondNodeID2,
5383 CORBA::Long LastNodeID2,
5384 CORBA::Boolean CreatePolygons,
5385 CORBA::Boolean CreatePolyedrs)
5386 throw (SALOME::SALOME_Exception)
5391 SMESHDS_Mesh* aMesh = getMeshDS();
5393 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5394 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5395 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5396 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5397 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5398 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5400 if (!aBorderFirstNode ||
5401 !aBorderSecondNode||
5403 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5404 if (!aSide2FirstNode ||
5405 !aSide2SecondNode ||
5407 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5409 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5410 << FirstNodeID1 << ", "
5411 << SecondNodeID1 << ", "
5412 << LastNodeID1 << ", "
5413 << FirstNodeID2 << ", "
5414 << SecondNodeID2 << ", "
5415 << LastNodeID2 << ", "
5416 << CreatePolygons<< ", "
5417 << CreatePolyedrs<< " )";
5419 SMESH::SMESH_MeshEditor::Sew_Error error =
5420 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5431 declareMeshModified( /*isReComputeSafe=*/false );
5434 SMESH_CATCH( SMESH::throwCorbaException );
5435 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5439 //=======================================================================
5440 //function : SewConformFreeBorders
5442 //=======================================================================
5444 SMESH::SMESH_MeshEditor::Sew_Error
5445 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5446 CORBA::Long SecondNodeID1,
5447 CORBA::Long LastNodeID1,
5448 CORBA::Long FirstNodeID2,
5449 CORBA::Long SecondNodeID2)
5450 throw (SALOME::SALOME_Exception)
5455 SMESHDS_Mesh* aMesh = getMeshDS();
5457 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5458 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5459 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5460 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5461 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5462 const SMDS_MeshNode* aSide2ThirdNode = 0;
5464 if (!aBorderFirstNode ||
5465 !aBorderSecondNode||
5467 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5468 if (!aSide2FirstNode ||
5470 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5472 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5473 << FirstNodeID1 << ", "
5474 << SecondNodeID1 << ", "
5475 << LastNodeID1 << ", "
5476 << FirstNodeID2 << ", "
5477 << SecondNodeID2 << " )";
5479 SMESH::SMESH_MeshEditor::Sew_Error error =
5480 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5489 declareMeshModified( /*isReComputeSafe=*/false );
5492 SMESH_CATCH( SMESH::throwCorbaException );
5493 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5497 //=======================================================================
5498 //function : SewBorderToSide
5500 //=======================================================================
5502 SMESH::SMESH_MeshEditor::Sew_Error
5503 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5504 CORBA::Long SecondNodeIDOnFreeBorder,
5505 CORBA::Long LastNodeIDOnFreeBorder,
5506 CORBA::Long FirstNodeIDOnSide,
5507 CORBA::Long LastNodeIDOnSide,
5508 CORBA::Boolean CreatePolygons,
5509 CORBA::Boolean CreatePolyedrs)
5510 throw (SALOME::SALOME_Exception)
5515 SMESHDS_Mesh* aMesh = getMeshDS();
5517 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5518 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5519 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5520 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5521 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5522 const SMDS_MeshNode* aSide2ThirdNode = 0;
5524 if (!aBorderFirstNode ||
5525 !aBorderSecondNode||
5527 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5528 if (!aSide2FirstNode ||
5530 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5532 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5533 << FirstNodeIDOnFreeBorder << ", "
5534 << SecondNodeIDOnFreeBorder << ", "
5535 << LastNodeIDOnFreeBorder << ", "
5536 << FirstNodeIDOnSide << ", "
5537 << LastNodeIDOnSide << ", "
5538 << CreatePolygons << ", "
5539 << CreatePolyedrs << ") ";
5541 SMESH::SMESH_MeshEditor::Sew_Error error =
5542 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5552 declareMeshModified( /*isReComputeSafe=*/false );
5555 SMESH_CATCH( SMESH::throwCorbaException );
5556 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5560 //=======================================================================
5561 //function : SewSideElements
5563 //=======================================================================
5565 SMESH::SMESH_MeshEditor::Sew_Error
5566 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5567 const SMESH::long_array& IDsOfSide2Elements,
5568 CORBA::Long NodeID1OfSide1ToMerge,
5569 CORBA::Long NodeID1OfSide2ToMerge,
5570 CORBA::Long NodeID2OfSide1ToMerge,
5571 CORBA::Long NodeID2OfSide2ToMerge)
5572 throw (SALOME::SALOME_Exception)
5577 SMESHDS_Mesh* aMesh = getMeshDS();
5579 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5580 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5581 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5582 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5584 if (!aFirstNode1ToMerge ||
5585 !aFirstNode2ToMerge )
5586 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5587 if (!aSecondNode1ToMerge||
5588 !aSecondNode2ToMerge)
5589 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5591 TIDSortedElemSet aSide1Elems, aSide2Elems;
5592 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5593 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5595 TPythonDump() << "error = " << this << ".SewSideElements( "
5596 << IDsOfSide1Elements << ", "
5597 << IDsOfSide2Elements << ", "
5598 << NodeID1OfSide1ToMerge << ", "
5599 << NodeID1OfSide2ToMerge << ", "
5600 << NodeID2OfSide1ToMerge << ", "
5601 << NodeID2OfSide2ToMerge << ")";
5603 SMESH::SMESH_MeshEditor::Sew_Error error =
5604 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5607 aSecondNode1ToMerge,
5608 aSecondNode2ToMerge));
5610 declareMeshModified( /*isReComputeSafe=*/false );
5613 SMESH_CATCH( SMESH::throwCorbaException );
5614 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5617 //================================================================================
5619 * \brief Set new nodes for given element
5620 * \param ide - element id
5621 * \param newIDs - new node ids
5622 * \retval CORBA::Boolean - true if result is OK
5624 //================================================================================
5626 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5627 const SMESH::long_array& newIDs)
5628 throw (SALOME::SALOME_Exception)
5633 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5634 if ( !elem ) return false;
5636 int nbn = newIDs.length();
5637 vector<const SMDS_MeshNode*> aNodes(nbn);
5638 for ( int i = 0; i < nbn; i++ ) {
5639 const SMDS_MeshNode* aNode = getMeshDS()->FindNode( newIDs[ i ]);
5642 aNodes[ i ] = aNode;
5644 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5645 << ide << ", " << newIDs << " )";
5647 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], aNodes.size() );
5649 declareMeshModified( /*isReComputeSafe=*/ !res );
5653 SMESH_CATCH( SMESH::throwCorbaException );
5657 //=======================================================================
5659 * \brief Makes a part of the mesh quadratic or bi-quadratic
5661 //=======================================================================
5663 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5664 CORBA::Boolean theToBiQuad,
5665 SMESH::SMESH_IDSource_ptr theObject)
5666 throw (SALOME::SALOME_Exception)
5671 TIDSortedElemSet elems;
5673 if ( !( elemsOK = CORBA::is_nil( theObject )))
5675 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5676 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5680 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5681 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5683 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5684 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5686 declareMeshModified( /*isReComputeSafe=*/false );
5689 SMESH_CATCH( SMESH::throwCorbaException );
5692 //=======================================================================
5693 //function : ConvertFromQuadratic
5695 //=======================================================================
5697 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5698 throw (SALOME::SALOME_Exception)
5703 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5704 TPythonDump() << this << ".ConvertFromQuadratic()";
5705 declareMeshModified( /*isReComputeSafe=*/!isDone );
5708 SMESH_CATCH( SMESH::throwCorbaException );
5712 //=======================================================================
5713 //function : ConvertToQuadratic
5715 //=======================================================================
5717 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5718 throw (SALOME::SALOME_Exception)
5720 convertToQuadratic( theForce3d, false );
5721 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5724 //================================================================================
5726 * \brief Makes a part of the mesh quadratic
5728 //================================================================================
5730 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5731 SMESH::SMESH_IDSource_ptr theObject)
5732 throw (SALOME::SALOME_Exception)
5734 convertToQuadratic( theForce3d, false, theObject );
5735 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5738 //================================================================================
5740 * \brief Makes a part of the mesh bi-quadratic
5742 //================================================================================
5744 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5745 SMESH::SMESH_IDSource_ptr theObject)
5746 throw (SALOME::SALOME_Exception)
5748 convertToQuadratic( theForce3d, true, theObject );
5749 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5752 //================================================================================
5754 * \brief Makes a part of the mesh linear
5756 //================================================================================
5758 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5759 throw (SALOME::SALOME_Exception)
5766 TIDSortedElemSet elems;
5767 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5769 if ( elems.empty() )
5771 ConvertFromQuadratic();
5773 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5775 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5779 getEditor().ConvertFromQuadratic(elems);
5782 declareMeshModified( /*isReComputeSafe=*/false );
5784 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5786 SMESH_CATCH( SMESH::throwCorbaException );
5789 //=======================================================================
5790 //function : makeMesh
5791 //purpose : create a named imported mesh
5792 //=======================================================================
5794 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5796 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5797 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5798 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5799 gen->SetName( meshSO, theMeshName, "Mesh" );
5800 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5802 return mesh._retn();
5805 //=======================================================================
5806 //function : dumpGroupsList
5808 //=======================================================================
5810 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5811 const SMESH::ListOfGroups * theGroupList)
5813 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5814 if ( isDumpGroupList )
5815 theDumpPython << theGroupList << " = ";
5818 //================================================================================
5820 \brief Generates the unique group name.
5821 \param thePrefix name prefix
5824 //================================================================================
5826 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5828 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5829 set<std::string> groupNames;
5831 // Get existing group names
5832 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5833 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5834 if (CORBA::is_nil(aGroup))
5837 CORBA::String_var name = aGroup->GetName();
5838 groupNames.insert( name.in() );
5842 std::string name = thePrefix;
5845 while (!groupNames.insert(name).second)
5846 name = SMESH_Comment( thePrefix ) << "_" << index++;
5851 //================================================================================
5853 * \brief Prepare SMESH_IDSource for work
5855 //================================================================================
5857 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5859 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5861 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5862 filter->SetMesh( mesh );
5865 //================================================================================
5867 * \brief Retrieve elements of given type from SMESH_IDSource
5869 //================================================================================
5871 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5872 const SMESHDS_Mesh* theMeshDS,
5873 TIDSortedElemSet& theElemSet,
5874 const SMDSAbs_ElementType theType,
5875 const bool emptyIfIsMesh,
5876 IDSource_Error* error)
5879 if ( error ) *error = IDSource_OK;
5881 if ( CORBA::is_nil( theIDSource ))
5883 if ( error ) *error = IDSource_INVALID;
5886 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5888 if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
5889 *error = IDSource_EMPTY;
5892 if ( getMeshDS() == theMeshDS ) // check if theIDSource belongs to myMesh
5894 SMESH::SMESH_Mesh_var mesh = theIDSource->GetMesh();
5895 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5896 if ( mesh_i && mesh_i != myMesh_i )
5899 *error = IDSource_INVALID;
5903 prepareIdSource( theIDSource );
5904 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5905 if ( anIDs->length() == 0 )
5907 if ( error ) *error = IDSource_EMPTY;
5910 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5911 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5913 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5915 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5919 if ( error ) *error = IDSource_INVALID;
5925 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5926 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5928 if ( error ) *error = IDSource_INVALID;
5935 //================================================================================
5937 * \brief Duplicates given elements, i.e. creates new elements based on the
5938 * same nodes as the given ones.
5939 * \param theElements - container of elements to duplicate.
5940 * \param theGroupName - a name of group to contain the generated elements.
5941 * If a group with such a name already exists, the new elements
5942 * are added to the existing group, else a new group is created.
5943 * If \a theGroupName is empty, new elements are not added
5945 * \return a group where the new elements are added. NULL if theGroupName == "".
5948 //================================================================================
5950 SMESH::SMESH_Group_ptr
5951 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5952 const char* theGroupName)
5953 throw (SALOME::SALOME_Exception)
5955 SMESH::SMESH_Group_var newGroup;
5962 TIDSortedElemSet elems;
5963 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5965 getEditor().DoubleElements( elems );
5967 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5970 SMESH::ElementType type =
5971 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5972 // find existing group
5973 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5974 for ( size_t i = 0; i < groups->length(); ++i )
5975 if ( groups[i]->GetType() == type )
5977 CORBA::String_var name = groups[i]->GetName();
5978 if ( strcmp( name, theGroupName ) == 0 ) {
5979 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5983 // create a new group
5984 if ( newGroup->_is_nil() )
5985 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5987 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5989 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5990 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5991 for ( size_t i = 0; i < aSeq.size(); i++ )
5992 groupDS->SMDSGroup().Add( aSeq[i] );
5997 if ( !newGroup->_is_nil() )
5998 pyDump << newGroup << " = ";
5999 pyDump << this << ".DoubleElements( "
6000 << theElements << ", " << "'" << theGroupName <<"')";
6002 SMESH_CATCH( SMESH::throwCorbaException );
6004 return newGroup._retn();
6007 //================================================================================
6009 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6010 \param theNodes - identifiers of nodes to be doubled
6011 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
6012 nodes. If list of element identifiers is empty then nodes are doubled but
6013 they not assigned to elements
6014 \return TRUE if operation has been completed successfully, FALSE otherwise
6015 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
6017 //================================================================================
6019 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
6020 const SMESH::long_array& theModifiedElems )
6021 throw (SALOME::SALOME_Exception)
6026 list< int > aListOfNodes;
6028 for ( i = 0, n = theNodes.length(); i < n; i++ )
6029 aListOfNodes.push_back( theNodes[ i ] );
6031 list< int > aListOfElems;
6032 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6033 aListOfElems.push_back( theModifiedElems[ i ] );
6035 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
6037 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6039 // Update Python script
6040 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
6044 SMESH_CATCH( SMESH::throwCorbaException );
6048 //================================================================================
6050 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6051 This method provided for convenience works as DoubleNodes() described above.
6052 \param theNodeId - identifier of node to be doubled.
6053 \param theModifiedElems - identifiers of elements to be updated.
6054 \return TRUE if operation has been completed successfully, FALSE otherwise
6055 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
6057 //================================================================================
6059 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
6060 const SMESH::long_array& theModifiedElems )
6061 throw (SALOME::SALOME_Exception)
6064 SMESH::long_array_var aNodes = new SMESH::long_array;
6065 aNodes->length( 1 );
6066 aNodes[ 0 ] = theNodeId;
6068 TPythonDump pyDump; // suppress dump by the next line
6070 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
6072 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
6076 SMESH_CATCH( SMESH::throwCorbaException );
6080 //================================================================================
6082 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6083 This method provided for convenience works as DoubleNodes() described above.
6084 \param theNodes - group of nodes to be doubled.
6085 \param theModifiedElems - group of elements to be updated.
6086 \return TRUE if operation has been completed successfully, FALSE otherwise
6087 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
6089 //================================================================================
6091 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
6092 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6093 throw (SALOME::SALOME_Exception)
6096 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6099 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6100 SMESH::long_array_var aModifiedElems;
6101 if ( !CORBA::is_nil( theModifiedElems ) )
6102 aModifiedElems = theModifiedElems->GetListOfID();
6104 aModifiedElems = new SMESH::long_array;
6106 TPythonDump pyDump; // suppress dump by the next line
6108 bool done = DoubleNodes( aNodes, aModifiedElems );
6110 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6114 SMESH_CATCH( SMESH::throwCorbaException );
6118 //================================================================================
6120 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6121 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6122 * \param theNodes - group of nodes to be doubled.
6123 * \param theModifiedElems - group of elements to be updated.
6124 * \return a new group with newly created nodes
6125 * \sa DoubleNodeGroup()
6127 //================================================================================
6129 SMESH::SMESH_Group_ptr
6130 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6131 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6132 throw (SALOME::SALOME_Exception)
6135 SMESH::SMESH_Group_var aNewGroup;
6137 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6138 return aNewGroup._retn();
6141 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6142 SMESH::long_array_var aModifiedElems;
6143 if ( !CORBA::is_nil( theModifiedElems ) )
6144 aModifiedElems = theModifiedElems->GetListOfID();
6146 aModifiedElems = new SMESH::long_array;
6147 aModifiedElems->length( 0 );
6150 TPythonDump pyDump; // suppress dump by the next line
6152 bool aResult = DoubleNodes( aNodes, aModifiedElems );
6155 // Create group with newly created nodes
6156 SMESH::long_array_var anIds = GetLastCreatedNodes();
6157 if (anIds->length() > 0) {
6158 std::string anUnindexedName (theNodes->GetName());
6159 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6160 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6161 aNewGroup->Add(anIds);
6162 pyDump << aNewGroup << " = ";
6166 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6167 << theModifiedElems << " )";
6169 return aNewGroup._retn();
6171 SMESH_CATCH( SMESH::throwCorbaException );
6175 //================================================================================
6177 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6178 This method provided for convenience works as DoubleNodes() described above.
6179 \param theNodes - list of groups of nodes to be doubled
6180 \param theModifiedElems - list of groups of elements to be updated.
6181 \return TRUE if operation has been completed successfully, FALSE otherwise
6182 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6184 //================================================================================
6186 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6187 const SMESH::ListOfGroups& theModifiedElems )
6188 throw (SALOME::SALOME_Exception)
6193 std::list< int > aNodes;
6195 for ( i = 0, n = theNodes.length(); i < n; i++ )
6197 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6198 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6200 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6201 for ( j = 0, m = aCurr->length(); j < m; j++ )
6202 aNodes.push_back( aCurr[ j ] );
6206 std::list< int > anElems;
6207 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6209 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6210 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6212 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6213 for ( j = 0, m = aCurr->length(); j < m; j++ )
6214 anElems.push_back( aCurr[ j ] );
6218 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6220 declareMeshModified( /*isReComputeSafe=*/false );
6222 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6226 SMESH_CATCH( SMESH::throwCorbaException );
6230 //================================================================================
6232 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6233 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6234 * \param theNodes - group of nodes to be doubled.
6235 * \param theModifiedElems - group of elements to be updated.
6236 * \return a new group with newly created nodes
6237 * \sa DoubleNodeGroups()
6239 //================================================================================
6241 SMESH::SMESH_Group_ptr
6242 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6243 const SMESH::ListOfGroups& theModifiedElems )
6244 throw (SALOME::SALOME_Exception)
6246 SMESH::SMESH_Group_var aNewGroup;
6248 TPythonDump pyDump; // suppress dump by the next line
6250 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6254 // Create group with newly created nodes
6255 SMESH::long_array_var anIds = GetLastCreatedNodes();
6256 if (anIds->length() > 0) {
6257 std::string anUnindexedName (theNodes[0]->GetName());
6258 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6259 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6260 aNewGroup->Add(anIds);
6261 pyDump << aNewGroup << " = ";
6265 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6266 << theModifiedElems << " )";
6268 return aNewGroup._retn();
6272 //================================================================================
6274 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6275 \param theElems - the list of elements (edges or faces) to be replicated
6276 The nodes for duplication could be found from these elements
6277 \param theNodesNot - list of nodes to NOT replicate
6278 \param theAffectedElems - the list of elements (cells and edges) to which the
6279 replicated nodes should be associated to.
6280 \return TRUE if operation has been completed successfully, FALSE otherwise
6281 \sa DoubleNodeGroup(), DoubleNodeGroups()
6283 //================================================================================
6285 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6286 const SMESH::long_array& theNodesNot,
6287 const SMESH::long_array& theAffectedElems )
6288 throw (SALOME::SALOME_Exception)
6293 SMESHDS_Mesh* aMeshDS = getMeshDS();
6294 TIDSortedElemSet anElems, aNodes, anAffected;
6295 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6296 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6297 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6299 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6301 // Update Python script
6302 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6303 << theNodesNot << ", " << theAffectedElems << " )";
6305 declareMeshModified( /*isReComputeSafe=*/false );
6308 SMESH_CATCH( SMESH::throwCorbaException );
6312 //================================================================================
6314 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6315 \param theElems - the list of elements (edges or faces) to be replicated
6316 The nodes for duplication could be found from these elements
6317 \param theNodesNot - list of nodes to NOT replicate
6318 \param theShape - shape to detect affected elements (element which geometric center
6319 located on or inside shape).
6320 The replicated nodes should be associated to affected elements.
6321 \return TRUE if operation has been completed successfully, FALSE otherwise
6322 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6324 //================================================================================
6326 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6327 const SMESH::long_array& theNodesNot,
6328 GEOM::GEOM_Object_ptr theShape )
6329 throw (SALOME::SALOME_Exception)
6335 SMESHDS_Mesh* aMeshDS = getMeshDS();
6336 TIDSortedElemSet anElems, aNodes;
6337 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6338 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6340 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6341 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6343 // Update Python script
6344 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6345 << theNodesNot << ", " << theShape << " )";
6347 declareMeshModified( /*isReComputeSafe=*/false );
6350 SMESH_CATCH( SMESH::throwCorbaException );
6354 //================================================================================
6356 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6357 \param theElems - group of of elements (edges or faces) to be replicated
6358 \param theNodesNot - group of nodes not to replicated
6359 \param theAffectedElems - group of elements to which the replicated nodes
6360 should be associated to.
6361 \return TRUE if operation has been completed successfully, FALSE otherwise
6362 \sa DoubleNodes(), DoubleNodeGroups()
6364 //================================================================================
6367 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6368 SMESH::SMESH_GroupBase_ptr theNodesNot,
6369 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6370 throw (SALOME::SALOME_Exception)
6373 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6379 SMESHDS_Mesh* aMeshDS = getMeshDS();
6380 TIDSortedElemSet anElems, aNodes, anAffected;
6381 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6382 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6383 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6385 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6387 // Update Python script
6388 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6389 << theNodesNot << ", " << theAffectedElems << " )";
6391 declareMeshModified( /*isReComputeSafe=*/false );
6394 SMESH_CATCH( SMESH::throwCorbaException );
6398 //================================================================================
6400 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6401 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6402 * \param theElems - group of of elements (edges or faces) to be replicated
6403 * \param theNodesNot - group of nodes not to replicated
6404 * \param theAffectedElems - group of elements to which the replicated nodes
6405 * should be associated to.
6406 * \return a new group with newly created elements
6407 * \sa DoubleNodeElemGroup()
6409 //================================================================================
6411 SMESH::SMESH_Group_ptr
6412 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6413 SMESH::SMESH_GroupBase_ptr theNodesNot,
6414 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6415 throw (SALOME::SALOME_Exception)
6418 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6422 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6423 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6425 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6427 << theNodesNot << ", "
6428 << theAffectedElems << " )";
6430 return elemGroup._retn();
6433 //================================================================================
6435 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6436 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6437 * \param theElems - group of of elements (edges or faces) to be replicated
6438 * \param theNodesNot - group of nodes not to replicated
6439 * \param theAffectedElems - group of elements to which the replicated nodes
6440 * should be associated to.
6441 * \return a new group with newly created elements
6442 * \sa DoubleNodeElemGroup()
6444 //================================================================================
6446 SMESH::ListOfGroups*
6447 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6448 SMESH::SMESH_GroupBase_ptr theNodesNot,
6449 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6450 CORBA::Boolean theElemGroupNeeded,
6451 CORBA::Boolean theNodeGroupNeeded)
6452 throw (SALOME::SALOME_Exception)
6455 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6456 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6457 aTwoGroups->length( 2 );
6459 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6460 return aTwoGroups._retn();
6465 SMESHDS_Mesh* aMeshDS = getMeshDS();
6466 TIDSortedElemSet anElems, aNodes, anAffected;
6467 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6468 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6469 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6472 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6474 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6480 // Create group with newly created elements
6481 CORBA::String_var elemGroupName = theElems->GetName();
6482 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6483 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6485 SMESH::long_array_var anIds = GetLastCreatedElems();
6486 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6487 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6488 aNewElemGroup->Add(anIds);
6490 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6492 SMESH::long_array_var anIds = GetLastCreatedNodes();
6493 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6494 aNewNodeGroup->Add(anIds);
6498 // Update Python script
6501 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6502 else pyDump << aNewElemGroup << ", ";
6503 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6504 else pyDump << aNewNodeGroup << " ] = ";
6506 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6507 << theNodesNot << ", "
6508 << theAffectedElems << ", "
6509 << theElemGroupNeeded << ", "
6510 << theNodeGroupNeeded <<" )";
6512 aTwoGroups[0] = aNewElemGroup._retn();
6513 aTwoGroups[1] = aNewNodeGroup._retn();
6514 return aTwoGroups._retn();
6516 SMESH_CATCH( SMESH::throwCorbaException );
6520 //================================================================================
6522 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6523 \param theElems - group of of elements (edges or faces) to be replicated
6524 \param theNodesNot - group of nodes not to replicated
6525 \param theShape - shape to detect affected elements (element which geometric center
6526 located on or inside shape).
6527 The replicated nodes should be associated to affected elements.
6528 \return TRUE if operation has been completed successfully, FALSE otherwise
6529 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6531 //================================================================================
6534 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6535 SMESH::SMESH_GroupBase_ptr theNodesNot,
6536 GEOM::GEOM_Object_ptr theShape )
6537 throw (SALOME::SALOME_Exception)
6540 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6546 SMESHDS_Mesh* aMeshDS = getMeshDS();
6547 TIDSortedElemSet anElems, aNodes, anAffected;
6548 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6549 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6551 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6552 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6555 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6557 // Update Python script
6558 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6559 << theNodesNot << ", " << theShape << " )";
6562 SMESH_CATCH( SMESH::throwCorbaException );
6566 //================================================================================
6568 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6569 * \param [in] theGrpList - groups
6570 * \param [in] theMeshDS - mesh
6571 * \param [out] theElemSet - set of elements
6572 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6574 //================================================================================
6576 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6577 SMESHDS_Mesh* theMeshDS,
6578 TIDSortedElemSet& theElemSet,
6579 const bool theIsNodeGrp)
6581 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6583 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6584 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6585 : aGrp->GetType() != SMESH::NODE ) )
6587 SMESH::long_array_var anIDs = aGrp->GetIDs();
6588 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6593 //================================================================================
6595 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6596 This method provided for convenience works as DoubleNodes() described above.
6597 \param theElems - list of groups of elements (edges or faces) to be replicated
6598 \param theNodesNot - list of groups of nodes not to replicated
6599 \param theAffectedElems - group of elements to which the replicated nodes
6600 should be associated to.
6601 \return TRUE if operation has been completed successfully, FALSE otherwise
6602 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6604 //================================================================================
6607 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6608 const SMESH::ListOfGroups& theNodesNot,
6609 const SMESH::ListOfGroups& theAffectedElems)
6610 throw (SALOME::SALOME_Exception)
6616 SMESHDS_Mesh* aMeshDS = getMeshDS();
6617 TIDSortedElemSet anElems, aNodes, anAffected;
6618 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6619 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6620 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6622 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6624 // Update Python script
6625 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6626 << &theNodesNot << ", " << &theAffectedElems << " )";
6628 declareMeshModified( /*isReComputeSafe=*/false );
6631 SMESH_CATCH( SMESH::throwCorbaException );
6635 //================================================================================
6637 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6638 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6639 \param theElems - list of groups of elements (edges or faces) to be replicated
6640 \param theNodesNot - list of groups of nodes not to replicated
6641 \param theAffectedElems - group of elements to which the replicated nodes
6642 should be associated to.
6643 * \return a new group with newly created elements
6644 * \sa DoubleNodeElemGroups()
6646 //================================================================================
6648 SMESH::SMESH_Group_ptr
6649 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6650 const SMESH::ListOfGroups& theNodesNot,
6651 const SMESH::ListOfGroups& theAffectedElems)
6652 throw (SALOME::SALOME_Exception)
6655 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6659 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6660 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6662 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6664 << theNodesNot << ", "
6665 << theAffectedElems << " )";
6667 return elemGroup._retn();
6670 //================================================================================
6672 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6673 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6674 \param theElems - list of groups of elements (edges or faces) to be replicated
6675 \param theNodesNot - list of groups of nodes not to replicated
6676 \param theAffectedElems - group of elements to which the replicated nodes
6677 should be associated to.
6678 * \return a new group with newly created elements
6679 * \sa DoubleNodeElemGroups()
6681 //================================================================================
6683 SMESH::ListOfGroups*
6684 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6685 const SMESH::ListOfGroups& theNodesNot,
6686 const SMESH::ListOfGroups& theAffectedElems,
6687 CORBA::Boolean theElemGroupNeeded,
6688 CORBA::Boolean theNodeGroupNeeded)
6689 throw (SALOME::SALOME_Exception)
6692 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6693 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6694 aTwoGroups->length( 2 );
6699 SMESHDS_Mesh* aMeshDS = getMeshDS();
6700 TIDSortedElemSet anElems, aNodes, anAffected;
6701 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6702 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6703 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6705 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6707 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6712 // Create group with newly created elements
6713 CORBA::String_var elemGroupName = theElems[0]->GetName();
6714 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6715 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6717 SMESH::long_array_var anIds = GetLastCreatedElems();
6718 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6719 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6720 aNewElemGroup->Add(anIds);
6722 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6724 SMESH::long_array_var anIds = GetLastCreatedNodes();
6725 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6726 aNewNodeGroup->Add(anIds);
6730 // Update Python script
6733 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6734 else pyDump << aNewElemGroup << ", ";
6735 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6736 else pyDump << aNewNodeGroup << " ] = ";
6738 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6739 << &theNodesNot << ", "
6740 << &theAffectedElems << ", "
6741 << theElemGroupNeeded << ", "
6742 << theNodeGroupNeeded << " )";
6744 aTwoGroups[0] = aNewElemGroup._retn();
6745 aTwoGroups[1] = aNewNodeGroup._retn();
6746 return aTwoGroups._retn();
6748 SMESH_CATCH( SMESH::throwCorbaException );
6752 //================================================================================
6754 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6755 This method provided for convenience works as DoubleNodes() described above.
6756 \param theElems - list of groups of elements (edges or faces) to be replicated
6757 \param theNodesNot - list of groups of nodes not to replicated
6758 \param theShape - shape to detect affected elements (element which geometric center
6759 located on or inside shape).
6760 The replicated nodes should be associated to affected elements.
6761 \return TRUE if operation has been completed successfully, FALSE otherwise
6762 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6764 //================================================================================
6767 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6768 const SMESH::ListOfGroups& theNodesNot,
6769 GEOM::GEOM_Object_ptr theShape )
6770 throw (SALOME::SALOME_Exception)
6776 SMESHDS_Mesh* aMeshDS = getMeshDS();
6777 TIDSortedElemSet anElems, aNodes;
6778 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6779 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6781 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6782 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6784 // Update Python script
6785 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6786 << &theNodesNot << ", " << theShape << " )";
6788 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6791 SMESH_CATCH( SMESH::throwCorbaException );
6795 //================================================================================
6797 \brief Identify the elements that will be affected by node duplication (actual
6798 duplication is not performed.
6799 This method is the first step of DoubleNodeElemGroupsInRegion.
6800 \param theElems - list of groups of elements (edges or faces) to be replicated
6801 \param theNodesNot - list of groups of nodes not to replicated
6802 \param theShape - shape to detect affected elements (element which geometric center
6803 located on or inside shape).
6804 The replicated nodes should be associated to affected elements.
6805 \return groups of affected elements
6806 \sa DoubleNodeElemGroupsInRegion()
6808 //================================================================================
6809 SMESH::ListOfGroups*
6810 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6811 const SMESH::ListOfGroups& theNodesNot,
6812 GEOM::GEOM_Object_ptr theShape )
6813 throw (SALOME::SALOME_Exception)
6816 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6817 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6818 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6819 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6823 ::SMESH_MeshEditor aMeshEditor(myMesh);
6825 SMESHDS_Mesh* aMeshDS = getMeshDS();
6826 TIDSortedElemSet anElems, aNodes;
6827 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6828 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6829 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6831 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6832 TIDSortedElemSet anAffected;
6833 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6835 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6838 if ( aResult && anAffected.size() > 0 )
6840 SMESH::long_array_var volumeIds = new SMESH::long_array;
6841 SMESH::long_array_var faceIds = new SMESH::long_array;
6842 SMESH::long_array_var edgeIds = new SMESH::long_array;
6843 volumeIds->length( anAffected.size() );
6844 faceIds ->length( anAffected.size() );
6845 edgeIds ->length( anAffected.size() );
6850 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6851 for (; eIt != anAffected.end(); ++eIt)
6853 const SMDS_MeshElement* anElem = *eIt;
6854 int elemId = anElem->GetID();
6855 switch ( anElem->GetType() ) {
6856 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6857 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6858 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6862 volumeIds->length(ivol);
6863 faceIds->length(iface);
6864 edgeIds->length(iedge);
6869 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6870 GenerateGroupName("affectedVolumes").c_str());
6871 aNewVolumeGroup->Add(volumeIds);
6872 aListOfGroups->length( nbGroups+1 );
6873 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6877 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6878 GenerateGroupName("affectedFaces").c_str());
6879 aNewFaceGroup->Add(faceIds);
6880 aListOfGroups->length( nbGroups+1 );
6881 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6885 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6886 GenerateGroupName("affectedEdges").c_str());
6887 aNewEdgeGroup->Add(edgeIds);
6888 aListOfGroups->length( nbGroups+1 );
6889 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6893 // Update Python script
6895 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6896 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6898 return aListOfGroups._retn();
6900 SMESH_CATCH( SMESH::throwCorbaException );
6904 //================================================================================
6906 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6907 The created 2D mesh elements based on nodes of free faces of boundary volumes
6908 \return TRUE if operation has been completed successfully, FALSE otherwise
6910 //================================================================================
6912 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6913 throw (SALOME::SALOME_Exception)
6918 bool aResult = getEditor().Make2DMeshFrom3D();
6920 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6922 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6925 SMESH_CATCH( SMESH::throwCorbaException );
6929 //================================================================================
6931 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6932 * The list of groups must contain at least two groups. The groups have to be disjoint:
6933 * no common element into two different groups.
6934 * The nodes of the internal faces at the boundaries of the groups are doubled.
6935 * Optionally, the internal faces are replaced by flat elements.
6936 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6937 * The flat elements are stored in groups of volumes.
6938 * These groups are named according to the position of the group in the list:
6939 * 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.
6940 * 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.
6941 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6942 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6943 * \param theDomains - list of groups of volumes
6944 * \param createJointElems - if TRUE, create the elements
6945 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6946 * the boundary between \a theDomains and the rest mesh
6947 * \return TRUE if operation has been completed successfully, FALSE otherwise
6949 //================================================================================
6952 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6953 CORBA::Boolean createJointElems,
6954 CORBA::Boolean onAllBoundaries )
6955 throw (SALOME::SALOME_Exception)
6962 SMESHDS_Mesh* aMeshDS = getMeshDS();
6964 // MESSAGE("theDomains.length = "<<theDomains.length());
6965 if ( theDomains.length() <= 1 && !onAllBoundaries )
6966 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6968 vector<TIDSortedElemSet> domains;
6969 domains.resize( theDomains.length() );
6971 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6973 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6974 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6976 // if ( aGrp->GetType() != SMESH::VOLUME )
6977 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6978 SMESH::long_array_var anIDs = aGrp->GetIDs();
6979 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6983 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6984 // TODO publish the groups of flat elements in study
6986 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6988 // Update Python script
6989 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6990 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6992 SMESH_CATCH( SMESH::throwCorbaException );
6994 myMesh_i->CreateGroupServants(); // publish created groups if any
6999 //================================================================================
7001 * \brief Double nodes on some external faces and create flat elements.
7002 * Flat elements are mainly used by some types of mechanic calculations.
7004 * Each group of the list must be constituted of faces.
7005 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
7006 * @param theGroupsOfFaces - list of groups of faces
7007 * @return TRUE if operation has been completed successfully, FALSE otherwise
7009 //================================================================================
7012 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
7013 throw (SALOME::SALOME_Exception)
7018 SMESHDS_Mesh* aMeshDS = getMeshDS();
7020 vector<TIDSortedElemSet> faceGroups;
7023 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
7025 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
7026 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
7028 TIDSortedElemSet faceGroup;
7030 faceGroups.push_back(faceGroup);
7031 SMESH::long_array_var anIDs = aGrp->GetIDs();
7032 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
7036 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
7037 // TODO publish the groups of flat elements in study
7039 declareMeshModified( /*isReComputeSafe=*/ !aResult );
7041 // Update Python script
7042 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
7045 SMESH_CATCH( SMESH::throwCorbaException );
7049 //================================================================================
7051 * \brief Identify all the elements around a geom shape, get the faces delimiting
7054 * Build groups of volume to remove, groups of faces to replace on the skin of the
7055 * object, groups of faces to remove inside the object, (idem edges).
7056 * Build ordered list of nodes at the border of each group of faces to replace
7057 * (to be used to build a geom subshape).
7059 //================================================================================
7061 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
7062 GEOM::GEOM_Object_ptr theShape,
7063 const char* groupName,
7064 const SMESH::double_array& theNodesCoords,
7065 SMESH::array_of_long_array_out GroupsOfNodes)
7066 throw (SALOME::SALOME_Exception)
7071 std::vector<std::vector<int> > aListOfListOfNodes;
7072 ::SMESH_MeshEditor aMeshEditor( myMesh );
7074 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
7075 if ( !theNodeSearcher )
7076 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
7078 vector<double> nodesCoords;
7079 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
7081 nodesCoords.push_back( theNodesCoords[i] );
7084 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
7085 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
7086 nodesCoords, aListOfListOfNodes);
7088 GroupsOfNodes = new SMESH::array_of_long_array;
7089 GroupsOfNodes->length( aListOfListOfNodes.size() );
7090 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
7091 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
7093 vector<int>& aListOfNodes = *llIt;
7094 vector<int>::iterator lIt = aListOfNodes.begin();;
7095 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
7096 aGroup.length( aListOfNodes.size() );
7097 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
7098 aGroup[ j ] = (*lIt);
7100 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
7103 << ", '" << groupName << "', "
7104 << theNodesCoords << " )";
7106 SMESH_CATCH( SMESH::throwCorbaException );
7109 // issue 20749 ===================================================================
7111 * \brief Creates missing boundary elements
7112 * \param elements - elements whose boundary is to be checked
7113 * \param dimension - defines type of boundary elements to create
7114 * \param groupName - a name of group to store created boundary elements in,
7115 * "" means not to create the group
7116 * \param meshName - a name of new mesh to store created boundary elements in,
7117 * "" means not to create the new mesh
7118 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
7119 * \param toCopyExistingBondary - if true, not only new but also pre-existing
7120 * boundary elements will be copied into the new mesh
7121 * \param group - returns the create group, if any
7122 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7124 // ================================================================================
7126 SMESH::SMESH_Mesh_ptr
7127 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7128 SMESH::Bnd_Dimension dim,
7129 const char* groupName,
7130 const char* meshName,
7131 CORBA::Boolean toCopyElements,
7132 CORBA::Boolean toCopyExistingBondary,
7133 SMESH::SMESH_Group_out group)
7134 throw (SALOME::SALOME_Exception)
7139 if ( dim > SMESH::BND_1DFROM2D )
7140 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7142 SMESHDS_Mesh* aMeshDS = getMeshDS();
7144 SMESH::SMESH_Mesh_var mesh_var;
7145 SMESH::SMESH_Group_var group_var;
7149 TIDSortedElemSet elements;
7150 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7151 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7155 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7156 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7158 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7160 // group of new boundary elements
7161 SMESH_Group* smesh_group = 0;
7162 if ( strlen(groupName) )
7164 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7165 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7166 smesh_group = group_i->GetSmeshGroup();
7170 getEditor().MakeBoundaryMesh( elements,
7171 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7175 toCopyExistingBondary);
7178 smesh_mesh->GetMeshDS()->Modified();
7181 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7183 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7184 if ( mesh_var->_is_nil() )
7185 pyDump << myMesh_i->_this() << ", ";
7187 pyDump << mesh_var << ", ";
7188 if ( group_var->_is_nil() )
7189 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7191 pyDump << group_var << " = ";
7192 pyDump << this << ".MakeBoundaryMesh( "
7194 << "SMESH." << dimName[int(dim)] << ", "
7195 << "'" << groupName << "', "
7196 << "'" << meshName<< "', "
7197 << toCopyElements << ", "
7198 << toCopyExistingBondary << ")";
7200 group = group_var._retn();
7201 return mesh_var._retn();
7203 SMESH_CATCH( SMESH::throwCorbaException );
7204 return SMESH::SMESH_Mesh::_nil();
7207 //================================================================================
7209 * \brief Creates missing boundary elements
7210 * \param dimension - defines type of boundary elements to create
7211 * \param groupName - a name of group to store all boundary elements in,
7212 * "" means not to create the group
7213 * \param meshName - a name of a new mesh, which is a copy of the initial
7214 * mesh + created boundary elements; "" means not to create the new mesh
7215 * \param toCopyAll - if true, the whole initial mesh will be copied into
7216 * the new mesh else only boundary elements will be copied into the new mesh
7217 * \param groups - optional groups of elements to make boundary around
7218 * \param mesh - returns the mesh where elements were added to
7219 * \param group - returns the created group, if any
7220 * \retval long - number of added boundary elements
7222 //================================================================================
7224 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7225 const char* groupName,
7226 const char* meshName,
7227 CORBA::Boolean toCopyAll,
7228 const SMESH::ListOfIDSources& groups,
7229 SMESH::SMESH_Mesh_out mesh,
7230 SMESH::SMESH_Group_out group)
7231 throw (SALOME::SALOME_Exception)
7236 if ( dim > SMESH::BND_1DFROM2D )
7237 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7239 // separate groups belonging to this and other mesh
7240 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7241 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7242 groupsOfThisMesh ->length( groups.length() );
7243 groupsOfOtherMesh->length( groups.length() );
7244 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7245 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7247 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7248 if ( !m->_is_nil() && myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7249 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7251 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7252 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7253 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7255 groupsOfThisMesh->length( nbGroups );
7256 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7261 if ( nbGroupsOfOtherMesh > 0 )
7263 // process groups belonging to another mesh
7264 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7265 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7266 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7267 groupsOfOtherMesh, mesh, group );
7270 SMESH::SMESH_Mesh_var mesh_var;
7271 SMESH::SMESH_Group_var group_var;
7274 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7275 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7279 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7281 /*toCopyGroups=*/false,
7282 /*toKeepIDs=*/true);
7284 mesh_var = makeMesh(meshName);
7286 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7287 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7290 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7291 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7293 // group of boundary elements
7294 SMESH_Group* smesh_group = 0;
7295 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7296 if ( strlen( groupName ))
7298 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7299 group_var = mesh_i->CreateGroup( groupType, groupName );
7300 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7301 smesh_group = group_i->GetSmeshGroup();
7304 TIDSortedElemSet elements;
7306 if ( groups.length() > 0 )
7308 for ( int i = 0; i < nbGroups; ++i )
7311 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7313 SMESH::Bnd_Dimension bdim =
7314 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7315 nbAdded += getEditor().MakeBoundaryMesh( elements,
7316 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7319 /*toCopyElements=*/false,
7320 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7321 /*toAddExistingBondary=*/true,
7322 /*aroundElements=*/true);
7328 nbAdded += getEditor().MakeBoundaryMesh( elements,
7329 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7332 /*toCopyElements=*/false,
7333 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7334 /*toAddExistingBondary=*/true);
7336 tgtMesh->GetMeshDS()->Modified();
7338 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7340 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7341 pyDump << "nbAdded, ";
7342 if ( mesh_var->_is_nil() )
7343 pyDump << myMesh_i->_this() << ", ";
7345 pyDump << mesh_var << ", ";
7346 if ( group_var->_is_nil() )
7347 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7349 pyDump << group_var << " = ";
7350 pyDump << this << ".MakeBoundaryElements( "
7351 << "SMESH." << dimName[int(dim)] << ", "
7352 << "'" << groupName << "', "
7353 << "'" << meshName<< "', "
7354 << toCopyAll << ", "
7357 mesh = mesh_var._retn();
7358 group = group_var._retn();
7361 SMESH_CATCH( SMESH::throwCorbaException );
7365 //================================================================================
7367 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7368 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7369 * plane passing through pairs of points specified by each PolySegment structure.
7370 * If there are several paths connecting a pair of points, the shortest path is
7371 * selected by the module. Position of the cutting plane is defined by the two
7372 * points and an optional vector lying on the plane specified by a PolySegment.
7373 * By default the vector is defined by Mesh module as following. A middle point
7374 * of the two given points is computed. The middle point is projected to the mesh.
7375 * The vector goes from the middle point to the projection point. In case of planar
7376 * mesh, the vector is normal to the mesh.
7377 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7378 * Return the used vector and position of the middle point.
7379 * \param [in] groupName - optional name of a group where created mesh segments will
7382 //================================================================================
7384 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7385 const char* theGroupName)
7386 throw (SALOME::SALOME_Exception)
7388 if ( theSegments.length() == 0 )
7389 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7390 if ( myMesh->NbFaces() == 0 )
7391 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7394 initData(/*deleteSearchers=*/false);
7396 SMESHDS_Group* groupDS = 0;
7397 SMESHDS_Mesh* meshDS = getMeshDS();
7398 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7400 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7401 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7402 while ( faceIt->more() )
7403 tmpMesh->Copy( faceIt->next() );
7404 meshDS = tmpMesh->GetMeshDS();
7406 else if ( theGroupName[0] ) // find/create a group of segments
7408 // SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7409 // while ( !groupDS && grpIt->more() )
7411 // SMESH_Group* group = grpIt->next();
7412 // if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7413 // strcmp( group->GetName(), theGroupName ) == 0 )
7415 // groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7420 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7422 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7423 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7427 // convert input polySegments
7428 SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() );
7429 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7431 SMESH::PolySegment& segIn = theSegments[ i ];
7432 SMESH_MeshAlgos::PolySegment& segOut = segments[ i ];
7433 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7434 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7435 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7436 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7437 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7440 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7443 segOut.myVector.SetCoord( segIn.vector.PS.x,
7445 segIn.vector.PS.z );
7448 // get a static ElementSearcher
7449 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7450 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7451 if ( !theElementSearcher )
7452 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7455 std::vector<const SMDS_MeshElement*> newEdges;
7456 std::vector<const SMDS_MeshNode*> newNodes;
7457 SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes,
7458 groupDS ? &groupDS->SMDSGroup() : 0,
7459 theElementSearcher );
7461 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ).
7463 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ).
7464 assign( newNodes.begin(), newNodes.end() );
7467 if ( myIsPreviewMode )
7469 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7471 SMESH::PolySegment& segOut = theSegments[ i ];
7472 SMESH_MeshAlgos::PolySegment& segIn = segments[ i ];
7473 segOut.vector.PS.x = segIn.myVector.X();
7474 segOut.vector.PS.y = segIn.myVector.Y();
7475 segOut.vector.PS.z = segIn.myVector.Z();
7480 TPythonDump() << "_segments = []";
7481 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7483 SMESH::PolySegment& segIn = theSegments[ i ];
7484 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7485 << segIn.node1ID1 << ", "
7486 << segIn.node1ID2 << ", "
7487 << segIn.node2ID1 << ", "
7488 << segIn.node2ID2 << ", "
7489 << "smeshBuilder.MakeDirStruct( "
7490 << segIn.vector.PS.x << ", "
7491 << segIn.vector.PS.y << ", "
7492 << segIn.vector.PS.z << ")))";
7494 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7497 SMESH_CATCH( SMESH::throwCorbaException );
7501 //================================================================================
7503 * \brief Create a slot of given width around given 1D elements lying on a triangle mesh.
7504 * The slot is constructed by cutting faces by cylindrical surfaces made
7505 * around each segment. Segments are expected to be created by MakePolyLine().
7506 * \return Edges located at the slot boundary
7508 //================================================================================
7510 SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments,
7511 CORBA::Double theWidth)
7512 throw (SALOME::SALOME_Exception)
7514 if ( CORBA::is_nil( theSegments ) ||
7515 theSegments->GetType() != SMESH::EDGE )
7516 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7517 if ( myMesh->NbFaces() == 0 )
7518 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7520 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
7523 initData(/*deleteSearchers=*/false);
7525 SMESHDS_Mesh* meshDS = getMeshDS();
7527 // get standalone face groups to be updated
7528 std::vector< SMDS_MeshGroup* > faceGroups;
7529 const std::set<SMESHDS_GroupBase*>& allGroups = meshDS->GetGroups();
7530 std::set<SMESHDS_GroupBase*>::const_iterator grIt = allGroups.begin();
7531 for ( ; grIt != allGroups.end(); ++grIt )
7532 if ( const SMESHDS_Group* gr = dynamic_cast< const SMESHDS_Group* >( *grIt ))
7533 if ( gr->GetType() == SMDSAbs_Face )
7534 faceGroups.push_back( & const_cast< SMESHDS_Group* >( gr )->SMDSGroup() );
7536 std::vector< SMESH_MeshAlgos::Edge > edges =
7537 SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ),
7538 theWidth, meshDS, faceGroups );
7540 resultEdges->length( edges.size() );
7541 for ( size_t i = 0; i < edges.size(); ++i )
7543 resultEdges[ i ].node1 = edges[i]._node1->GetID();
7544 resultEdges[ i ].node2 = edges[i]._node2->GetID();
7545 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
7549 SMESH_CATCH( SMESH::throwCorbaException );
7551 TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed
7553 return resultEdges._retn();