1 // Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_SetIterator.hxx"
46 #include "SMDS_VolumeTool.hxx"
47 #include "SMESHDS_Group.hxx"
48 #include "SMESHDS_GroupOnGeom.hxx"
49 #include "SMESH_ControlsDef.hxx"
50 #include "SMESH_Filter_i.hxx"
51 #include "SMESH_Gen_i.hxx"
52 #include "SMESH_Group.hxx"
53 #include "SMESH_Group_i.hxx"
54 #include "SMESH_MeshAlgos.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PythonDump.hxx"
58 #include "SMESH_subMeshEventListener.hxx"
59 #include "SMESH_subMesh_i.hxx"
61 #include <utilities.h>
62 #include <Utils_ExceptHandlers.hxx>
63 #include <Utils_CorbaException.hxx>
64 #include <SALOMEDS_wrap.hxx>
65 #include <SALOME_GenericObj_i.hh>
67 #include <BRepAdaptor_Surface.hxx>
68 #include <BRep_Tool.hxx>
69 #include <TopExp_Explorer.hxx>
71 #include <TopoDS_Edge.hxx>
72 #include <TopoDS_Face.hxx>
77 #include <Standard_Failure.hxx>
78 #include <Standard_ErrorHandler.hxx>
83 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
85 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
88 using SMESH::TPythonDump;
91 namespace MeshEditor_I {
93 //=============================================================================
95 * \brief Mesh to apply modifications for preview purposes
97 //=============================================================================
99 struct TPreviewMesh: public SMESH_Mesh
101 SMDSAbs_ElementType myPreviewType; // type to show
103 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
104 _isShapeToMesh = (_id = 0);
105 _myMeshDS = new SMESHDS_Mesh( _id, true );
106 myPreviewType = previewElements;
108 //!< Copy a set of elements
109 void Copy(const TIDSortedElemSet & theElements,
110 TIDSortedElemSet& theCopyElements,
111 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
112 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
114 // loop on theIDsOfElements
115 TIDSortedElemSet::const_iterator eIt = theElements.begin();
116 for ( ; eIt != theElements.end(); ++eIt )
118 const SMDS_MeshElement* anElem = *eIt;
119 if ( !anElem ) continue;
120 SMDSAbs_ElementType type = anElem->GetType();
121 if ( type == theAvoidType ||
122 ( theSelectType != SMDSAbs_All && type != theSelectType ))
124 const SMDS_MeshElement* anElemCopy;
125 if ( type == SMDSAbs_Node)
126 anElemCopy = Copy( cast2Node(anElem) );
128 anElemCopy = Copy( anElem );
130 theCopyElements.insert( theCopyElements.end(), anElemCopy );
134 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
136 // copy element nodes
137 int anElemNbNodes = anElem->NbNodes();
138 vector< int > anElemNodesID( anElemNbNodes ) ;
139 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
140 for ( int i = 0; itElemNodes->more(); i++)
142 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
144 anElemNodesID[i] = anElemNode->GetID();
147 // creates a corresponding element on copied nodes
148 ::SMESH_MeshEditor::ElemFeatures elemType;
149 elemType.Init( anElem, /*basicOnly=*/false );
150 elemType.SetID( anElem->GetID() );
151 SMDS_MeshElement* anElemCopy =
152 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
156 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
158 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
159 anElemNode->GetID());
163 GetMeshDS()->ClearMesh();
165 void Remove( SMDSAbs_ElementType type )
167 Remove( GetMeshDS()->elementsIterator( type ));
169 void Remove( SMDS_ElemIteratorPtr eIt )
171 while ( eIt->more() )
172 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
174 };// struct TPreviewMesh
176 static SMESH_NodeSearcher * theNodeSearcher = 0;
177 static SMESH_ElementSearcher * theElementSearcher = 0;
179 //=============================================================================
181 * \brief Deleter of theNodeSearcher and theElementSearcher at any compute event occurred
183 //=============================================================================
185 struct TSearchersDeleter : public SMESH_subMeshEventListener
188 string myMeshPartIOR;
190 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
191 "SMESH_MeshEditor_i::TSearchersDeleter"),
193 //!< Delete theNodeSearcher
196 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
197 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
199 typedef map < int, SMESH_subMesh * > TDependsOnMap;
200 //!< The meshod called by submesh: do my main job
201 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
202 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
204 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
206 Unset( sm->GetFather() );
209 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
210 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
212 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
219 myMeshPartIOR = meshPartIOR;
220 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
221 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
222 while ( smIt->more() )
225 sm->SetEventListener( this, 0, sm );
229 //!< delete self from all submeshes
230 void Unset(SMESH_Mesh* mesh)
232 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
233 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
234 while ( smIt->more() )
235 smIt->next()->DeleteEventListener( this );
240 } theSearchersDeleter;
242 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
244 TCollection_AsciiString typeStr;
245 switch ( theMirrorType ) {
246 case SMESH::SMESH_MeshEditor::POINT:
247 typeStr = "SMESH.SMESH_MeshEditor.POINT";
249 case SMESH::SMESH_MeshEditor::AXIS:
250 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
253 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
257 //================================================================================
259 * \brief function for conversion of long_array to TIDSortedElemSet
260 * \param IDs - array of IDs
261 * \param aMesh - mesh
262 * \param aMap - collection to fill
263 * \param aType - element type
265 //================================================================================
267 void arrayToSet(const SMESH::long_array & IDs,
268 const SMESHDS_Mesh* aMesh,
269 TIDSortedElemSet& aMap,
270 const SMDSAbs_ElementType aType = SMDSAbs_All,
271 SMDS_MeshElement::Filter* aFilter = NULL)
273 SMDS_MeshElement::NonNullFilter filter1;
274 SMDS_MeshElement::TypeFilter filter2( aType );
276 if ( aFilter == NULL )
277 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
279 SMDS_MeshElement::Filter & filter = *aFilter;
281 if ( aType == SMDSAbs_Node )
282 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
283 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
285 aMap.insert( aMap.end(), elem );
288 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
289 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
291 aMap.insert( aMap.end(), elem );
295 //================================================================================
297 * \brief Retrieve nodes from SMESH_IDSource
299 //================================================================================
301 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
302 const SMESHDS_Mesh* theMeshDS,
303 TIDSortedNodeSet& theNodeSet)
306 if ( CORBA::is_nil( theObject ) )
308 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
310 for ( SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator(); nIt->more(); )
311 if ( const SMDS_MeshElement * elem = nIt->next() )
312 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
316 SMESH::array_of_ElementType_var types = theObject->GetTypes();
317 SMESH::long_array_var aElementsId = theObject->GetIDs();
318 if ( types->length() == 1 && types[0] == SMESH::NODE)
320 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
321 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
322 theNodeSet.insert( theNodeSet.end(), n);
326 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
327 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
328 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
333 //================================================================================
335 * \brief Returns elements connected to the given elements
337 //================================================================================
339 void getElementsAround(const TIDSortedElemSet& theElements,
340 const SMESHDS_Mesh* theMeshDS,
341 TIDSortedElemSet& theElementsAround)
343 if ( theElements.empty() ) return;
345 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
346 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
348 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
349 return; // all the elements are in theElements
352 elemType = SMDSAbs_All;
354 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
356 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
357 for ( ; elemIt != theElements.end(); ++elemIt )
359 const SMDS_MeshElement* e = *elemIt;
360 int i = e->NbCornerNodes();
363 const SMDS_MeshNode* n = e->GetNode( i );
364 if ( !isNodeChecked[ n->GetID() ])
366 isNodeChecked[ n->GetID() ] = true;
367 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
368 while ( invIt->more() )
370 const SMDS_MeshElement* elemAround = invIt->next();
371 if ( !theElements.count( elemAround ))
372 theElementsAround.insert( elemAround );
379 //================================================================================
381 * \brief Return a string used to detect change of mesh part on which theElementSearcher
382 * is going to be used
384 //================================================================================
386 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type = SMESH::ALL )
388 if ( SMESH::DownCast<SMESH_Mesh_i*>( theMeshPart ))
390 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
391 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
392 // take into account passible group modification
393 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
394 partIOR += SMESH_Comment( type );
398 } // namespace MeshEditor_I
400 using namespace MeshEditor_I;
402 //=============================================================================
406 //=============================================================================
408 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
410 myMesh( &theMesh->GetImpl() ),
412 myIsPreviewMode ( isPreview ),
418 //================================================================================
422 //================================================================================
424 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
426 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
427 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
428 poa->deactivate_object(anObjectId.in());
430 //deleteAuxIDSources();
431 delete myPreviewMesh; myPreviewMesh = 0;
432 delete myPreviewEditor; myPreviewEditor = 0;
435 //================================================================================
437 * \brief Returns the mesh
439 //================================================================================
441 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
443 return myMesh_i->_this();
446 //================================================================================
448 * \brief Clear members
450 //================================================================================
452 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
454 if ( myIsPreviewMode ) {
455 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
458 if ( deleteSearchers )
459 TSearchersDeleter::Delete();
461 getEditor().GetError().reset();
462 getEditor().ClearLastCreated();
465 //================================================================================
467 * \brief Increment mesh modif time and optionally record that the performed
468 * modification may influence further mesh re-compute.
469 * \param [in] isReComputeSafe - true if the modification does not influence
470 * further mesh re-compute
472 //================================================================================
474 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
476 myMesh->GetMeshDS()->Modified();
477 if ( !isReComputeSafe )
478 myMesh->SetIsModified( true );
481 //================================================================================
483 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
484 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
486 //================================================================================
488 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
490 if ( myIsPreviewMode && !myPreviewEditor ) {
491 if ( !myPreviewMesh ) getPreviewMesh();
492 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
494 return myIsPreviewMode ? *myPreviewEditor : myEditor;
497 //================================================================================
499 * \brief Initialize and return myPreviewMesh
500 * \param previewElements - type of elements to show in preview
502 * WARNING: call it once per method!
504 //================================================================================
506 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
508 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
510 delete myPreviewEditor;
512 delete myPreviewMesh;
513 myPreviewMesh = new TPreviewMesh( previewElements );
515 myPreviewMesh->Clear();
516 return myPreviewMesh;
519 //================================================================================
521 * Return data of mesh edition preview
523 //================================================================================
525 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
526 throw (SALOME::SALOME_Exception)
529 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
531 if ( myIsPreviewMode || hasBadElems )
533 list<int> aNodesConnectivity;
534 typedef map<int, int> TNodesMap;
537 SMESHDS_Mesh* aMeshDS;
538 std::unique_ptr< SMESH_MeshPartDS > aMeshPartDS;
540 const list<const SMDS_MeshElement*>& badElems =
541 static_cast<SMESH_BadInputElements*>( getEditor().GetError().get() )->myBadElements;
542 aMeshPartDS.reset( new SMESH_MeshPartDS( badElems ));
543 aMeshDS = aMeshPartDS.get();
546 aMeshDS = getEditor().GetMeshDS();
548 myPreviewData = new SMESH::MeshPreviewStruct();
549 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
552 SMDSAbs_ElementType previewType = SMDSAbs_All;
554 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
555 previewType = aPreviewMesh->myPreviewType;
556 switch ( previewType ) {
557 case SMDSAbs_Edge : break;
558 case SMDSAbs_Face : break;
559 case SMDSAbs_Volume: break;
561 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
565 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
567 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
569 while ( itMeshElems->more() ) {
570 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
571 SMDS_NodeIteratorPtr itElemNodes =
572 (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
573 aMeshElem->interlacedNodesIterator() :
574 aMeshElem->nodeIterator() );
575 while ( itElemNodes->more() ) {
576 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
577 int aNodeID = aMeshNode->GetID();
578 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
579 if ( anIter == nodesMap.end() ) {
580 // filling the nodes coordinates
581 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
582 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
583 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
584 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
587 aNodesConnectivity.push_back(anIter->second);
590 // filling the elements types
591 SMDSAbs_ElementType aType = aMeshElem->GetType();
592 bool isPoly = aMeshElem->IsPoly();
593 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
594 myPreviewData->elementTypes[i].isPoly = isPoly;
595 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
598 myPreviewData->nodesXYZ.length( j );
600 // filling the elements connectivities
601 list<int>::iterator aConnIter = aNodesConnectivity.begin();
602 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
603 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
604 myPreviewData->elementConnectivities[i] = *aConnIter;
606 return myPreviewData._retn();
608 SMESH_CATCH( SMESH::throwCorbaException );
612 //================================================================================
614 * \brief Returns list of it's IDs of created nodes
615 * \retval SMESH::long_array* - list of node ID
617 //================================================================================
619 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
620 throw (SALOME::SALOME_Exception)
623 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
625 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
626 myLastCreatedNodes->length( aSeq.size() );
627 for ( size_t i = 0; i < aSeq.size(); i++)
628 myLastCreatedNodes[i] = aSeq[i]->GetID();
630 return myLastCreatedNodes._retn();
631 SMESH_CATCH( SMESH::throwCorbaException );
635 //================================================================================
637 * \brief Returns list of it's IDs of created elements
638 * \retval SMESH::long_array* - list of elements' ID
640 //================================================================================
642 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
643 throw (SALOME::SALOME_Exception)
646 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
648 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
649 myLastCreatedElems->length( aSeq.size() );
650 for ( size_t i = 0; i < aSeq.size(); i++ )
651 myLastCreatedElems[i] = aSeq[i]->GetID();
653 return myLastCreatedElems._retn();
654 SMESH_CATCH( SMESH::throwCorbaException );
658 //=======================================================================
659 //function : ClearLastCreated
660 //purpose : Clears sequences of last created elements and nodes
661 //=======================================================================
663 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
666 getEditor().ClearLastCreated();
667 SMESH_CATCH( SMESH::throwCorbaException );
670 //=======================================================================
672 * Returns description of an error/warning occurred during the last operation
673 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
675 //=======================================================================
677 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
678 throw (SALOME::SALOME_Exception)
681 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
682 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
683 if ( errIn && !errIn->IsOK() )
685 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
686 errOut->comment = errIn->myComment.c_str();
687 errOut->subShapeID = -1;
688 errOut->hasBadMesh = errIn->HasBadElems();
693 errOut->subShapeID = -1;
694 errOut->hasBadMesh = false;
697 return errOut._retn();
698 SMESH_CATCH( SMESH::throwCorbaException );
702 //=======================================================================
703 //function : MakeIDSource
704 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
705 // Call UnRegister() as you fininsh using it!!
706 //=======================================================================
708 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
709 public virtual SALOME::GenericObj_i
711 SMESH::long_array _ids;
712 SMESH::ElementType _type;
713 SMESH::SMESH_Mesh_ptr _mesh;
714 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
715 SMESH::long_array* GetMeshInfo() { return 0; }
716 SMESH::long_array* GetNbElementsByType()
718 SMESH::long_array_var aRes = new SMESH::long_array();
719 aRes->length(SMESH::NB_ELEMENT_TYPES);
720 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
721 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
724 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
725 bool IsMeshInfoCorrect() { return true; }
726 SMESH::array_of_ElementType* GetTypes()
728 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
729 if ( _ids.length() > 0 ) {
733 return types._retn();
735 SALOMEDS::TMPFile* GetVtkUgStream()
737 SALOMEDS::TMPFile_var SeqFile;
738 return SeqFile._retn();
742 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
743 SMESH::ElementType type)
745 _IDSource* idSrc = new _IDSource;
746 idSrc->_mesh = myMesh_i->_this();
749 if ( type == SMESH::ALL && ids.length() > 0 )
750 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
752 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
754 return anIDSourceVar._retn();
757 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
759 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
762 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
765 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
767 nbIds = (int) tmpIdSource->_ids.length();
768 return & tmpIdSource->_ids[0];
774 // void SMESH_MeshEditor_i::deleteAuxIDSources()
776 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
777 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
779 // myAuxIDSources.clear();
782 //=============================================================================
786 //=============================================================================
789 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
790 throw (SALOME::SALOME_Exception)
797 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
798 IdList.push_back( IDsOfElements[i] );
800 // Update Python script
801 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
804 bool ret = getEditor().Remove( IdList, false );
806 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
809 SMESH_CATCH( SMESH::throwCorbaException );
813 //=============================================================================
817 //=============================================================================
819 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
820 throw (SALOME::SALOME_Exception)
826 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
827 IdList.push_back( IDsOfNodes[i] );
829 // Update Python script
830 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
832 bool ret = getEditor().Remove( IdList, true );
834 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
837 SMESH_CATCH( SMESH::throwCorbaException );
841 //=============================================================================
845 //=============================================================================
847 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
848 throw (SALOME::SALOME_Exception)
853 // Update Python script
854 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
856 // Create filter to find all orphan nodes
857 SMESH::Controls::Filter::TIdSequence seq;
858 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
859 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
861 // remove orphan nodes (if there are any)
862 list< int > IdList( seq.begin(), seq.end() );
864 int nbNodesBefore = myMesh->NbNodes();
865 getEditor().Remove( IdList, true );
866 int nbNodesAfter = myMesh->NbNodes();
868 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
869 return nbNodesBefore - nbNodesAfter;
871 SMESH_CATCH( SMESH::throwCorbaException );
875 //=============================================================================
879 //=============================================================================
881 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
882 throw (SALOME::SALOME_Exception)
887 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
889 // Update Python script
890 TPythonDump() << "nodeID = " << this << ".AddNode( "
891 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
893 declareMeshModified( /*isReComputeSafe=*/false );
896 SMESH_CATCH( SMESH::throwCorbaException );
900 //=============================================================================
902 * Create 0D element on the given node.
904 //=============================================================================
906 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode,
907 CORBA::Boolean DuplicateElements)
908 throw (SALOME::SALOME_Exception)
913 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
914 SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
916 SMDS_MeshElement* elem = 0;
917 if ( DuplicateElements || !it0D->more() )
918 elem = getMeshDS()->Add0DElement(aNode);
920 // Update Python script
921 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
923 declareMeshModified( /*isReComputeSafe=*/false );
925 return elem ? elem->GetID() : 0;
927 SMESH_CATCH( SMESH::throwCorbaException );
931 //=============================================================================
933 * Create a ball element on the given node.
935 //=============================================================================
937 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
938 throw (SALOME::SALOME_Exception)
943 if ( diameter < std::numeric_limits<double>::min() )
944 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
946 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
947 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
949 // Update Python script
950 TPythonDump() << "ballElem = "
951 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
953 declareMeshModified( /*isReComputeSafe=*/false );
954 return elem ? elem->GetID() : 0;
956 SMESH_CATCH( SMESH::throwCorbaException );
960 //=============================================================================
962 * Create an edge, either linear and quadratic (this is determed
963 * by number of given nodes, two or three)
965 //=============================================================================
967 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
968 throw (SALOME::SALOME_Exception)
973 int NbNodes = IDsOfNodes.length();
974 SMDS_MeshElement* elem = 0;
977 CORBA::Long index1 = IDsOfNodes[0];
978 CORBA::Long index2 = IDsOfNodes[1];
979 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
980 getMeshDS()->FindNode(index2));
982 // Update Python script
983 TPythonDump() << "edge = " << this << ".AddEdge([ "
984 << index1 << ", " << index2 <<" ])";
987 CORBA::Long n1 = IDsOfNodes[0];
988 CORBA::Long n2 = IDsOfNodes[1];
989 CORBA::Long n12 = IDsOfNodes[2];
990 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
991 getMeshDS()->FindNode(n2),
992 getMeshDS()->FindNode(n12));
993 // Update Python script
994 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
995 <<n1<<", "<<n2<<", "<<n12<<" ])";
998 declareMeshModified( /*isReComputeSafe=*/false );
999 return elem ? elem->GetID() : 0;
1001 SMESH_CATCH( SMESH::throwCorbaException );
1005 //=============================================================================
1009 //=============================================================================
1011 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1012 throw (SALOME::SALOME_Exception)
1017 int NbNodes = IDsOfNodes.length();
1023 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1024 for (int i = 0; i < NbNodes; i++)
1025 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1027 SMDS_MeshElement* elem = 0;
1029 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1030 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1031 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1032 nodes[4], nodes[5]); break;
1033 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1034 nodes[4], nodes[5], nodes[6]); break;
1035 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1036 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1037 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1038 nodes[4], nodes[5], nodes[6], nodes[7],
1040 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1043 // Update Python script
1044 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1046 declareMeshModified( /*isReComputeSafe=*/false );
1048 return elem ? elem->GetID() : 0;
1050 SMESH_CATCH( SMESH::throwCorbaException );
1054 //=============================================================================
1058 //=============================================================================
1060 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1061 throw (SALOME::SALOME_Exception)
1066 int NbNodes = IDsOfNodes.length();
1067 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1068 for (int i = 0; i < NbNodes; i++)
1069 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1072 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1074 // Update Python script
1075 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1077 declareMeshModified( /*isReComputeSafe=*/false );
1078 return elem ? elem->GetID() : 0;
1080 SMESH_CATCH( SMESH::throwCorbaException );
1084 //=============================================================================
1086 * AddQuadPolygonalFace
1088 //=============================================================================
1090 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1091 throw (SALOME::SALOME_Exception)
1096 int NbNodes = IDsOfNodes.length();
1097 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1098 for (int i = 0; i < NbNodes; i++)
1099 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1101 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1103 // Update Python script
1104 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1106 declareMeshModified( /*isReComputeSafe=*/false );
1107 return elem ? elem->GetID() : 0;
1109 SMESH_CATCH( SMESH::throwCorbaException );
1113 //=============================================================================
1115 * Create volume, either linear and quadratic (this is determed
1116 * by number of given nodes)
1118 //=============================================================================
1120 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1121 throw (SALOME::SALOME_Exception)
1126 int NbNodes = IDsOfNodes.length();
1127 vector< const SMDS_MeshNode*> n(NbNodes);
1128 for(int i=0;i<NbNodes;i++)
1129 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1131 SMDS_MeshElement* elem = 0;
1134 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1135 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1136 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1137 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1138 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1139 n[6],n[7],n[8],n[9]);
1141 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1142 n[6],n[7],n[8],n[9],n[10],n[11]);
1144 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1145 n[7],n[8],n[9],n[10],n[11],n[12]);
1147 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1148 n[9],n[10],n[11],n[12],n[13],n[14]);
1150 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1151 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1152 n[15],n[16],n[17],n[18],n[19]);
1154 case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1155 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1158 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1159 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1160 n[15],n[16],n[17],n[18],n[19],
1161 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1165 // Update Python script
1166 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1168 declareMeshModified( /*isReComputeSafe=*/false );
1169 return elem ? elem->GetID() : 0;
1171 SMESH_CATCH( SMESH::throwCorbaException );
1175 //=============================================================================
1177 * AddPolyhedralVolume
1179 //=============================================================================
1180 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1181 const SMESH::long_array & Quantities)
1182 throw (SALOME::SALOME_Exception)
1187 int NbNodes = IDsOfNodes.length();
1188 std::vector<const SMDS_MeshNode*> n (NbNodes);
1189 for (int i = 0; i < NbNodes; i++)
1191 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1192 if (!aNode) return 0;
1196 int NbFaces = Quantities.length();
1197 std::vector<int> q (NbFaces);
1198 for (int j = 0; j < NbFaces; j++)
1199 q[j] = Quantities[j];
1201 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1203 // Update Python script
1204 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1205 << IDsOfNodes << ", " << Quantities << " )";
1207 declareMeshModified( /*isReComputeSafe=*/false );
1208 return elem ? elem->GetID() : 0;
1210 SMESH_CATCH( SMESH::throwCorbaException );
1214 //=============================================================================
1216 * AddPolyhedralVolumeByFaces
1218 //=============================================================================
1220 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1221 throw (SALOME::SALOME_Exception)
1226 int NbFaces = IdsOfFaces.length();
1227 std::vector<const SMDS_MeshNode*> poly_nodes;
1228 std::vector<int> quantities (NbFaces);
1230 for (int i = 0; i < NbFaces; i++) {
1231 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1232 quantities[i] = aFace->NbNodes();
1234 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1235 while (It->more()) {
1236 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1240 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1242 // Update Python script
1243 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1244 << IdsOfFaces << " )";
1246 declareMeshModified( /*isReComputeSafe=*/false );
1247 return elem ? elem->GetID() : 0;
1249 SMESH_CATCH( SMESH::throwCorbaException );
1253 //=============================================================================
1255 // \brief Create 0D elements on all nodes of the given object.
1256 // \param theObject object on whose nodes 0D elements will be created.
1257 // \param theGroupName optional name of a group to add 0D elements created
1258 // and/or found on nodes of \a theObject.
1259 // \param DuplicateElements to add one more 0D element to a node or not.
1260 // \return an object (a new group or a temporary SMESH_IDSource) holding
1261 // ids of new and/or found 0D elements.
1263 //=============================================================================
1265 SMESH::SMESH_IDSource_ptr
1266 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1267 const char* theGroupName,
1268 CORBA::Boolean theDuplicateElements)
1269 throw (SALOME::SALOME_Exception)
1274 SMESH::SMESH_IDSource_var result;
1277 TIDSortedElemSet elements, elems0D;
1278 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1279 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1281 SMESH::long_array_var newElems = new SMESH::long_array;
1282 newElems->length( elems0D.size() );
1283 TIDSortedElemSet::iterator eIt = elems0D.begin();
1284 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1285 newElems[ i ] = (*eIt)->GetID();
1287 SMESH::SMESH_GroupBase_var groupToFill;
1288 if ( theGroupName && strlen( theGroupName ))
1290 // Get existing group named theGroupName
1291 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1292 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1293 SMESH::SMESH_GroupBase_var group = groups[i];
1294 if ( !group->_is_nil() ) {
1295 CORBA::String_var name = group->GetName();
1296 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1297 groupToFill = group;
1302 if ( groupToFill->_is_nil() )
1303 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1304 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1305 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1308 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1310 group_i->Add( newElems );
1311 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1312 pyDump << groupToFill;
1316 result = MakeIDSource( newElems, SMESH::ELEM0D );
1317 pyDump << "elem0DIDs";
1320 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1321 << theObject << ", '" << theGroupName << "' )";
1323 return result._retn();
1325 SMESH_CATCH( SMESH::throwCorbaException );
1329 //=============================================================================
1331 * \brief Bind a node to a vertex
1332 * \param NodeID - node ID
1333 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1334 * \retval boolean - false if NodeID or VertexID is invalid
1336 //=============================================================================
1338 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1339 throw (SALOME::SALOME_Exception)
1343 SMESHDS_Mesh * mesh = getMeshDS();
1344 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1346 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1348 if ( mesh->MaxShapeIndex() < VertexID )
1349 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1351 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1352 if ( shape.ShapeType() != TopAbs_VERTEX )
1353 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1355 mesh->SetNodeOnVertex( node, VertexID );
1357 myMesh->SetIsModified( true );
1359 SMESH_CATCH( SMESH::throwCorbaException );
1362 //=============================================================================
1364 * \brief Store node position on an edge
1365 * \param NodeID - node ID
1366 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1367 * \param paramOnEdge - parameter on edge where the node is located
1368 * \retval boolean - false if any parameter is invalid
1370 //=============================================================================
1372 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1373 CORBA::Double paramOnEdge)
1374 throw (SALOME::SALOME_Exception)
1378 SMESHDS_Mesh * mesh = getMeshDS();
1379 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1381 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1383 if ( mesh->MaxShapeIndex() < EdgeID )
1384 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1386 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1387 if ( shape.ShapeType() != TopAbs_EDGE )
1388 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1391 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1392 if ( paramOnEdge < f || paramOnEdge > l )
1393 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1395 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1397 myMesh->SetIsModified( true );
1399 SMESH_CATCH( SMESH::throwCorbaException );
1402 //=============================================================================
1404 * \brief Store node position on a face
1405 * \param NodeID - node ID
1406 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1407 * \param u - U parameter on face where the node is located
1408 * \param v - V parameter on face where the node is located
1409 * \retval boolean - false if any parameter is invalid
1411 //=============================================================================
1413 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1414 CORBA::Double u, CORBA::Double v)
1415 throw (SALOME::SALOME_Exception)
1418 SMESHDS_Mesh * mesh = getMeshDS();
1419 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1421 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1423 if ( mesh->MaxShapeIndex() < FaceID )
1424 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1426 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1427 if ( shape.ShapeType() != TopAbs_FACE )
1428 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1430 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1431 bool isOut = ( u < surf.FirstUParameter() ||
1432 u > surf.LastUParameter() ||
1433 v < surf.FirstVParameter() ||
1434 v > surf.LastVParameter() );
1438 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1439 << " u( " << surf.FirstUParameter()
1440 << "," << surf.LastUParameter()
1441 << ") v( " << surf.FirstVParameter()
1442 << "," << surf.LastVParameter() << ")" );
1444 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1447 mesh->SetNodeOnFace( node, FaceID, u, v );
1448 myMesh->SetIsModified( true );
1450 SMESH_CATCH( SMESH::throwCorbaException );
1453 //=============================================================================
1455 * \brief Bind a node to a solid
1456 * \param NodeID - node ID
1457 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1458 * \retval boolean - false if NodeID or SolidID is invalid
1460 //=============================================================================
1462 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1463 throw (SALOME::SALOME_Exception)
1466 SMESHDS_Mesh * mesh = getMeshDS();
1467 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1469 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1471 if ( mesh->MaxShapeIndex() < SolidID )
1472 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1474 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1475 if ( shape.ShapeType() != TopAbs_SOLID &&
1476 shape.ShapeType() != TopAbs_SHELL)
1477 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1479 mesh->SetNodeInVolume( node, SolidID );
1481 SMESH_CATCH( SMESH::throwCorbaException );
1484 //=============================================================================
1486 * \brief Bind an element to a shape
1487 * \param ElementID - element ID
1488 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1490 //=============================================================================
1492 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1493 CORBA::Long ShapeID)
1494 throw (SALOME::SALOME_Exception)
1497 SMESHDS_Mesh * mesh = getMeshDS();
1498 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1500 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1502 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1503 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1505 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1506 if ( shape.ShapeType() != TopAbs_EDGE &&
1507 shape.ShapeType() != TopAbs_FACE &&
1508 shape.ShapeType() != TopAbs_SOLID &&
1509 shape.ShapeType() != TopAbs_SHELL )
1510 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1512 mesh->SetMeshElementOnShape( elem, ShapeID );
1514 myMesh->SetIsModified( true );
1516 SMESH_CATCH( SMESH::throwCorbaException );
1519 //=============================================================================
1523 //=============================================================================
1525 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1526 CORBA::Long NodeID2)
1527 throw (SALOME::SALOME_Exception)
1532 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1533 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1537 // Update Python script
1538 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1539 << NodeID1 << ", " << NodeID2 << " )";
1541 int ret = getEditor().InverseDiag ( n1, n2 );
1543 declareMeshModified( /*isReComputeSafe=*/false );
1546 SMESH_CATCH( SMESH::throwCorbaException );
1550 //=============================================================================
1554 //=============================================================================
1556 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1557 CORBA::Long NodeID2)
1558 throw (SALOME::SALOME_Exception)
1563 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1564 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1568 // Update Python script
1569 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1570 << NodeID1 << ", " << NodeID2 << " )";
1573 bool stat = getEditor().DeleteDiag ( n1, n2 );
1575 declareMeshModified( /*isReComputeSafe=*/!stat );
1579 SMESH_CATCH( SMESH::throwCorbaException );
1583 //=============================================================================
1587 //=============================================================================
1589 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1590 throw (SALOME::SALOME_Exception)
1595 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1597 CORBA::Long index = IDsOfElements[i];
1598 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1600 getEditor().Reorient( elem );
1602 // Update Python script
1603 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1605 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1608 SMESH_CATCH( SMESH::throwCorbaException );
1612 //=============================================================================
1616 //=============================================================================
1618 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1619 throw (SALOME::SALOME_Exception)
1624 TPythonDump aTPythonDump; // suppress dump in Reorient()
1626 prepareIdSource( theObject );
1628 SMESH::long_array_var anElementsId = theObject->GetIDs();
1629 CORBA::Boolean isDone = Reorient(anElementsId);
1631 // Update Python script
1632 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1634 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1637 SMESH_CATCH( SMESH::throwCorbaException );
1641 //=======================================================================
1642 //function : Reorient2D
1643 //purpose : Reorient faces contained in \a the2Dgroup.
1644 // the2Dgroup - the mesh or its part to reorient
1645 // theDirection - desired direction of normal of \a theFace
1646 // theFace - ID of face whose orientation is checked.
1647 // It can be < 1 then \a thePoint is used to find a face.
1648 // thePoint - is used to find a face if \a theFace < 1.
1649 // return number of reoriented elements.
1650 //=======================================================================
1652 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1653 const SMESH::DirStruct& theDirection,
1654 CORBA::Long theFace,
1655 const SMESH::PointStruct& thePoint)
1656 throw (SALOME::SALOME_Exception)
1659 initData(/*deleteSearchers=*/false);
1661 TIDSortedElemSet elements;
1662 IDSource_Error error;
1663 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1664 if ( error == IDSource_EMPTY )
1666 if ( error == IDSource_INVALID )
1667 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1670 const SMDS_MeshElement* face = 0;
1673 face = getMeshDS()->FindElement( theFace );
1675 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1676 if ( face->GetType() != SMDSAbs_Face )
1677 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1681 // create theElementSearcher if needed
1682 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1683 if ( !theElementSearcher )
1685 if ( elements.empty() ) // search in the whole mesh
1687 if ( myMesh->NbFaces() == 0 )
1688 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1690 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1694 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1695 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1697 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1701 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1702 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1705 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1706 if ( !elements.empty() && !elements.count( face ))
1707 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1710 const SMESH::PointStruct * P = &theDirection.PS;
1711 gp_Vec dirVec( P->x, P->y, P->z );
1712 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1713 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1715 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1718 declareMeshModified( /*isReComputeSafe=*/false );
1720 TPythonDump() << this << ".Reorient2D( "
1721 << the2Dgroup << ", "
1722 << theDirection << ", "
1724 << thePoint << " )";
1728 SMESH_CATCH( SMESH::throwCorbaException );
1732 //=======================================================================
1733 //function : Reorient2DBy3D
1734 //purpose : Reorient faces basing on orientation of adjacent volumes.
1735 //=======================================================================
1737 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1738 SMESH::SMESH_IDSource_ptr volumeGroup,
1739 CORBA::Boolean outsideNormal)
1740 throw (SALOME::SALOME_Exception)
1745 TIDSortedElemSet volumes;
1746 IDSource_Error volsError;
1747 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1750 for ( size_t i = 0; i < faceGroups.length(); ++i )
1752 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1754 TIDSortedElemSet faces;
1755 IDSource_Error error;
1756 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1757 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1758 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1759 if ( error == IDSource_OK && volsError != IDSource_OK )
1760 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1762 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1764 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1769 declareMeshModified( /*isReComputeSafe=*/false );
1771 TPythonDump() << this << ".Reorient2DBy3D( "
1772 << faceGroups << ", "
1773 << volumeGroup << ", "
1774 << outsideNormal << " )";
1778 SMESH_CATCH( SMESH::throwCorbaException );
1782 //=============================================================================
1784 * \brief Fuse neighbour triangles into quadrangles.
1786 //=============================================================================
1788 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1789 SMESH::NumericalFunctor_ptr Criterion,
1790 CORBA::Double MaxAngle)
1791 throw (SALOME::SALOME_Exception)
1796 SMESHDS_Mesh* aMesh = getMeshDS();
1797 TIDSortedElemSet faces,copyFaces;
1798 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1799 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1800 TIDSortedElemSet* workElements = & faces;
1802 if ( myIsPreviewMode ) {
1803 SMDSAbs_ElementType select = SMDSAbs_Face;
1804 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1805 workElements = & copyFaces;
1808 SMESH::NumericalFunctor_i* aNumericalFunctor =
1809 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1810 SMESH::Controls::NumericalFunctorPtr aCrit;
1811 if ( !aNumericalFunctor )
1812 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1814 aCrit = aNumericalFunctor->GetNumericalFunctor();
1816 if ( !myIsPreviewMode ) {
1817 // Update Python script
1818 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1819 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1822 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1824 declareMeshModified( /*isReComputeSafe=*/!stat );
1827 SMESH_CATCH( SMESH::throwCorbaException );
1831 //=============================================================================
1833 * \brief Fuse neighbour triangles into quadrangles.
1835 //=============================================================================
1837 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1838 SMESH::NumericalFunctor_ptr Criterion,
1839 CORBA::Double MaxAngle)
1840 throw (SALOME::SALOME_Exception)
1845 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1847 prepareIdSource( theObject );
1848 SMESH::long_array_var anElementsId = theObject->GetIDs();
1849 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1851 if ( !myIsPreviewMode ) {
1852 SMESH::NumericalFunctor_i* aNumericalFunctor =
1853 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1855 // Update Python script
1856 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1857 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1862 SMESH_CATCH( SMESH::throwCorbaException );
1866 //=============================================================================
1868 * \brief Split quadrangles into triangles.
1870 //=============================================================================
1872 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1873 SMESH::NumericalFunctor_ptr Criterion)
1874 throw (SALOME::SALOME_Exception)
1879 SMESHDS_Mesh* aMesh = getMeshDS();
1880 TIDSortedElemSet faces;
1881 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1883 SMESH::NumericalFunctor_i* aNumericalFunctor =
1884 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1885 SMESH::Controls::NumericalFunctorPtr aCrit;
1886 if ( !aNumericalFunctor )
1887 aCrit.reset( new SMESH::Controls::AspectRatio() );
1889 aCrit = aNumericalFunctor->GetNumericalFunctor();
1892 // Update Python script
1893 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1895 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1897 declareMeshModified( /*isReComputeSafe=*/false );
1900 SMESH_CATCH( SMESH::throwCorbaException );
1904 //=============================================================================
1906 * \brief Split quadrangles into triangles.
1908 //=============================================================================
1910 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1911 SMESH::NumericalFunctor_ptr Criterion)
1912 throw (SALOME::SALOME_Exception)
1917 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1919 prepareIdSource( theObject );
1920 SMESH::long_array_var anElementsId = theObject->GetIDs();
1921 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1923 SMESH::NumericalFunctor_i* aNumericalFunctor =
1924 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1926 // Update Python script
1927 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1929 declareMeshModified( /*isReComputeSafe=*/false );
1932 SMESH_CATCH( SMESH::throwCorbaException );
1936 //================================================================================
1938 * \brief Split each of quadrangles into 4 triangles.
1939 * \param [in] theObject - theQuads Container of quadrangles to split.
1941 //================================================================================
1943 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1944 throw (SALOME::SALOME_Exception)
1949 TIDSortedElemSet faces;
1950 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1952 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1954 getEditor().QuadTo4Tri( faces );
1955 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1957 SMESH_CATCH( SMESH::throwCorbaException );
1960 //=============================================================================
1962 * \brief Split quadrangles into triangles.
1964 //=============================================================================
1966 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1967 CORBA::Boolean Diag13)
1968 throw (SALOME::SALOME_Exception)
1973 SMESHDS_Mesh* aMesh = getMeshDS();
1974 TIDSortedElemSet faces;
1975 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1977 // Update Python script
1978 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1979 << IDsOfElements << ", " << Diag13 << " )";
1981 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1983 declareMeshModified( /*isReComputeSafe=*/ !stat );
1986 SMESH_CATCH( SMESH::throwCorbaException );
1990 //=============================================================================
1992 * \brief Split quadrangles into triangles.
1994 //=============================================================================
1996 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1997 CORBA::Boolean Diag13)
1998 throw (SALOME::SALOME_Exception)
2003 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2005 prepareIdSource( theObject );
2006 SMESH::long_array_var anElementsId = theObject->GetIDs();
2007 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2009 // Update Python script
2010 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2011 << theObject << ", " << Diag13 << " )";
2013 declareMeshModified( /*isReComputeSafe=*/!isDone );
2016 SMESH_CATCH( SMESH::throwCorbaException );
2021 //=============================================================================
2023 * Find better splitting of the given quadrangle.
2024 * \param IDOfQuad ID of the quadrangle to be split.
2025 * \param Criterion A criterion to choose a diagonal for splitting.
2026 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2027 * diagonal is better, 0 if error occurs.
2029 //=============================================================================
2031 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2032 SMESH::NumericalFunctor_ptr Criterion)
2033 throw (SALOME::SALOME_Exception)
2038 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2039 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2041 SMESH::NumericalFunctor_i* aNumericalFunctor =
2042 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2043 SMESH::Controls::NumericalFunctorPtr aCrit;
2044 if (aNumericalFunctor)
2045 aCrit = aNumericalFunctor->GetNumericalFunctor();
2047 aCrit.reset(new SMESH::Controls::AspectRatio());
2049 int id = getEditor().BestSplit(quad, aCrit);
2050 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2054 SMESH_CATCH( SMESH::throwCorbaException );
2058 //================================================================================
2060 * \brief Split volumic elements into tetrahedrons
2062 //================================================================================
2064 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2065 CORBA::Short methodFlags)
2066 throw (SALOME::SALOME_Exception)
2071 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2072 const int noneFacet = -1;
2073 prepareIdSource( elems );
2074 if ( SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME ))
2075 while ( volIt->more() )
2076 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2078 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2079 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2081 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2082 << elems << ", " << methodFlags << " )";
2084 SMESH_CATCH( SMESH::throwCorbaException );
2087 //================================================================================
2089 * \brief Split hexahedra into triangular prisms
2090 * \param elems - elements to split
2091 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2092 * to split into triangles
2093 * \param methodFlags - flags passing splitting method:
2094 * 1 - split the hexahedron into 2 prisms
2095 * 2 - split the hexahedron into 4 prisms
2097 //================================================================================
2099 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2100 const SMESH::PointStruct & startHexPoint,
2101 const SMESH::DirStruct& facetToSplitNormal,
2102 CORBA::Short methodFlags,
2103 CORBA::Boolean allDomains)
2104 throw (SALOME::SALOME_Exception)
2108 prepareIdSource( elems );
2110 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2113 gp_Dir( facetToSplitNormal.PS.x,
2114 facetToSplitNormal.PS.y,
2115 facetToSplitNormal.PS.z ));
2116 TIDSortedElemSet elemSet;
2117 prepareIdSource( elems );
2118 SMESH::long_array_var anElementsId = elems->GetIDs();
2119 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2120 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2122 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2123 while ( !elemSet.empty() )
2125 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2129 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2130 for ( ; ef != elemFacets.end(); ++ef )
2131 elemSet.erase( ef->first );
2134 if ( methodFlags == 2 )
2135 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2137 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2139 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2140 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2142 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2144 << startHexPoint << ", "
2145 << facetToSplitNormal<< ", "
2146 << methodFlags<< ", "
2147 << allDomains << " )";
2149 SMESH_CATCH( SMESH::throwCorbaException );
2152 //================================================================================
2154 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2155 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2156 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2157 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2158 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2159 * will be split in order to keep the mesh conformal.
2160 * \param elems - elements to split
2162 //================================================================================
2164 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2165 throw (SALOME::SALOME_Exception)
2170 TIDSortedElemSet elemSet;
2171 for ( size_t i = 0; i < theElems.length(); ++i )
2173 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2174 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2175 if ( mesh->GetId() != myMesh_i->GetId() )
2176 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2178 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2180 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2182 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2184 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2185 << theElems << " )";
2187 SMESH_CATCH( SMESH::throwCorbaException );
2190 //=======================================================================
2193 //=======================================================================
2196 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2197 const SMESH::long_array & IDsOfFixedNodes,
2198 CORBA::Long MaxNbOfIterations,
2199 CORBA::Double MaxAspectRatio,
2200 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2201 throw (SALOME::SALOME_Exception)
2203 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2204 MaxAspectRatio, Method, false );
2208 //=======================================================================
2209 //function : SmoothParametric
2211 //=======================================================================
2214 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2215 const SMESH::long_array & IDsOfFixedNodes,
2216 CORBA::Long MaxNbOfIterations,
2217 CORBA::Double MaxAspectRatio,
2218 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2219 throw (SALOME::SALOME_Exception)
2221 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2222 MaxAspectRatio, Method, true );
2226 //=======================================================================
2227 //function : SmoothObject
2229 //=======================================================================
2232 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2233 const SMESH::long_array & IDsOfFixedNodes,
2234 CORBA::Long MaxNbOfIterations,
2235 CORBA::Double MaxAspectRatio,
2236 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2237 throw (SALOME::SALOME_Exception)
2239 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2240 MaxAspectRatio, Method, false);
2244 //=======================================================================
2245 //function : SmoothParametricObject
2247 //=======================================================================
2250 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2251 const SMESH::long_array & IDsOfFixedNodes,
2252 CORBA::Long MaxNbOfIterations,
2253 CORBA::Double MaxAspectRatio,
2254 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2255 throw (SALOME::SALOME_Exception)
2257 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2258 MaxAspectRatio, Method, true);
2262 //=============================================================================
2266 //=============================================================================
2269 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2270 const SMESH::long_array & IDsOfFixedNodes,
2271 CORBA::Long MaxNbOfIterations,
2272 CORBA::Double MaxAspectRatio,
2273 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2275 throw (SALOME::SALOME_Exception)
2280 SMESHDS_Mesh* aMesh = getMeshDS();
2282 TIDSortedElemSet elements;
2283 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2285 set<const SMDS_MeshNode*> fixedNodes;
2286 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2287 CORBA::Long index = IDsOfFixedNodes[i];
2288 const SMDS_MeshNode * node = aMesh->FindNode(index);
2290 fixedNodes.insert( node );
2292 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2293 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2294 method = ::SMESH_MeshEditor::CENTROIDAL;
2296 getEditor().Smooth(elements, fixedNodes, method,
2297 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2299 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2301 // Update Python script
2302 TPythonDump() << "isDone = " << this << "."
2303 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2304 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2305 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2306 << "SMESH.SMESH_MeshEditor."
2307 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2308 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2312 SMESH_CATCH( SMESH::throwCorbaException );
2316 //=============================================================================
2320 //=============================================================================
2323 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2324 const SMESH::long_array & IDsOfFixedNodes,
2325 CORBA::Long MaxNbOfIterations,
2326 CORBA::Double MaxAspectRatio,
2327 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2329 throw (SALOME::SALOME_Exception)
2334 TPythonDump aTPythonDump; // suppress dump in smooth()
2336 prepareIdSource( theObject );
2337 SMESH::long_array_var anElementsId = theObject->GetIDs();
2338 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2339 MaxAspectRatio, Method, IsParametric);
2341 // Update Python script
2342 aTPythonDump << "isDone = " << this << "."
2343 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2344 << theObject << ", " << IDsOfFixedNodes << ", "
2345 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2346 << "SMESH.SMESH_MeshEditor."
2347 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2348 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2352 SMESH_CATCH( SMESH::throwCorbaException );
2356 //=============================================================================
2360 //=============================================================================
2362 void SMESH_MeshEditor_i::RenumberNodes()
2363 throw (SALOME::SALOME_Exception)
2366 // Update Python script
2367 TPythonDump() << this << ".RenumberNodes()";
2369 getMeshDS()->Renumber( true );
2371 SMESH_CATCH( SMESH::throwCorbaException );
2374 //=============================================================================
2378 //=============================================================================
2380 void SMESH_MeshEditor_i::RenumberElements()
2381 throw (SALOME::SALOME_Exception)
2384 // Update Python script
2385 TPythonDump() << this << ".RenumberElements()";
2387 getMeshDS()->Renumber( false );
2389 SMESH_CATCH( SMESH::throwCorbaException );
2392 //=======================================================================
2394 * \brief Return groups by their IDs
2396 //=======================================================================
2398 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2399 throw (SALOME::SALOME_Exception)
2404 myMesh_i->CreateGroupServants();
2405 return myMesh_i->GetGroups( *groupIDs );
2407 SMESH_CATCH( SMESH::throwCorbaException );
2411 //=======================================================================
2412 //function : RotationSweepObjects
2414 //=======================================================================
2416 SMESH::ListOfGroups*
2417 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2418 const SMESH::ListOfIDSources & theEdges,
2419 const SMESH::ListOfIDSources & theFaces,
2420 const SMESH::AxisStruct & theAxis,
2421 CORBA::Double theAngleInRadians,
2422 CORBA::Long theNbOfSteps,
2423 CORBA::Double theTolerance,
2424 const bool theMakeGroups)
2425 throw (SALOME::SALOME_Exception)
2430 TIDSortedElemSet elemsNodes[2];
2431 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2432 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2433 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2435 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2436 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2437 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2438 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2440 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2441 bool makeWalls=true;
2442 if ( myIsPreviewMode )
2444 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2445 TPreviewMesh * tmpMesh = getPreviewMesh();
2446 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2447 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2448 workElements = & copyElements[0];
2449 //makeWalls = false; -- faces are needed for preview
2452 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2454 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2455 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2457 ::SMESH_MeshEditor::PGroupIDs groupIds =
2458 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2459 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2461 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2463 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2465 if ( !myIsPreviewMode )
2467 dumpGroupsList( aPythonDump, aGroups );
2468 aPythonDump << this<< ".RotationSweepObjects( "
2473 << TVar( theAngleInRadians ) << ", "
2474 << TVar( theNbOfSteps ) << ", "
2475 << TVar( theTolerance ) << ", "
2476 << theMakeGroups << " )";
2480 getPreviewMesh()->Remove( SMDSAbs_Volume );
2483 return aGroups ? aGroups : new SMESH::ListOfGroups;
2485 SMESH_CATCH( SMESH::throwCorbaException );
2489 namespace MeshEditor_I
2492 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2494 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2496 bool myIsExtrusionByNormal;
2498 static int makeFlags( CORBA::Boolean MakeGroups,
2499 CORBA::Boolean ScaleVariation = false,
2500 CORBA::Boolean AngleVariation = false,
2501 CORBA::Boolean ByAverageNormal = false,
2502 CORBA::Boolean UseInputElemsOnly = false,
2503 CORBA::Long Flags = 0,
2504 CORBA::Boolean MakeBoundary = true )
2506 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2507 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2508 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2509 if ( ScaleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2510 if ( AngleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION;
2511 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2515 ExtrusionParams(const SMESH::DirStruct & theDir,
2516 CORBA::Long theNbOfSteps,
2517 const SMESH::double_array & theScaleFactors,
2518 CORBA::Boolean theScaleVariation,
2519 const SMESH::double_array & theAngles,
2520 CORBA::Boolean theAngleVariation,
2521 const SMESH::double_array & theBasePoint,
2522 CORBA::Boolean theMakeGroups):
2523 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2527 toList( theScaleFactors ),
2528 toList( theAngles ),
2529 TBasePoint( theBasePoint ),
2530 makeFlags( theMakeGroups, theScaleVariation, theAngleVariation )),
2531 myIsExtrusionByNormal( false )
2535 ExtrusionParams(const SMESH::DirStruct & theDir,
2536 CORBA::Long theNbOfSteps,
2537 CORBA::Boolean theMakeGroups,
2538 CORBA::Long theExtrFlags,
2539 CORBA::Double theSewTolerance):
2540 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2544 std::list<double>(),
2545 std::list<double>(),
2547 makeFlags( theMakeGroups, false, false, false, false,
2548 theExtrFlags, false ),
2550 myIsExtrusionByNormal( false )
2553 // params for extrusion by normal
2554 ExtrusionParams(CORBA::Double theStepSize,
2555 CORBA::Long theNbOfSteps,
2556 CORBA::Short theDim,
2557 CORBA::Boolean theByAverageNormal,
2558 CORBA::Boolean theUseInputElemsOnly,
2559 CORBA::Boolean theMakeGroups ):
2560 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2562 makeFlags( theMakeGroups, false, false,
2563 theByAverageNormal, theUseInputElemsOnly ),
2565 myIsExtrusionByNormal( true )
2571 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2574 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2576 std::list<double> scales;
2577 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2578 scales.push_back( theScaleFactors[i] );
2584 // structure used to convert SMESH::double_array to gp_XYZ*
2588 TBasePoint( const SMESH::double_array & theBasePoint )
2591 if ( theBasePoint.length() == 3 )
2593 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2597 operator const gp_XYZ*() const { return pp; }
2602 //=======================================================================
2604 * \brief Generate dim+1 elements by extrusion of elements along vector
2605 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2606 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2607 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2608 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2609 * \param [in] nbOfSteps - number of elements to generate from one element
2610 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2611 * corresponding to groups the input elements included in.
2612 * \return ListOfGroups - new groups created if \a toMakeGroups is true
2614 //=======================================================================
2616 SMESH::ListOfGroups*
2617 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2618 const SMESH::ListOfIDSources & theEdges,
2619 const SMESH::ListOfIDSources & theFaces,
2620 const SMESH::DirStruct & theStepVector,
2621 CORBA::Long theNbOfSteps,
2622 CORBA::Boolean theToMakeGroups,
2623 const SMESH::double_array & theScaleFactors,
2624 CORBA::Boolean theScalesVariation,
2625 const SMESH::double_array & theBasePoint,
2626 const SMESH::double_array & theAngles,
2627 CORBA::Boolean theAnglesVariation)
2628 throw (SALOME::SALOME_Exception)
2633 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, theScalesVariation,
2634 theAngles, theAnglesVariation, theBasePoint, theToMakeGroups );
2636 TIDSortedElemSet elemsNodes[2];
2637 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2638 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2639 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2641 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2642 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2643 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2644 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2646 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2647 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2648 if ( myIsPreviewMode )
2650 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2651 // previewType = SMDSAbs_Edge;
2653 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2654 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2655 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2656 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2657 workElements = & copyElements[0];
2659 params.SetNoGroups();
2661 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2663 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2664 ::SMESH_MeshEditor::PGroupIDs groupIds =
2665 getEditor().ExtrusionSweep( workElements, params, aHistory );
2667 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2669 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2671 if ( !myIsPreviewMode )
2673 dumpGroupsList( aPythonDump, aGroups );
2674 aPythonDump << this<< ".ExtrusionSweepObjects( "
2678 << theStepVector << ", "
2679 << TVar( theNbOfSteps ) << ", "
2680 << theToMakeGroups << ", "
2681 << TVar( theScaleFactors ) << ", "
2682 << theScalesVariation << ", "
2683 << TVar( theBasePoint ) << ", "
2684 << TVar( theAngles ) << ", "
2685 << theAnglesVariation << " )";
2689 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2692 return aGroups ? aGroups : new SMESH::ListOfGroups;
2694 SMESH_CATCH( SMESH::throwCorbaException );
2698 //=======================================================================
2699 //function : ExtrusionByNormal
2701 //=======================================================================
2703 SMESH::ListOfGroups*
2704 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2705 CORBA::Double stepSize,
2706 CORBA::Long nbOfSteps,
2707 CORBA::Boolean byAverageNormal,
2708 CORBA::Boolean useInputElemsOnly,
2709 CORBA::Boolean makeGroups,
2711 throw (SALOME::SALOME_Exception)
2716 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2718 ExtrusionParams params( stepSize, nbOfSteps, dim,
2719 byAverageNormal, useInputElemsOnly, makeGroups );
2721 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2722 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2724 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2725 if (( elemTypes->length() == 1 ) &&
2726 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2727 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2730 TIDSortedElemSet elemsNodes[2];
2731 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2732 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2734 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2735 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2736 if ( myIsPreviewMode )
2738 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2739 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2740 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2741 workElements = & copyElements[0];
2743 params.SetNoGroups();
2746 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2747 ::SMESH_MeshEditor::PGroupIDs groupIds =
2748 getEditor().ExtrusionSweep( workElements, params, aHistory );
2750 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2752 if (!myIsPreviewMode) {
2753 dumpGroupsList(aPythonDump, aGroups);
2754 aPythonDump << this << ".ExtrusionByNormal( " << objects
2755 << ", " << TVar( stepSize )
2756 << ", " << TVar( nbOfSteps )
2757 << ", " << byAverageNormal
2758 << ", " << useInputElemsOnly
2759 << ", " << makeGroups
2765 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2768 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2770 return aGroups ? aGroups : new SMESH::ListOfGroups;
2772 SMESH_CATCH( SMESH::throwCorbaException );
2776 //=======================================================================
2777 //function : AdvancedExtrusion
2779 //=======================================================================
2781 SMESH::ListOfGroups*
2782 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2783 const SMESH::DirStruct & theStepVector,
2784 CORBA::Long theNbOfSteps,
2785 CORBA::Long theExtrFlags,
2786 CORBA::Double theSewTolerance,
2787 CORBA::Boolean theMakeGroups)
2788 throw (SALOME::SALOME_Exception)
2793 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2795 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2796 theExtrFlags, theSewTolerance );
2798 TIDSortedElemSet elemsNodes[2];
2799 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2801 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2802 ::SMESH_MeshEditor::PGroupIDs groupIds =
2803 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2805 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2807 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2809 if ( !myIsPreviewMode ) {
2810 dumpGroupsList(aPythonDump, aGroups);
2811 aPythonDump << this << ".AdvancedExtrusion( "
2812 << theIDsOfElements << ", "
2813 << theStepVector << ", "
2814 << theNbOfSteps << ", "
2815 << theExtrFlags << ", "
2816 << theSewTolerance << ", "
2817 << theMakeGroups << " )";
2821 getPreviewMesh()->Remove( SMDSAbs_Volume );
2824 return aGroups ? aGroups : new SMESH::ListOfGroups;
2826 SMESH_CATCH( SMESH::throwCorbaException );
2830 //================================================================================
2832 * \brief Convert extrusion error to IDL enum
2834 //================================================================================
2838 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2840 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2844 RETCASE( EXTR_NO_ELEMENTS );
2845 RETCASE( EXTR_PATH_NOT_EDGE );
2846 RETCASE( EXTR_BAD_PATH_SHAPE );
2847 RETCASE( EXTR_BAD_STARTING_NODE );
2848 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2849 RETCASE( EXTR_CANT_GET_TANGENT );
2851 return SMESH::SMESH_MeshEditor::EXTR_OK;
2855 //=======================================================================
2856 //function : extrusionAlongPath
2858 //=======================================================================
2859 SMESH::ListOfGroups*
2860 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2861 const SMESH::ListOfIDSources & theEdges,
2862 const SMESH::ListOfIDSources & theFaces,
2863 SMESH::SMESH_IDSource_ptr thePathObject,
2864 GEOM::GEOM_Object_ptr thePathShape,
2865 CORBA::Long theNodeStart,
2866 CORBA::Boolean theHasAngles,
2867 const SMESH::double_array & theAngles,
2868 CORBA::Boolean theAnglesVariation,
2869 CORBA::Boolean theHasRefPoint,
2870 const SMESH::PointStruct & theRefPoint,
2872 const SMESH::double_array & theScaleFactors,
2873 CORBA::Boolean theScalesVariation,
2874 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2875 throw (SALOME::SALOME_Exception)
2880 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2882 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2883 if ( thePathObject->_is_nil() )
2884 return aGroups._retn();
2887 SMDS_ElemIteratorPtr pathEdgesIterator;
2889 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathObject );
2890 if ( !CORBA::is_nil( thePathShape ) && aMeshImp )
2892 // get a sub-mesh of thePathShape
2893 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2894 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2896 return aGroups._retn();
2898 if ( !aSubMesh->GetSubMeshDS() )
2900 SMESHDS_Mesh * meshDS = aMeshImp->GetImpl().GetMeshDS();
2901 meshDS->AddCompoundSubmesh( aShape, TopAbs_EDGE );
2902 if ( !aSubMesh->GetSubMeshDS() )
2903 return aGroups._retn();
2905 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2906 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2907 if ( !pathEdgesIterator->more() ||
2908 pathEdgesIterator->next()->GetType() != SMDSAbs_Edge )
2909 return aGroups._retn();
2911 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2915 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2916 prepareIdSource( thePathObject );
2917 pathEdgesIterator = SMESH_Mesh_i::GetElements( thePathObject, SMESH::EDGE );
2918 if ( !pathEdgesIterator || !pathEdgesIterator->more() )
2919 return aGroups._retn();
2924 SMESH::SMESH_Mesh_var pathMesh = thePathObject->GetMesh();
2925 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( pathMesh );
2929 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2930 const SMDS_MeshNode* nodeStart = aMeshImp->GetImpl().GetMeshDS()->FindNode( theNodeStart );
2932 return aGroups._retn();
2935 TIDSortedElemSet elemsNodes[2];
2936 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2937 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2938 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2940 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2941 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2942 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2943 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2945 list<double> angles = ExtrusionParams::toList( theAngles );
2946 list<double> scales = ExtrusionParams::toList( theScaleFactors );
2948 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2949 const gp_Pnt *refPntPtr = theHasRefPoint ? &refPnt : 0;
2951 int nbOldGroups = myMesh->NbGroup();
2953 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2954 if ( myIsPreviewMode )
2956 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2957 TPreviewMesh * tmpMesh = getPreviewMesh();
2958 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2959 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2960 workElements = & copyElements[0];
2961 theMakeGroups = false;
2964 ::SMESH_MeshEditor::Extrusion_Error error =
2965 getEditor().ExtrusionAlongTrack( workElements,
2966 &(aMeshImp->GetImpl()), pathEdgesIterator, nodeStart,
2967 angles, theAnglesVariation,
2968 scales, theScalesVariation,
2969 refPntPtr, theMakeGroups );
2971 declareMeshModified( /*isReComputeSafe=*/true );
2972 theError = convExtrError( error );
2974 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2975 if ( theMakeGroups ) {
2976 list<int> groupIDs = myMesh->GetGroupIds();
2977 list<int>::iterator newBegin = groupIDs.begin();
2978 std::advance( newBegin, nbOldGroups ); // skip old groups
2979 groupIDs.erase( groupIDs.begin(), newBegin );
2980 aGroups = getGroups( & groupIDs );
2981 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2984 if ( !myIsPreviewMode ) {
2985 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2986 else aPythonDump << "(_noGroups, error) = ";
2987 aPythonDump << this << ".ExtrusionAlongPathObjects( "
2991 << thePathObject << ", "
2992 << thePathShape << ", "
2993 << theNodeStart << ", "
2994 << theHasAngles << ", "
2995 << TVar( theAngles ) << ", "
2996 << theAnglesVariation << ", "
2997 << theHasRefPoint << ", "
2998 << "SMESH.PointStruct( "
2999 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3000 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3001 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
3002 << theMakeGroups << ", "
3003 << TVar( theScaleFactors ) << ", "
3004 << theScalesVariation << " )";
3008 getPreviewMesh()->Remove( SMDSAbs_Volume );
3011 return aGroups._retn();
3013 SMESH_CATCH( SMESH::throwCorbaException );
3017 //================================================================================
3019 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
3020 * of given angles along path steps
3021 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
3022 * which proceeds the extrusion
3023 * \param PathShape is shape(edge); as the mesh can be complex, the edge
3024 * is used to define the sub-mesh for the path
3026 //================================================================================
3028 SMESH::double_array*
3029 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
3030 GEOM::GEOM_Object_ptr thePathShape,
3031 const SMESH::double_array & theAngles)
3033 SMESH::double_array_var aResult = new SMESH::double_array();
3034 int nbAngles = theAngles.length();
3035 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3037 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3038 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3039 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3040 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3041 return aResult._retn();
3042 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3043 if ( nbSteps == nbAngles )
3045 aResult.inout() = theAngles;
3049 aResult->length( nbSteps );
3050 double rAn2St = double( nbAngles ) / double( nbSteps );
3051 double angPrev = 0, angle;
3052 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3054 double angCur = rAn2St * ( iSt+1 );
3055 double angCurFloor = floor( angCur );
3056 double angPrevFloor = floor( angPrev );
3057 if ( angPrevFloor == angCurFloor )
3058 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3061 int iP = int( angPrevFloor );
3062 double angPrevCeil = ceil(angPrev);
3063 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3065 int iC = int( angCurFloor );
3066 if ( iC < nbAngles )
3067 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3069 iP = int( angPrevCeil );
3071 angle += theAngles[ iC ];
3073 aResult[ iSt ] = angle;
3078 // Update Python script
3079 TPythonDump() << "rotAngles = " << theAngles;
3080 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3081 << thePathMesh << ", "
3082 << thePathShape << ", "
3085 return aResult._retn();
3088 //=======================================================================
3091 //=======================================================================
3093 SMESH::ListOfGroups*
3094 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3095 const SMESH::AxisStruct & theAxis,
3096 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3097 CORBA::Boolean theCopy,
3099 ::SMESH_Mesh* theTargetMesh)
3100 throw (SALOME::SALOME_Exception)
3105 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3106 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3108 if ( theTargetMesh )
3112 switch ( theMirrorType ) {
3113 case SMESH::SMESH_MeshEditor::POINT:
3114 aTrsf.SetMirror( P );
3116 case SMESH::SMESH_MeshEditor::AXIS:
3117 aTrsf.SetMirror( gp_Ax1( P, V ));
3120 aTrsf.SetMirror( gp_Ax2( P, V ));
3123 TIDSortedElemSet copyElements;
3124 TIDSortedElemSet* workElements = & theElements;
3126 if ( myIsPreviewMode )
3128 TPreviewMesh * tmpMesh = getPreviewMesh();
3129 tmpMesh->Copy( theElements, copyElements);
3130 if ( !theCopy && !theTargetMesh )
3132 TIDSortedElemSet elemsAround, elemsAroundCopy;
3133 getElementsAround( theElements, getMeshDS(), elemsAround );
3134 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3136 workElements = & copyElements;
3137 theMakeGroups = false;
3140 ::SMESH_MeshEditor::PGroupIDs groupIds =
3141 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3143 if ( !myIsPreviewMode )
3145 if ( theTargetMesh )
3146 theTargetMesh->GetMeshDS()->Modified();
3148 declareMeshModified( /*isReComputeSafe=*/false );
3151 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3153 SMESH_CATCH( SMESH::throwCorbaException );
3157 //=======================================================================
3160 //=======================================================================
3162 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3163 const SMESH::AxisStruct & theAxis,
3164 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3165 CORBA::Boolean theCopy)
3166 throw (SALOME::SALOME_Exception)
3168 if ( !myIsPreviewMode ) {
3169 TPythonDump() << this << ".Mirror( "
3170 << theIDsOfElements << ", "
3172 << mirrorTypeName(theMirrorType) << ", "
3175 if ( theIDsOfElements.length() > 0 )
3177 TIDSortedElemSet elements;
3178 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3179 mirror(elements, theAxis, theMirrorType, theCopy, false);
3184 //=======================================================================
3185 //function : MirrorObject
3187 //=======================================================================
3189 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3190 const SMESH::AxisStruct & theAxis,
3191 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3192 CORBA::Boolean theCopy)
3193 throw (SALOME::SALOME_Exception)
3195 if ( !myIsPreviewMode ) {
3196 TPythonDump() << this << ".MirrorObject( "
3197 << theObject << ", "
3199 << mirrorTypeName(theMirrorType) << ", "
3202 TIDSortedElemSet elements;
3204 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3206 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3207 mirror(elements, theAxis, theMirrorType, theCopy, false);
3210 //=======================================================================
3211 //function : MirrorMakeGroups
3213 //=======================================================================
3215 SMESH::ListOfGroups*
3216 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3217 const SMESH::AxisStruct& theMirror,
3218 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3219 throw (SALOME::SALOME_Exception)
3221 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3223 SMESH::ListOfGroups * aGroups = 0;
3224 if ( theIDsOfElements.length() > 0 )
3226 TIDSortedElemSet elements;
3227 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3228 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3230 if (!myIsPreviewMode) {
3231 dumpGroupsList(aPythonDump, aGroups);
3232 aPythonDump << this << ".MirrorMakeGroups( "
3233 << theIDsOfElements << ", "
3234 << theMirror << ", "
3235 << mirrorTypeName(theMirrorType) << " )";
3240 //=======================================================================
3241 //function : MirrorObjectMakeGroups
3243 //=======================================================================
3245 SMESH::ListOfGroups*
3246 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3247 const SMESH::AxisStruct& theMirror,
3248 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3249 throw (SALOME::SALOME_Exception)
3251 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3253 SMESH::ListOfGroups * aGroups = 0;
3254 TIDSortedElemSet elements;
3255 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3256 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3258 if (!myIsPreviewMode)
3260 dumpGroupsList(aPythonDump,aGroups);
3261 aPythonDump << this << ".MirrorObjectMakeGroups( "
3262 << theObject << ", "
3263 << theMirror << ", "
3264 << mirrorTypeName(theMirrorType) << " )";
3269 //=======================================================================
3270 //function : MirrorMakeMesh
3272 //=======================================================================
3274 SMESH::SMESH_Mesh_ptr
3275 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3276 const SMESH::AxisStruct& theMirror,
3277 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3278 CORBA::Boolean theCopyGroups,
3279 const char* theMeshName)
3280 throw (SALOME::SALOME_Exception)
3282 SMESH_Mesh_i* mesh_i;
3283 SMESH::SMESH_Mesh_var mesh;
3284 { // open new scope to dump "MakeMesh" command
3285 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3287 TPythonDump pydump; // to prevent dump at mesh creation
3289 mesh = makeMesh( theMeshName );
3290 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3291 if (mesh_i && theIDsOfElements.length() > 0 )
3293 TIDSortedElemSet elements;
3294 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3295 mirror(elements, theMirror, theMirrorType,
3296 false, theCopyGroups, & mesh_i->GetImpl());
3297 mesh_i->CreateGroupServants();
3300 if (!myIsPreviewMode) {
3301 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3302 << theIDsOfElements << ", "
3303 << theMirror << ", "
3304 << mirrorTypeName(theMirrorType) << ", "
3305 << theCopyGroups << ", '"
3306 << theMeshName << "' )";
3311 if (!myIsPreviewMode && mesh_i)
3312 mesh_i->GetGroups();
3314 return mesh._retn();
3317 //=======================================================================
3318 //function : MirrorObjectMakeMesh
3320 //=======================================================================
3322 SMESH::SMESH_Mesh_ptr
3323 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3324 const SMESH::AxisStruct& theMirror,
3325 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3326 CORBA::Boolean theCopyGroups,
3327 const char* theMeshName)
3328 throw (SALOME::SALOME_Exception)
3330 SMESH_Mesh_i* mesh_i;
3331 SMESH::SMESH_Mesh_var mesh;
3332 { // open new scope to dump "MakeMesh" command
3333 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3335 TPythonDump pydump; // to prevent dump at mesh creation
3337 mesh = makeMesh( theMeshName );
3338 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3339 TIDSortedElemSet elements;
3341 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3343 mirror(elements, theMirror, theMirrorType,
3344 false, theCopyGroups, & mesh_i->GetImpl());
3345 mesh_i->CreateGroupServants();
3347 if (!myIsPreviewMode) {
3348 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3349 << theObject << ", "
3350 << theMirror << ", "
3351 << mirrorTypeName(theMirrorType) << ", "
3352 << theCopyGroups << ", '"
3353 << theMeshName << "' )";
3358 if (!myIsPreviewMode && mesh_i)
3359 mesh_i->GetGroups();
3361 return mesh._retn();
3364 //=======================================================================
3365 //function : translate
3367 //=======================================================================
3369 SMESH::ListOfGroups*
3370 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3371 const SMESH::DirStruct & theVector,
3372 CORBA::Boolean theCopy,
3374 ::SMESH_Mesh* theTargetMesh)
3375 throw (SALOME::SALOME_Exception)
3380 if ( theTargetMesh )
3384 const SMESH::PointStruct * P = &theVector.PS;
3385 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3387 TIDSortedElemSet copyElements;
3388 TIDSortedElemSet* workElements = &theElements;
3390 if ( myIsPreviewMode )
3392 TPreviewMesh * tmpMesh = getPreviewMesh();
3393 tmpMesh->Copy( theElements, copyElements);
3394 if ( !theCopy && !theTargetMesh )
3396 TIDSortedElemSet elemsAround, elemsAroundCopy;
3397 getElementsAround( theElements, getMeshDS(), elemsAround );
3398 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3400 workElements = & copyElements;
3401 theMakeGroups = false;
3404 ::SMESH_MeshEditor::PGroupIDs groupIds =
3405 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3407 if ( !myIsPreviewMode )
3409 if ( theTargetMesh )
3410 theTargetMesh->GetMeshDS()->Modified();
3412 declareMeshModified( /*isReComputeSafe=*/false );
3415 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3417 SMESH_CATCH( SMESH::throwCorbaException );
3421 //=======================================================================
3422 //function : Translate
3424 //=======================================================================
3426 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3427 const SMESH::DirStruct & theVector,
3428 CORBA::Boolean theCopy)
3429 throw (SALOME::SALOME_Exception)
3431 if (!myIsPreviewMode) {
3432 TPythonDump() << this << ".Translate( "
3433 << theIDsOfElements << ", "
3434 << theVector << ", "
3437 if (theIDsOfElements.length()) {
3438 TIDSortedElemSet elements;
3439 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3440 translate(elements, theVector, theCopy, false);
3444 //=======================================================================
3445 //function : TranslateObject
3447 //=======================================================================
3449 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3450 const SMESH::DirStruct & theVector,
3451 CORBA::Boolean theCopy)
3452 throw (SALOME::SALOME_Exception)
3454 if (!myIsPreviewMode) {
3455 TPythonDump() << this << ".TranslateObject( "
3456 << theObject << ", "
3457 << theVector << ", "
3460 TIDSortedElemSet elements;
3462 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3464 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3465 translate(elements, theVector, theCopy, false);
3468 //=======================================================================
3469 //function : TranslateMakeGroups
3471 //=======================================================================
3473 SMESH::ListOfGroups*
3474 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3475 const SMESH::DirStruct& theVector)
3476 throw (SALOME::SALOME_Exception)
3478 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3480 SMESH::ListOfGroups * aGroups = 0;
3481 if (theIDsOfElements.length()) {
3482 TIDSortedElemSet elements;
3483 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3484 aGroups = translate(elements,theVector,true,true);
3486 if (!myIsPreviewMode) {
3487 dumpGroupsList(aPythonDump, aGroups);
3488 aPythonDump << this << ".TranslateMakeGroups( "
3489 << theIDsOfElements << ", "
3490 << theVector << " )";
3495 //=======================================================================
3496 //function : TranslateObjectMakeGroups
3498 //=======================================================================
3500 SMESH::ListOfGroups*
3501 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3502 const SMESH::DirStruct& theVector)
3503 throw (SALOME::SALOME_Exception)
3505 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3507 SMESH::ListOfGroups * aGroups = 0;
3508 TIDSortedElemSet elements;
3509 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3510 aGroups = translate(elements, theVector, true, true);
3512 if (!myIsPreviewMode) {
3513 dumpGroupsList(aPythonDump, aGroups);
3514 aPythonDump << this << ".TranslateObjectMakeGroups( "
3515 << theObject << ", "
3516 << theVector << " )";
3521 //=======================================================================
3522 //function : TranslateMakeMesh
3524 //=======================================================================
3526 SMESH::SMESH_Mesh_ptr
3527 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3528 const SMESH::DirStruct& theVector,
3529 CORBA::Boolean theCopyGroups,
3530 const char* theMeshName)
3531 throw (SALOME::SALOME_Exception)
3533 SMESH_Mesh_i* mesh_i;
3534 SMESH::SMESH_Mesh_var mesh;
3536 { // open new scope to dump "MakeMesh" command
3537 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3539 TPythonDump pydump; // to prevent dump at mesh creation
3541 mesh = makeMesh( theMeshName );
3542 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3544 if ( mesh_i && theIDsOfElements.length() )
3546 TIDSortedElemSet elements;
3547 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3548 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3549 mesh_i->CreateGroupServants();
3552 if ( !myIsPreviewMode ) {
3553 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3554 << theIDsOfElements << ", "
3555 << theVector << ", "
3556 << theCopyGroups << ", '"
3557 << theMeshName << "' )";
3562 if (!myIsPreviewMode && mesh_i)
3563 mesh_i->GetGroups();
3565 return mesh._retn();
3568 //=======================================================================
3569 //function : TranslateObjectMakeMesh
3571 //=======================================================================
3573 SMESH::SMESH_Mesh_ptr
3574 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3575 const SMESH::DirStruct& theVector,
3576 CORBA::Boolean theCopyGroups,
3577 const char* theMeshName)
3578 throw (SALOME::SALOME_Exception)
3581 SMESH_Mesh_i* mesh_i;
3582 SMESH::SMESH_Mesh_var mesh;
3583 { // open new scope to dump "MakeMesh" command
3584 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3586 TPythonDump pydump; // to prevent dump at mesh creation
3587 mesh = makeMesh( theMeshName );
3588 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3590 TIDSortedElemSet elements;
3592 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3594 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3595 mesh_i->CreateGroupServants();
3597 if ( !myIsPreviewMode ) {
3598 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3599 << theObject << ", "
3600 << theVector << ", "
3601 << theCopyGroups << ", '"
3602 << theMeshName << "' )";
3607 if (!myIsPreviewMode && mesh_i)
3608 mesh_i->GetGroups();
3610 return mesh._retn();
3612 SMESH_CATCH( SMESH::throwCorbaException );
3616 //=======================================================================
3619 //=======================================================================
3621 SMESH::ListOfGroups*
3622 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3623 const SMESH::AxisStruct & theAxis,
3624 CORBA::Double theAngle,
3625 CORBA::Boolean theCopy,
3627 ::SMESH_Mesh* theTargetMesh)
3628 throw (SALOME::SALOME_Exception)
3633 if ( theTargetMesh )
3636 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3637 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3640 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3642 TIDSortedElemSet copyElements;
3643 TIDSortedElemSet* workElements = &theElements;
3644 if ( myIsPreviewMode ) {
3645 TPreviewMesh * tmpMesh = getPreviewMesh();
3646 tmpMesh->Copy( theElements, copyElements );
3647 if ( !theCopy && !theTargetMesh )
3649 TIDSortedElemSet elemsAround, elemsAroundCopy;
3650 getElementsAround( theElements, getMeshDS(), elemsAround );
3651 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3653 workElements = ©Elements;
3654 theMakeGroups = false;
3657 ::SMESH_MeshEditor::PGroupIDs groupIds =
3658 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3660 if ( !myIsPreviewMode)
3662 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3663 else declareMeshModified( /*isReComputeSafe=*/false );
3666 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3668 SMESH_CATCH( SMESH::throwCorbaException );
3672 //=======================================================================
3675 //=======================================================================
3677 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3678 const SMESH::AxisStruct & theAxis,
3679 CORBA::Double theAngle,
3680 CORBA::Boolean theCopy)
3681 throw (SALOME::SALOME_Exception)
3683 if (!myIsPreviewMode) {
3684 TPythonDump() << this << ".Rotate( "
3685 << theIDsOfElements << ", "
3687 << TVar( theAngle ) << ", "
3690 if (theIDsOfElements.length() > 0)
3692 TIDSortedElemSet elements;
3693 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3694 rotate(elements,theAxis,theAngle,theCopy,false);
3698 //=======================================================================
3699 //function : RotateObject
3701 //=======================================================================
3703 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3704 const SMESH::AxisStruct & theAxis,
3705 CORBA::Double theAngle,
3706 CORBA::Boolean theCopy)
3707 throw (SALOME::SALOME_Exception)
3709 if ( !myIsPreviewMode ) {
3710 TPythonDump() << this << ".RotateObject( "
3711 << theObject << ", "
3713 << TVar( theAngle ) << ", "
3716 TIDSortedElemSet elements;
3717 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3718 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3719 rotate(elements,theAxis,theAngle,theCopy,false);
3722 //=======================================================================
3723 //function : RotateMakeGroups
3725 //=======================================================================
3727 SMESH::ListOfGroups*
3728 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3729 const SMESH::AxisStruct& theAxis,
3730 CORBA::Double theAngle)
3731 throw (SALOME::SALOME_Exception)
3733 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3735 SMESH::ListOfGroups * aGroups = 0;
3736 if (theIDsOfElements.length() > 0)
3738 TIDSortedElemSet elements;
3739 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3740 aGroups = rotate(elements,theAxis,theAngle,true,true);
3742 if (!myIsPreviewMode) {
3743 dumpGroupsList(aPythonDump, aGroups);
3744 aPythonDump << this << ".RotateMakeGroups( "
3745 << theIDsOfElements << ", "
3747 << TVar( theAngle ) << " )";
3752 //=======================================================================
3753 //function : RotateObjectMakeGroups
3755 //=======================================================================
3757 SMESH::ListOfGroups*
3758 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3759 const SMESH::AxisStruct& theAxis,
3760 CORBA::Double theAngle)
3761 throw (SALOME::SALOME_Exception)
3763 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3765 SMESH::ListOfGroups * aGroups = 0;
3766 TIDSortedElemSet elements;
3767 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3768 aGroups = rotate(elements, theAxis, theAngle, true, true);
3770 if (!myIsPreviewMode) {
3771 dumpGroupsList(aPythonDump, aGroups);
3772 aPythonDump << this << ".RotateObjectMakeGroups( "
3773 << theObject << ", "
3775 << TVar( theAngle ) << " )";
3780 //=======================================================================
3781 //function : RotateMakeMesh
3783 //=======================================================================
3785 SMESH::SMESH_Mesh_ptr
3786 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3787 const SMESH::AxisStruct& theAxis,
3788 CORBA::Double theAngleInRadians,
3789 CORBA::Boolean theCopyGroups,
3790 const char* theMeshName)
3791 throw (SALOME::SALOME_Exception)
3794 SMESH::SMESH_Mesh_var mesh;
3795 SMESH_Mesh_i* mesh_i;
3797 { // open new scope to dump "MakeMesh" command
3798 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3800 TPythonDump pydump; // to prevent dump at mesh creation
3802 mesh = makeMesh( theMeshName );
3803 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3805 if ( mesh_i && theIDsOfElements.length() > 0 )
3807 TIDSortedElemSet elements;
3808 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3809 rotate(elements, theAxis, theAngleInRadians,
3810 false, theCopyGroups, & mesh_i->GetImpl());
3811 mesh_i->CreateGroupServants();
3813 if ( !myIsPreviewMode ) {
3814 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3815 << theIDsOfElements << ", "
3817 << TVar( theAngleInRadians ) << ", "
3818 << theCopyGroups << ", '"
3819 << theMeshName << "' )";
3824 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3825 mesh_i->GetGroups();
3827 return mesh._retn();
3829 SMESH_CATCH( SMESH::throwCorbaException );
3833 //=======================================================================
3834 //function : RotateObjectMakeMesh
3836 //=======================================================================
3838 SMESH::SMESH_Mesh_ptr
3839 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3840 const SMESH::AxisStruct& theAxis,
3841 CORBA::Double theAngleInRadians,
3842 CORBA::Boolean theCopyGroups,
3843 const char* theMeshName)
3844 throw (SALOME::SALOME_Exception)
3847 SMESH::SMESH_Mesh_var mesh;
3848 SMESH_Mesh_i* mesh_i;
3850 {// open new scope to dump "MakeMesh" command
3851 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3853 TPythonDump pydump; // to prevent dump at mesh creation
3854 mesh = makeMesh( theMeshName );
3855 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3857 TIDSortedElemSet elements;
3859 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3861 rotate(elements, theAxis, theAngleInRadians,
3862 false, theCopyGroups, & mesh_i->GetImpl());
3863 mesh_i->CreateGroupServants();
3865 if ( !myIsPreviewMode ) {
3866 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3867 << theObject << ", "
3869 << TVar( theAngleInRadians ) << ", "
3870 << theCopyGroups << ", '"
3871 << theMeshName << "' )";
3876 if (!myIsPreviewMode && mesh_i)
3877 mesh_i->GetGroups();
3879 return mesh._retn();
3881 SMESH_CATCH( SMESH::throwCorbaException );
3885 //=======================================================================
3888 //=======================================================================
3890 SMESH::ListOfGroups*
3891 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3892 const SMESH::PointStruct& thePoint,
3893 const SMESH::double_array& theScaleFact,
3894 CORBA::Boolean theCopy,
3896 ::SMESH_Mesh* theTargetMesh)
3897 throw (SALOME::SALOME_Exception)
3901 if ( theScaleFact.length() < 1 )
3902 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3903 if ( theScaleFact.length() == 2 )
3904 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3906 if ( theTargetMesh )
3909 TIDSortedElemSet elements;
3910 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3911 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3916 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3917 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3921 // fight against orthogonalization
3922 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3923 // 0, S[1], 0, thePoint.y * (1-S[1]),
3924 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3925 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3926 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3927 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3928 loc.SetCoord( thePoint.x * (1-S[0]),
3929 thePoint.y * (1-S[1]),
3930 thePoint.z * (1-S[2]));
3931 M.SetDiagonal( S[0], S[1], S[2] );
3933 TIDSortedElemSet copyElements;
3934 TIDSortedElemSet* workElements = &elements;
3935 if ( myIsPreviewMode )
3937 TPreviewMesh * tmpMesh = getPreviewMesh();
3938 tmpMesh->Copy( elements, copyElements);
3939 if ( !theCopy && !theTargetMesh )
3941 TIDSortedElemSet elemsAround, elemsAroundCopy;
3942 getElementsAround( elements, getMeshDS(), elemsAround );
3943 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3945 workElements = & copyElements;
3946 theMakeGroups = false;
3949 ::SMESH_MeshEditor::PGroupIDs groupIds =
3950 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3952 if ( !myIsPreviewMode )
3954 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3955 else declareMeshModified( /*isReComputeSafe=*/false );
3957 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3959 SMESH_CATCH( SMESH::throwCorbaException );
3963 //=======================================================================
3966 //=======================================================================
3968 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3969 const SMESH::PointStruct& thePoint,
3970 const SMESH::double_array& theScaleFact,
3971 CORBA::Boolean theCopy)
3972 throw (SALOME::SALOME_Exception)
3974 if ( !myIsPreviewMode ) {
3975 TPythonDump() << this << ".Scale( "
3976 << theObject << ", "
3978 << TVar( theScaleFact ) << ", "
3981 scale(theObject, thePoint, theScaleFact, theCopy, false);
3985 //=======================================================================
3986 //function : ScaleMakeGroups
3988 //=======================================================================
3990 SMESH::ListOfGroups*
3991 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3992 const SMESH::PointStruct& thePoint,
3993 const SMESH::double_array& theScaleFact)
3994 throw (SALOME::SALOME_Exception)
3996 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3998 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3999 if (!myIsPreviewMode) {
4000 dumpGroupsList(aPythonDump, aGroups);
4001 aPythonDump << this << ".Scale("
4004 << TVar( theScaleFact ) << ",True,True)";
4010 //=======================================================================
4011 //function : ScaleMakeMesh
4013 //=======================================================================
4015 SMESH::SMESH_Mesh_ptr
4016 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4017 const SMESH::PointStruct& thePoint,
4018 const SMESH::double_array& theScaleFact,
4019 CORBA::Boolean theCopyGroups,
4020 const char* theMeshName)
4021 throw (SALOME::SALOME_Exception)
4023 SMESH_Mesh_i* mesh_i;
4024 SMESH::SMESH_Mesh_var mesh;
4025 { // open new scope to dump "MakeMesh" command
4026 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4028 TPythonDump pydump; // to prevent dump at mesh creation
4029 mesh = makeMesh( theMeshName );
4030 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4034 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4035 mesh_i->CreateGroupServants();
4037 if ( !myIsPreviewMode )
4038 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4039 << theObject << ", "
4041 << TVar( theScaleFact ) << ", "
4042 << theCopyGroups << ", '"
4043 << theMeshName << "' )";
4047 if (!myIsPreviewMode && mesh_i)
4048 mesh_i->GetGroups();
4050 return mesh._retn();
4053 //================================================================================
4055 * \brief Make an offset mesh from a source 2D mesh
4056 * \param [inout] theObject - source mesh. New elements are added to this mesh
4057 * if \a theMeshName is empty.
4058 * \param [in] theValue - offset value
4059 * \param [in] theCopyGroups - to generate groups
4060 * \param [in] theMeshName - optional name of a new mesh
4061 * \param [out] theGroups - new groups
4062 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
4064 //================================================================================
4066 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4067 CORBA::Double theValue,
4068 CORBA::Boolean theCopyGroups,
4069 CORBA::Boolean theCopyElements,
4070 const char* theMeshName,
4071 SMESH::ListOfGroups_out theGroups)
4072 throw (SALOME::SALOME_Exception)
4077 SMESHDS_Mesh* aMeshDS = getMeshDS();
4079 SMESH::SMESH_Mesh_var mesh_var;
4080 ::SMESH_MeshEditor::PGroupIDs groupIds;
4084 TIDSortedElemSet elements, copyElements;
4085 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4086 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4089 SMESH_Mesh* tgtMesh = 0;
4090 if ( myIsPreviewMode )
4092 TPreviewMesh * tmpMesh = getPreviewMesh();
4094 tmpMesh->Copy( elements, copyElements );
4095 elements.swap( copyElements );
4096 theCopyGroups = false;
4097 theCopyElements = false;
4102 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4103 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4104 tgtMesh = & mesh_i->GetImpl();
4106 groupIds = getEditor().Offset( elements, theValue, tgtMesh,
4107 theCopyGroups, theCopyElements, !myIsPreviewMode );
4109 tgtMesh->GetMeshDS()->Modified();
4112 if ( myIsPreviewMode )
4114 //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4118 if ( *theMeshName && mesh_var->NbFaces() == 0 )
4120 // new mesh empty, remove it
4121 SALOMEDS::Study_var study = SMESH_Gen_i::getStudyServant();
4122 SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
4123 SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::ObjectToSObject( mesh_var );
4124 builder->RemoveObjectWithChildren( meshSO );
4125 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4127 if ( !groupIds ) // nothing changed in the current mesh
4128 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4130 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4132 // result of Offset() is a tuple (mesh, groups)
4133 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4134 else pyDump << mesh_var << ", ";
4135 pyDump << theGroups << " = " << this << ".Offset( "
4136 << theObject << ", "
4138 << theCopyGroups << ", "
4139 << theCopyElements << ", "
4140 << "'" << theMeshName<< "')";
4143 return mesh_var._retn();
4145 SMESH_CATCH( SMESH::throwCorbaException );
4146 return SMESH::SMESH_Mesh::_nil();
4149 //=======================================================================
4150 //function : findCoincidentNodes
4152 //=======================================================================
4154 void SMESH_MeshEditor_i::
4155 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4156 CORBA::Double Tolerance,
4157 SMESH::array_of_long_array_out GroupsOfNodes,
4158 CORBA::Boolean SeparateCornersAndMedium)
4160 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4161 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4163 GroupsOfNodes = new SMESH::array_of_long_array;
4164 GroupsOfNodes->length( aListOfListOfNodes.size() );
4165 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4166 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4168 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4169 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4170 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4171 aGroup.length( aListOfNodes.size() );
4172 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4173 aGroup[ j ] = (*lIt)->GetID();
4177 //=======================================================================
4178 //function : FindCoincidentNodes
4180 //=======================================================================
4182 void SMESH_MeshEditor_i::
4183 FindCoincidentNodes (CORBA::Double Tolerance,
4184 SMESH::array_of_long_array_out GroupsOfNodes,
4185 CORBA::Boolean SeparateCornersAndMedium)
4186 throw (SALOME::SALOME_Exception)
4191 TIDSortedNodeSet nodes; // no input nodes
4192 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4194 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4195 << Tolerance << ", "
4196 << SeparateCornersAndMedium << " )";
4198 SMESH_CATCH( SMESH::throwCorbaException );
4201 //=======================================================================
4202 //function : FindCoincidentNodesOnPart
4204 //=======================================================================
4206 void SMESH_MeshEditor_i::
4207 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4208 CORBA::Double Tolerance,
4209 SMESH::array_of_long_array_out GroupsOfNodes,
4210 CORBA::Boolean SeparateCornersAndMedium)
4211 throw (SALOME::SALOME_Exception)
4216 TIDSortedNodeSet nodes;
4217 prepareIdSource( theObject );
4218 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4220 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4222 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4224 << Tolerance << ", "
4225 << SeparateCornersAndMedium << " )";
4227 SMESH_CATCH( SMESH::throwCorbaException );
4230 //================================================================================
4232 * \brief Finds nodes coincident with Tolerance within Objects excluding nodes within
4233 * ExceptSubMeshOrGroups
4235 //================================================================================
4237 void SMESH_MeshEditor_i::
4238 FindCoincidentNodesOnPartBut(const SMESH::ListOfIDSources& theObjects,
4239 CORBA::Double theTolerance,
4240 SMESH::array_of_long_array_out theGroupsOfNodes,
4241 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4242 CORBA::Boolean theSeparateCornersAndMedium)
4243 throw (SALOME::SALOME_Exception)
4248 TIDSortedNodeSet nodes;
4249 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4251 prepareIdSource( theObjects[i] );
4252 idSourceToNodeSet( theObjects[i], getMeshDS(), nodes );
4254 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4256 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4258 while ( nodeIt->more() )
4259 nodes.erase( cast2Node( nodeIt->next() ));
4261 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4263 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4264 << theObjects <<", "
4265 << theTolerance << ", "
4266 << theExceptSubMeshOrGroups << ", "
4267 << theSeparateCornersAndMedium << " )";
4269 SMESH_CATCH( SMESH::throwCorbaException );
4272 //=======================================================================
4273 //function : MergeNodes
4275 //=======================================================================
4277 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4278 const SMESH::ListOfIDSources& NodesToKeep,
4279 CORBA::Boolean AvoidMakingHoles)
4280 throw (SALOME::SALOME_Exception)
4285 SMESHDS_Mesh* aMesh = getMeshDS();
4287 TPythonDump aTPythonDump;
4288 aTPythonDump << this << ".MergeNodes([";
4290 TIDSortedNodeSet setOfNodesToKeep;
4291 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4293 prepareIdSource( NodesToKeep[i] );
4294 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ))
4295 while ( nodeIt->more() )
4296 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4299 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4300 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4302 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4303 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4304 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4305 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4307 CORBA::Long index = aNodeGroup[ j ];
4308 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4310 if ( setOfNodesToKeep.count( node ))
4311 aListOfNodes.push_front( node );
4313 aListOfNodes.push_back( node );
4316 if ( aListOfNodes.size() < 2 )
4317 aListOfListOfNodes.pop_back();
4319 if ( i > 0 ) aTPythonDump << ", ";
4320 aTPythonDump << aNodeGroup;
4323 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4325 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4327 declareMeshModified( /*isReComputeSafe=*/false );
4329 SMESH_CATCH( SMESH::throwCorbaException );
4332 //=======================================================================
4333 //function : FindEqualElements
4335 //=======================================================================
4337 void SMESH_MeshEditor_i::FindEqualElements(const SMESH::ListOfIDSources& theObjects,
4338 const SMESH::ListOfIDSources& theExceptObjects,
4339 SMESH::array_of_long_array_out theGroupsOfElementsID)
4340 throw (SALOME::SALOME_Exception)
4345 theGroupsOfElementsID = new SMESH::array_of_long_array;
4347 TIDSortedElemSet elems;
4348 bool hasOkObject = false;
4349 bool emptyIfIsMesh= ( theObjects.length() == 1 && theExceptObjects.length() == 0 );
4351 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4353 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( theObjects[i] );
4354 if ( !( !group->_is_nil() && group->GetType() == SMESH::NODE ))
4355 if ( idSourceToSet( theObjects[i], getMeshDS(), elems, SMDSAbs_All, emptyIfIsMesh ))
4361 for ( CORBA::ULong i = 0; i < theExceptObjects.length(); ++i )
4363 if ( SMDS_ElemIteratorPtr elemIt = myMesh_i->GetElements( theExceptObjects[i], SMESH::ALL ))
4364 while ( elemIt->more() )
4365 elems.erase( elemIt->next() );
4368 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4369 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4371 theGroupsOfElementsID->length( aListOfListOfElementsID.size() );
4373 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4374 aListOfListOfElementsID.begin();
4375 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4377 SMESH::long_array& aGroup = (*theGroupsOfElementsID)[ j ];
4378 list<int>& listOfIDs = *arraysIt;
4379 aGroup.length( listOfIDs.size() );
4380 list<int>::iterator idIt = listOfIDs.begin();
4381 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4382 aGroup[ k ] = *idIt;
4385 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4386 << theObjects << ", "
4387 << theExceptObjects << " )";
4390 SMESH_CATCH( SMESH::throwCorbaException );
4393 //=======================================================================
4394 //function : MergeElements
4396 //=======================================================================
4398 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& theGroupsOfElementsID,
4399 const SMESH::ListOfIDSources& theElementsToKeep)
4400 throw (SALOME::SALOME_Exception)
4405 TPythonDump aTPythonDump;
4406 aTPythonDump << this << ".MergeElements( [";
4408 NCollection_Map< int > idsToKeep;
4409 for ( CORBA::ULong i = 0; i < theElementsToKeep.length(); i++ )
4411 if ( CORBA::is_nil( theElementsToKeep[i] ))
4413 SMESH::array_of_ElementType_var elemTypes = theElementsToKeep[i]->GetTypes();
4414 if ( elemTypes->length() == 1 && elemTypes[0] == SMESH::NODE )
4416 SMESH::long_array_var elementsId = theElementsToKeep[i]->GetIDs();
4417 for ( CORBA::ULong j = 0; j < elementsId->length(); ++j )
4418 idsToKeep.Add( elementsId[ j ]);
4421 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4423 for ( CORBA::ULong i = 0; i < theGroupsOfElementsID.length(); i++ )
4425 const SMESH::long_array& anElemsIDGroup = theGroupsOfElementsID[ i ];
4426 aListOfListOfElementsID.push_back( list< int >() );
4427 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4428 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ )
4430 CORBA::Long id = anElemsIDGroup[ j ];
4431 if ( idsToKeep.Contains( id )) aListOfElemsID.push_front( id );
4432 else aListOfElemsID.push_back( id );
4434 if ( aListOfElemsID.size() < 2 )
4435 aListOfListOfElementsID.pop_back();
4436 if ( i > 0 ) aTPythonDump << ", ";
4437 aTPythonDump << anElemsIDGroup;
4440 getEditor().MergeElements(aListOfListOfElementsID);
4442 declareMeshModified( /*isReComputeSafe=*/true );
4444 aTPythonDump << "], " << theElementsToKeep << " )";
4446 SMESH_CATCH( SMESH::throwCorbaException );
4449 //=======================================================================
4450 //function : MergeEqualElements
4452 //=======================================================================
4454 void SMESH_MeshEditor_i::MergeEqualElements()
4455 throw (SALOME::SALOME_Exception)
4460 getEditor().MergeEqualElements();
4462 declareMeshModified( /*isReComputeSafe=*/true );
4464 TPythonDump() << this << ".MergeEqualElements()";
4466 SMESH_CATCH( SMESH::throwCorbaException );
4469 //=============================================================================
4471 * Move the node to a given point
4473 //=============================================================================
4475 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4479 throw (SALOME::SALOME_Exception)
4482 initData(/*deleteSearchers=*/false);
4484 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4488 if ( theNodeSearcher )
4489 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4491 if ( myIsPreviewMode ) // make preview data
4493 // in a preview mesh, make edges linked to a node
4494 TPreviewMesh& tmpMesh = *getPreviewMesh();
4495 TIDSortedElemSet linkedNodes;
4496 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4497 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4498 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4499 for ( ; nIt != linkedNodes.end(); ++nIt )
4501 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4502 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4506 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4507 // fill preview data
4509 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4510 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4512 getMeshDS()->MoveNode(node, x, y, z);
4514 if ( !myIsPreviewMode )
4516 // Update Python script
4517 TPythonDump() << "isDone = " << this << ".MoveNode( "
4518 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4519 declareMeshModified( /*isReComputeSafe=*/false );
4522 SMESH_CATCH( SMESH::throwCorbaException );
4527 //================================================================================
4529 * \brief Return ID of node closest to a given point
4531 //================================================================================
4533 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4536 throw (SALOME::SALOME_Exception)
4539 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4541 if ( !theNodeSearcher ) {
4542 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4545 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4546 return node->GetID();
4548 SMESH_CATCH( SMESH::throwCorbaException );
4552 //================================================================================
4554 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4555 * move the node closest to the point to point's location and return ID of the node
4557 //================================================================================
4559 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4562 CORBA::Long theNodeID)
4563 throw (SALOME::SALOME_Exception)
4566 // We keep theNodeSearcher until any mesh modification:
4567 // 1) initData() deletes theNodeSearcher at any edition,
4568 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4570 initData(/*deleteSearchers=*/false);
4572 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4574 int nodeID = theNodeID;
4575 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4576 if ( !node ) // preview moving node
4578 if ( !theNodeSearcher ) {
4579 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4582 node = theNodeSearcher->FindClosestTo( p );
4585 nodeID = node->GetID();
4586 if ( myIsPreviewMode ) // make preview data
4588 // in a preview mesh, make edges linked to a node
4589 TPreviewMesh tmpMesh = *getPreviewMesh();
4590 TIDSortedElemSet linkedNodes;
4591 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4592 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4593 for ( ; nIt != linkedNodes.end(); ++nIt )
4595 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4596 tmpMesh.Copy( &edge );
4599 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4601 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4602 // fill preview data
4604 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4606 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4610 getMeshDS()->MoveNode(node, x, y, z);
4614 if ( !myIsPreviewMode )
4616 TPythonDump() << "nodeID = " << this
4617 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4618 << ", " << nodeID << " )";
4620 declareMeshModified( /*isReComputeSafe=*/false );
4625 SMESH_CATCH( SMESH::throwCorbaException );
4629 //=======================================================================
4631 * Return elements of given type where the given point is IN or ON.
4633 * 'ALL' type means elements of any type excluding nodes
4635 //=======================================================================
4637 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4640 SMESH::ElementType type)
4641 throw (SALOME::SALOME_Exception)
4644 SMESH::long_array_var res = new SMESH::long_array;
4645 vector< const SMDS_MeshElement* > foundElems;
4647 theSearchersDeleter.Set( myMesh );
4648 if ( !theElementSearcher ) {
4649 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4651 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4652 SMDSAbs_ElementType( type ),
4654 res->length( foundElems.size() );
4655 for ( size_t i = 0; i < foundElems.size(); ++i )
4656 res[i] = foundElems[i]->GetID();
4660 SMESH_CATCH( SMESH::throwCorbaException );
4664 //=======================================================================
4665 //function : FindAmongElementsByPoint
4666 //purpose : Searching among the given elements, return elements of given type
4667 // where the given point is IN or ON.
4668 // 'ALL' type means elements of any type excluding nodes
4669 //=======================================================================
4672 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4676 SMESH::ElementType type)
4677 throw (SALOME::SALOME_Exception)
4680 SMESH::long_array_var res = new SMESH::long_array;
4682 prepareIdSource( elementIDs );
4683 if ( type != SMESH::NODE )
4685 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4686 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4687 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4688 type != types[0] ) // but search of elements of dim > 0
4692 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4693 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4694 if ( mesh_i != myMesh_i )
4696 SMESH::SMESH_MeshEditor_var editor=
4697 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4698 return editor->FindAmongElementsByPoint( elementIDs, x,y,z, type );
4701 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4702 return FindElementsByPoint( x,y,z, type );
4704 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4706 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4707 if ( !theElementSearcher )
4709 // create a searcher from elementIDs
4710 SMDS_ElemIteratorPtr elemIt;
4711 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( elementIDs ))
4713 //prepareIdSource( elementIDs );
4714 elemIt = myMesh_i->GetElements( elementIDs, type );
4718 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4721 vector< const SMDS_MeshElement* > foundElems;
4723 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4724 SMDSAbs_ElementType( type ),
4726 res->length( foundElems.size() );
4727 for ( size_t i = 0; i < foundElems.size(); ++i )
4728 res[i] = foundElems[i]->GetID();
4732 SMESH_CATCH( SMESH::throwCorbaException );
4736 //=======================================================================
4737 //function : ProjectPoint
4738 //purpose : Project a point to a mesh object.
4739 // Return ID of an element of given type where the given point is projected
4740 // and coordinates of the projection point.
4741 // In the case if nothing found, return -1 and []
4742 //=======================================================================
4744 CORBA::Long SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
4747 SMESH::ElementType type,
4748 SMESH::SMESH_IDSource_ptr meshObject,
4749 SMESH::double_array_out projecton)
4750 throw (SALOME::SALOME_Exception)
4752 if ( CORBA::is_nil( meshObject ))
4753 THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
4757 SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
4758 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4759 if ( mesh_i != myMesh_i )
4761 SMESH::SMESH_MeshEditor_var editor=
4762 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4763 return editor->ProjectPoint( x,y,z, type, meshObject, projecton );
4767 theSearchersDeleter.Set( myMesh, getPartIOR( meshObject, type ));
4768 if ( !theElementSearcher )
4770 // create a searcher from meshObject
4772 SMDS_ElemIteratorPtr elemIt;
4773 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
4775 prepareIdSource( meshObject );
4776 elemIt = myMesh_i->GetElements( meshObject, type );
4780 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4783 const SMDS_MeshElement* elem = 0;
4784 gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
4785 SMDSAbs_ElementType( type ),
4788 projecton = new SMESH::double_array();
4789 if ( elem && !elem->IsNull() )
4791 projecton->length( 3 );
4792 projecton[0] = pProj.X();
4793 projecton[1] = pProj.Y();
4794 projecton[2] = pProj.Z();
4795 return elem->GetID();
4798 SMESH_CATCH( SMESH::throwCorbaException );
4802 //=======================================================================
4803 //function : GetPointState
4804 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4805 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4806 //=======================================================================
4808 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4811 throw (SALOME::SALOME_Exception)
4814 theSearchersDeleter.Set( myMesh );
4815 if ( !theElementSearcher ) {
4816 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4818 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4820 SMESH_CATCH( SMESH::throwCorbaException );
4824 //=======================================================================
4825 //function : IsManifold
4826 //purpose : Check if a 2D mesh is manifold
4827 //=======================================================================
4829 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4830 throw (SALOME::SALOME_Exception)
4832 bool isManifold = true;
4835 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4836 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4838 /*closedOnly=*/true,
4840 SMESH_CATCH( SMESH::throwCorbaException );
4845 //=======================================================================
4846 //function : IsCoherentOrientation2D
4847 //purpose : Check if orientation of 2D elements is coherent
4848 //=======================================================================
4850 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4851 throw (SALOME::SALOME_Exception)
4853 bool isGoodOri = true;
4856 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4857 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4859 /*closedOnly=*/true,
4862 SMESH_CATCH( SMESH::throwCorbaException );
4867 //=======================================================================
4868 //function : Get1DBranches
4869 //purpose : Partition given 1D elements into groups of contiguous edges.
4870 // A node where number of meeting edges != 2 is a group end.
4871 // An optional startNode is used to orient groups it belongs to.
4872 //return : a list of edge groups and a list of corresponding node groups.
4873 // If a group is closed, the first and last nodes of the group are same.
4874 //=======================================================================
4876 SMESH::array_of_long_array*
4877 SMESH_MeshEditor_i::Get1DBranches( SMESH::SMESH_IDSource_ptr theEdges,
4878 CORBA::Long theStartNode,
4879 SMESH::array_of_long_array_out theNodeGroups )
4880 throw (SALOME::SALOME_Exception)
4882 if ( CORBA::is_nil( theEdges ))
4883 THROW_SALOME_CORBA_EXCEPTION("Get1DBranches(): NULL group given", SALOME::BAD_PARAM);
4885 SMESH::array_of_long_array_var edgeGroupArray = new SMESH::array_of_long_array;
4886 theNodeGroups = new SMESH::array_of_long_array;
4890 prepareIdSource( theEdges );
4892 SMESH_MeshAlgos::TElemGroupVector edgeBranches;
4893 SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
4894 SMESH_MeshAlgos::Get1DBranches( SMESH_Mesh_i::GetElements( theEdges, SMESH::EDGE ),
4897 getMeshDS()->FindNode( theStartNode ));
4899 edgeGroupArray->length( edgeBranches.size() );
4900 for ( size_t iG = 0; iG < edgeBranches.size(); ++iG )
4902 edgeGroupArray[ iG ].length( edgeBranches[ iG ].size() );
4903 for ( size_t i = 0; i < edgeBranches[ iG ].size(); ++i )
4904 edgeGroupArray[ iG ][ i ] = edgeBranches[ iG ][ i ]->GetID();
4907 theNodeGroups->length( nodeBranches.size() );
4908 for ( size_t iG = 0; iG < nodeBranches.size(); ++iG )
4910 theNodeGroups[ iG ].length( nodeBranches[ iG ].size() );
4911 for ( size_t i = 0; i < nodeBranches[ iG ].size(); ++i )
4912 theNodeGroups[ iG ][ i ] = nodeBranches[ iG ][ i ]->GetID();
4915 SMESH_CATCH( SMESH::throwCorbaException );
4917 return edgeGroupArray._retn();
4920 //=======================================================================
4921 //function : FindSharpEdges
4922 //purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
4923 //=======================================================================
4925 SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
4926 CORBA::Boolean theAddExisting)
4927 throw (SALOME::SALOME_Exception)
4929 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
4934 std::vector< SMESH_MeshAlgos::Edge > edges =
4935 SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
4937 if ( myIsPreviewMode ) // fill a preview mesh with edges
4939 TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
4940 SMDS_Mesh* meshDS = mesh->GetMeshDS();
4941 for ( size_t i = 0; i < edges.size(); ++i )
4943 SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
4944 SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4945 SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
4946 if ( edges[i]._medium )
4948 xyz1.Set( edges[i]._medium );
4949 SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4950 mesh->GetMeshDS()->AddEdge( n1, n2, nm );
4954 mesh->GetMeshDS()->AddEdge( n1, n2 );
4960 resultEdges->length( edges.size() );
4961 for ( size_t i = 0; i < edges.size(); ++i )
4963 resultEdges[ i ].node1 = edges[i]._node1->GetID();
4964 resultEdges[ i ].node2 = edges[i]._node2->GetID();
4965 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
4968 SMESH_CATCH( SMESH::throwCorbaException );
4969 return resultEdges._retn();
4972 //=======================================================================
4973 //function : FindFreeBorders
4974 //purpose : Returns all or only closed FreeBorder's.
4975 //=======================================================================
4977 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4978 throw (SALOME::SALOME_Exception)
4980 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4983 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4984 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4986 resBorders->length( foundFreeBordes.size() );
4987 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
4989 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
4990 SMESH::FreeBorder& bordOut = resBorders[i];
4991 bordOut.nodeIDs.length( bordNodes.size() );
4992 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
4993 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
4996 SMESH_CATCH( SMESH::throwCorbaException );
4998 return resBorders._retn();
5001 //=======================================================================
5002 //function : FillHole
5003 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
5004 //=======================================================================
5006 SMESH::SMESH_Group_ptr
5007 SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole,
5008 const char* theGroupName)
5009 throw (SALOME::SALOME_Exception)
5013 if ( theHole.nodeIDs.length() < 4 )
5014 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
5015 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
5016 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
5017 "First and last nodes must be same", SALOME::BAD_PARAM);
5019 SMESH_MeshAlgos::TFreeBorder bordNodes;
5020 bordNodes.resize( theHole.nodeIDs.length() );
5021 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
5023 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
5024 if ( !bordNodes[ iN ] )
5025 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
5026 << " does not exist", SALOME::BAD_PARAM);
5031 // prepare a preview mesh
5032 MeshEditor_I::TPreviewMesh* previewMesh = 0;
5033 SMDS_Mesh* meshDS = getMeshDS();
5034 if ( myIsPreviewMode )
5036 // copy faces sharing nodes of theHole
5037 TIDSortedElemSet holeFaces;
5038 previewMesh = getPreviewMesh( SMDSAbs_Face );
5039 for ( size_t i = 0; i < bordNodes.size(); ++i )
5041 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
5042 while ( fIt->more() )
5044 const SMDS_MeshElement* face = fIt->next();
5045 if ( holeFaces.insert( face ).second )
5046 previewMesh->Copy( face );
5048 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
5049 ASSERT( bordNodes[i] );
5051 meshDS = previewMesh->GetMeshDS();
5055 std::vector<const SMDS_MeshElement*> newFaces;
5056 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
5058 if ( myIsPreviewMode )
5061 previewMesh->Clear();
5062 for ( size_t i = 0; i < newFaces.size(); ++i )
5063 previewMesh->Copy( newFaces[i] );
5067 // return new faces via a group
5068 SMESH::SMESH_Group_var group;
5069 if ( theGroupName && theGroupName[0] && !newFaces.empty() )
5071 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5072 for ( CORBA::ULong i = 0; i < groups->length(); ++i )
5074 SMESH::SMESH_GroupBase_var g = groups[ i ];
5075 if ( g->GetType() != SMESH::FACE ) continue;
5076 SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g );
5077 if ( standalone->_is_nil() ) continue;
5078 CORBA::String_var name = g->GetName();
5079 if ( strcmp( theGroupName, name.in() ) == 0 )
5085 if ( group->_is_nil() )
5086 group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName );
5088 if ( !group->_is_nil() )
5090 SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group );
5091 SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() );
5092 for ( size_t i = 0; i < newFaces.size(); ++i )
5093 grpDS->Add( newFaces[ i ]);
5098 getEditor().ClearLastCreated();
5099 SMESH_SequenceOfElemPtr& aSeq =
5100 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
5101 aSeq.swap( newFaces );
5104 if ( group->_is_nil() ) pyDump << "_group = ";
5105 else pyDump << group << " = ";
5106 pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
5108 return group._retn();
5111 SMESH_CATCH( SMESH::throwCorbaException );
5113 return SMESH::SMESH_Group::_nil();
5116 //=======================================================================
5117 //function : convError
5119 //=======================================================================
5121 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5123 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5127 RETCASE( SEW_BORDER1_NOT_FOUND );
5128 RETCASE( SEW_BORDER2_NOT_FOUND );
5129 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5130 RETCASE( SEW_BAD_SIDE_NODES );
5131 RETCASE( SEW_VOLUMES_TO_SPLIT );
5132 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5133 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5134 RETCASE( SEW_BAD_SIDE1_NODES );
5135 RETCASE( SEW_BAD_SIDE2_NODES );
5136 RETCASE( SEW_INTERNAL_ERROR );
5138 return SMESH::SMESH_MeshEditor::SEW_OK;
5141 //=======================================================================
5143 * Returns groups of FreeBorder's coincident within the given tolerance.
5144 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
5145 * to free borders being compared is used.
5147 //=======================================================================
5149 SMESH::CoincidentFreeBorders*
5150 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
5152 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
5156 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
5157 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
5159 // copy free borders
5160 aCFB->borders.length( cfb._borders.size() );
5161 for ( size_t i = 0; i < cfb._borders.size(); ++i )
5163 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
5164 SMESH::FreeBorder& aBRD = aCFB->borders[i];
5165 aBRD.nodeIDs.length( nodes.size() );
5166 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5167 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
5170 // copy coincident parts
5171 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
5172 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
5174 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
5175 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
5176 aGRP.length( grp.size() );
5177 for ( size_t iP = 0; iP < grp.size(); ++iP )
5179 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
5180 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5181 aPART.border = part._border;
5182 aPART.node1 = part._node1;
5183 aPART.node2 = part._node2;
5184 aPART.nodeLast = part._nodeLast;
5187 SMESH_CATCH( SMESH::doNothing );
5189 TPythonDump() << "CoincidentFreeBorders = "
5190 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
5192 return aCFB._retn();
5195 //=======================================================================
5197 * Sew FreeBorder's of each group
5199 //=======================================================================
5201 CORBA::Short SMESH_MeshEditor_i::
5202 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
5203 CORBA::Boolean createPolygons,
5204 CORBA::Boolean createPolyhedra)
5205 throw (SALOME::SALOME_Exception)
5207 CORBA::Short nbSewed = 0;
5209 SMESH_MeshAlgos::TFreeBorderVec groups;
5210 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
5212 // check the input and collect nodes
5213 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
5215 borderNodes.clear();
5216 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
5217 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
5219 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5220 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
5221 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
5223 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
5225 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
5226 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
5227 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
5228 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
5229 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
5230 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5232 // do not keep these nodes for further sewing as nodes can be removed by the sewing
5233 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
5234 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
5235 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
5237 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
5239 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
5241 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5243 borderNodes.push_back( n1 );
5244 borderNodes.push_back( n2 );
5245 borderNodes.push_back( n3 );
5247 groups.push_back( borderNodes );
5250 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
5251 // to get nodes that replace other nodes during merge we create 0D elements
5252 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
5255 vector< const SMDS_MeshElement* > tmp0Delems;
5256 for ( size_t i = 0; i < groups.size(); ++i )
5258 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5259 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5261 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
5263 tmp0Delems.push_back( it0D->next() );
5265 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
5269 // cout << endl << "INIT" << endl;
5270 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5272 // cout << i << " ";
5273 // if ( i % 3 == 0 ) cout << "^ ";
5274 // tmp0Delems[i]->GetNode(0)->Print( cout );
5279 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
5281 for ( size_t i = 0; i < groups.size(); ++i )
5283 bool isBordToBord = true;
5284 bool groupSewed = false;
5285 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5286 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
5288 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
5289 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
5290 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
5292 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
5293 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
5294 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
5296 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
5299 // TIDSortedElemSet emptySet, avoidSet;
5300 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
5302 // cout << "WRONG 2nd 1" << endl;
5303 // n0->Print( cout );
5304 // n1->Print( cout );
5306 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
5308 // cout << "WRONG 2nd 2" << endl;
5309 // n3->Print( cout );
5310 // n4->Print( cout );
5313 if ( !isBordToBord )
5315 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5316 n2 = 0; // and n2 is not used
5318 // 1st border moves to 2nd
5319 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5321 /*2ndIsFreeBorder=*/ isBordToBord,
5322 createPolygons, createPolyhedra);
5323 groupSewed = ( res == ok );
5325 isBordToBord = false;
5326 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5327 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5329 // cout << t << " ";
5330 // if ( t % 3 == 0 ) cout << "^ ";
5331 // tmp0Delems[t]->GetNode(0)->Print( cout );
5334 i0D += nodes.size();
5335 nbSewed += groupSewed;
5338 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5339 << freeBorders << ", "
5340 << createPolygons << ", "
5341 << createPolyhedra << " )";
5343 SMESH_CATCH( SMESH::doNothing );
5345 declareMeshModified( /*isReComputeSafe=*/false );
5347 // remove tmp 0D elements
5349 set< const SMDS_MeshElement* > removed0D;
5350 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5352 if ( removed0D.insert( tmp0Delems[i] ).second )
5353 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5355 SMESH_CATCH( SMESH::throwCorbaException );
5360 //=======================================================================
5361 //function : SewFreeBorders
5363 //=======================================================================
5365 SMESH::SMESH_MeshEditor::Sew_Error
5366 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5367 CORBA::Long SecondNodeID1,
5368 CORBA::Long LastNodeID1,
5369 CORBA::Long FirstNodeID2,
5370 CORBA::Long SecondNodeID2,
5371 CORBA::Long LastNodeID2,
5372 CORBA::Boolean CreatePolygons,
5373 CORBA::Boolean CreatePolyedrs)
5374 throw (SALOME::SALOME_Exception)
5379 SMESHDS_Mesh* aMesh = getMeshDS();
5381 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5382 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5383 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5384 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5385 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5386 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5388 if (!aBorderFirstNode ||
5389 !aBorderSecondNode||
5391 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5392 if (!aSide2FirstNode ||
5393 !aSide2SecondNode ||
5395 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5397 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5398 << FirstNodeID1 << ", "
5399 << SecondNodeID1 << ", "
5400 << LastNodeID1 << ", "
5401 << FirstNodeID2 << ", "
5402 << SecondNodeID2 << ", "
5403 << LastNodeID2 << ", "
5404 << CreatePolygons<< ", "
5405 << CreatePolyedrs<< " )";
5407 SMESH::SMESH_MeshEditor::Sew_Error error =
5408 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5419 declareMeshModified( /*isReComputeSafe=*/false );
5422 SMESH_CATCH( SMESH::throwCorbaException );
5423 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5427 //=======================================================================
5428 //function : SewConformFreeBorders
5430 //=======================================================================
5432 SMESH::SMESH_MeshEditor::Sew_Error
5433 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5434 CORBA::Long SecondNodeID1,
5435 CORBA::Long LastNodeID1,
5436 CORBA::Long FirstNodeID2,
5437 CORBA::Long SecondNodeID2)
5438 throw (SALOME::SALOME_Exception)
5443 SMESHDS_Mesh* aMesh = getMeshDS();
5445 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5446 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5447 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5448 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5449 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5450 const SMDS_MeshNode* aSide2ThirdNode = 0;
5452 if (!aBorderFirstNode ||
5453 !aBorderSecondNode||
5455 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5456 if (!aSide2FirstNode ||
5458 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5460 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5461 << FirstNodeID1 << ", "
5462 << SecondNodeID1 << ", "
5463 << LastNodeID1 << ", "
5464 << FirstNodeID2 << ", "
5465 << SecondNodeID2 << " )";
5467 SMESH::SMESH_MeshEditor::Sew_Error error =
5468 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5477 declareMeshModified( /*isReComputeSafe=*/false );
5480 SMESH_CATCH( SMESH::throwCorbaException );
5481 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5485 //=======================================================================
5486 //function : SewBorderToSide
5488 //=======================================================================
5490 SMESH::SMESH_MeshEditor::Sew_Error
5491 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5492 CORBA::Long SecondNodeIDOnFreeBorder,
5493 CORBA::Long LastNodeIDOnFreeBorder,
5494 CORBA::Long FirstNodeIDOnSide,
5495 CORBA::Long LastNodeIDOnSide,
5496 CORBA::Boolean CreatePolygons,
5497 CORBA::Boolean CreatePolyedrs)
5498 throw (SALOME::SALOME_Exception)
5503 SMESHDS_Mesh* aMesh = getMeshDS();
5505 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5506 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5507 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5508 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5509 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5510 const SMDS_MeshNode* aSide2ThirdNode = 0;
5512 if (!aBorderFirstNode ||
5513 !aBorderSecondNode||
5515 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5516 if (!aSide2FirstNode ||
5518 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5520 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5521 << FirstNodeIDOnFreeBorder << ", "
5522 << SecondNodeIDOnFreeBorder << ", "
5523 << LastNodeIDOnFreeBorder << ", "
5524 << FirstNodeIDOnSide << ", "
5525 << LastNodeIDOnSide << ", "
5526 << CreatePolygons << ", "
5527 << CreatePolyedrs << ") ";
5529 SMESH::SMESH_MeshEditor::Sew_Error error =
5530 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5540 declareMeshModified( /*isReComputeSafe=*/false );
5543 SMESH_CATCH( SMESH::throwCorbaException );
5544 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5548 //=======================================================================
5549 //function : SewSideElements
5551 //=======================================================================
5553 SMESH::SMESH_MeshEditor::Sew_Error
5554 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5555 const SMESH::long_array& IDsOfSide2Elements,
5556 CORBA::Long NodeID1OfSide1ToMerge,
5557 CORBA::Long NodeID1OfSide2ToMerge,
5558 CORBA::Long NodeID2OfSide1ToMerge,
5559 CORBA::Long NodeID2OfSide2ToMerge)
5560 throw (SALOME::SALOME_Exception)
5565 SMESHDS_Mesh* aMesh = getMeshDS();
5567 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5568 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5569 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5570 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5572 if (!aFirstNode1ToMerge ||
5573 !aFirstNode2ToMerge )
5574 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5575 if (!aSecondNode1ToMerge||
5576 !aSecondNode2ToMerge)
5577 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5579 TIDSortedElemSet aSide1Elems, aSide2Elems;
5580 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5581 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5583 TPythonDump() << "error = " << this << ".SewSideElements( "
5584 << IDsOfSide1Elements << ", "
5585 << IDsOfSide2Elements << ", "
5586 << NodeID1OfSide1ToMerge << ", "
5587 << NodeID1OfSide2ToMerge << ", "
5588 << NodeID2OfSide1ToMerge << ", "
5589 << NodeID2OfSide2ToMerge << ")";
5591 SMESH::SMESH_MeshEditor::Sew_Error error =
5592 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5595 aSecondNode1ToMerge,
5596 aSecondNode2ToMerge));
5598 declareMeshModified( /*isReComputeSafe=*/false );
5601 SMESH_CATCH( SMESH::throwCorbaException );
5602 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5605 //================================================================================
5607 * \brief Set new nodes for given element
5608 * \param ide - element id
5609 * \param newIDs - new node ids
5610 * \retval CORBA::Boolean - true if result is OK
5612 //================================================================================
5614 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5615 const SMESH::long_array& newIDs)
5616 throw (SALOME::SALOME_Exception)
5621 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5622 if ( !elem ) return false;
5624 int nbn = newIDs.length();
5625 vector<const SMDS_MeshNode*> aNodes(nbn);
5626 for ( int i = 0; i < nbn; i++ ) {
5627 const SMDS_MeshNode* aNode = getMeshDS()->FindNode( newIDs[ i ]);
5630 aNodes[ i ] = aNode;
5632 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5633 << ide << ", " << newIDs << " )";
5635 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], aNodes.size() );
5637 declareMeshModified( /*isReComputeSafe=*/ !res );
5641 SMESH_CATCH( SMESH::throwCorbaException );
5645 //=======================================================================
5647 * \brief Makes a part of the mesh quadratic or bi-quadratic
5649 //=======================================================================
5651 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5652 CORBA::Boolean theToBiQuad,
5653 SMESH::SMESH_IDSource_ptr theObject)
5654 throw (SALOME::SALOME_Exception)
5659 TIDSortedElemSet elems;
5661 if ( !( elemsOK = CORBA::is_nil( theObject )))
5663 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5664 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5668 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5669 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5671 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5672 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5674 declareMeshModified( /*isReComputeSafe=*/false );
5677 SMESH_CATCH( SMESH::throwCorbaException );
5680 //=======================================================================
5681 //function : ConvertFromQuadratic
5683 //=======================================================================
5685 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5686 throw (SALOME::SALOME_Exception)
5691 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5692 TPythonDump() << this << ".ConvertFromQuadratic()";
5693 declareMeshModified( /*isReComputeSafe=*/!isDone );
5696 SMESH_CATCH( SMESH::throwCorbaException );
5700 //=======================================================================
5701 //function : ConvertToQuadratic
5703 //=======================================================================
5705 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5706 throw (SALOME::SALOME_Exception)
5708 convertToQuadratic( theForce3d, false );
5709 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5712 //================================================================================
5714 * \brief Makes a part of the mesh quadratic
5716 //================================================================================
5718 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5719 SMESH::SMESH_IDSource_ptr theObject)
5720 throw (SALOME::SALOME_Exception)
5722 convertToQuadratic( theForce3d, false, theObject );
5723 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5726 //================================================================================
5728 * \brief Makes a part of the mesh bi-quadratic
5730 //================================================================================
5732 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5733 SMESH::SMESH_IDSource_ptr theObject)
5734 throw (SALOME::SALOME_Exception)
5736 convertToQuadratic( theForce3d, true, theObject );
5737 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5740 //================================================================================
5742 * \brief Makes a part of the mesh linear
5744 //================================================================================
5746 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5747 throw (SALOME::SALOME_Exception)
5754 TIDSortedElemSet elems;
5755 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5757 if ( elems.empty() )
5759 ConvertFromQuadratic();
5761 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5763 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5767 getEditor().ConvertFromQuadratic(elems);
5770 declareMeshModified( /*isReComputeSafe=*/false );
5772 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5774 SMESH_CATCH( SMESH::throwCorbaException );
5777 //=======================================================================
5778 //function : makeMesh
5779 //purpose : create a named imported mesh
5780 //=======================================================================
5782 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5784 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5785 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5786 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5787 gen->SetName( meshSO, theMeshName, "Mesh" );
5788 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5790 return mesh._retn();
5793 //=======================================================================
5794 //function : dumpGroupsList
5796 //=======================================================================
5798 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5799 const SMESH::ListOfGroups * theGroupList)
5801 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5802 if ( isDumpGroupList )
5803 theDumpPython << theGroupList << " = ";
5806 //================================================================================
5808 \brief Generates the unique group name.
5809 \param thePrefix name prefix
5812 //================================================================================
5814 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5816 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5817 set<std::string> groupNames;
5819 // Get existing group names
5820 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5821 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5822 if (CORBA::is_nil(aGroup))
5825 CORBA::String_var name = aGroup->GetName();
5826 groupNames.insert( name.in() );
5830 std::string name = thePrefix;
5833 while (!groupNames.insert(name).second)
5834 name = SMESH_Comment( thePrefix ) << "_" << index++;
5839 //================================================================================
5841 * \brief Prepare SMESH_IDSource for work
5843 //================================================================================
5845 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5847 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5849 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5850 filter->SetMesh( mesh );
5853 //================================================================================
5855 * \brief Retrieve elements of given type from SMESH_IDSource
5857 //================================================================================
5859 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5860 const SMESHDS_Mesh* theMeshDS,
5861 TIDSortedElemSet& theElemSet,
5862 const SMDSAbs_ElementType theType,
5863 const bool emptyIfIsMesh,
5864 IDSource_Error* error)
5867 if ( error ) *error = IDSource_OK;
5869 if ( CORBA::is_nil( theIDSource ))
5871 if ( error ) *error = IDSource_INVALID;
5874 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5876 if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
5877 *error = IDSource_EMPTY;
5880 if ( getMeshDS() == theMeshDS ) // check if theIDSource belongs to myMesh
5882 SMESH::SMESH_Mesh_var mesh = theIDSource->GetMesh();
5883 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5884 if ( mesh_i && mesh_i != myMesh_i )
5887 *error = IDSource_INVALID;
5891 prepareIdSource( theIDSource );
5892 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5893 if ( anIDs->length() == 0 )
5895 if ( error ) *error = IDSource_EMPTY;
5898 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5899 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5901 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5903 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5907 if ( error ) *error = IDSource_INVALID;
5913 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5914 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5916 if ( error ) *error = IDSource_INVALID;
5923 //================================================================================
5925 * \brief Duplicates given elements, i.e. creates new elements based on the
5926 * same nodes as the given ones.
5927 * \param theElements - container of elements to duplicate.
5928 * \param theGroupName - a name of group to contain the generated elements.
5929 * If a group with such a name already exists, the new elements
5930 * are added to the existing group, else a new group is created.
5931 * If \a theGroupName is empty, new elements are not added
5933 * \return a group where the new elements are added. NULL if theGroupName == "".
5936 //================================================================================
5938 SMESH::SMESH_Group_ptr
5939 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5940 const char* theGroupName)
5941 throw (SALOME::SALOME_Exception)
5943 SMESH::SMESH_Group_var newGroup;
5950 TIDSortedElemSet elems;
5951 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5953 getEditor().DoubleElements( elems );
5955 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5958 SMESH::ElementType type =
5959 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5960 // find existing group
5961 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5962 for ( size_t i = 0; i < groups->length(); ++i )
5963 if ( groups[i]->GetType() == type )
5965 CORBA::String_var name = groups[i]->GetName();
5966 if ( strcmp( name, theGroupName ) == 0 ) {
5967 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5971 // create a new group
5972 if ( newGroup->_is_nil() )
5973 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5975 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5977 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5978 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5979 for ( size_t i = 0; i < aSeq.size(); i++ )
5980 groupDS->SMDSGroup().Add( aSeq[i] );
5985 if ( !newGroup->_is_nil() )
5986 pyDump << newGroup << " = ";
5987 pyDump << this << ".DoubleElements( "
5988 << theElements << ", " << "'" << theGroupName <<"')";
5990 SMESH_CATCH( SMESH::throwCorbaException );
5992 return newGroup._retn();
5995 //================================================================================
5997 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5998 \param theNodes - identifiers of nodes to be doubled
5999 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
6000 nodes. If list of element identifiers is empty then nodes are doubled but
6001 they not assigned to elements
6002 \return TRUE if operation has been completed successfully, FALSE otherwise
6003 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
6005 //================================================================================
6007 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
6008 const SMESH::long_array& theModifiedElems )
6009 throw (SALOME::SALOME_Exception)
6014 list< int > aListOfNodes;
6016 for ( i = 0, n = theNodes.length(); i < n; i++ )
6017 aListOfNodes.push_back( theNodes[ i ] );
6019 list< int > aListOfElems;
6020 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6021 aListOfElems.push_back( theModifiedElems[ i ] );
6023 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
6025 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6027 // Update Python script
6028 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
6032 SMESH_CATCH( SMESH::throwCorbaException );
6036 //================================================================================
6038 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6039 This method provided for convenience works as DoubleNodes() described above.
6040 \param theNodeId - identifier of node to be doubled.
6041 \param theModifiedElems - identifiers of elements to be updated.
6042 \return TRUE if operation has been completed successfully, FALSE otherwise
6043 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
6045 //================================================================================
6047 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
6048 const SMESH::long_array& theModifiedElems )
6049 throw (SALOME::SALOME_Exception)
6052 SMESH::long_array_var aNodes = new SMESH::long_array;
6053 aNodes->length( 1 );
6054 aNodes[ 0 ] = theNodeId;
6056 TPythonDump pyDump; // suppress dump by the next line
6058 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
6060 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
6064 SMESH_CATCH( SMESH::throwCorbaException );
6068 //================================================================================
6070 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6071 This method provided for convenience works as DoubleNodes() described above.
6072 \param theNodes - group of nodes to be doubled.
6073 \param theModifiedElems - group of elements to be updated.
6074 \return TRUE if operation has been completed successfully, FALSE otherwise
6075 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
6077 //================================================================================
6079 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
6080 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6081 throw (SALOME::SALOME_Exception)
6084 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6087 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6088 SMESH::long_array_var aModifiedElems;
6089 if ( !CORBA::is_nil( theModifiedElems ) )
6090 aModifiedElems = theModifiedElems->GetListOfID();
6092 aModifiedElems = new SMESH::long_array;
6094 TPythonDump pyDump; // suppress dump by the next line
6096 bool done = DoubleNodes( aNodes, aModifiedElems );
6098 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6102 SMESH_CATCH( SMESH::throwCorbaException );
6106 //================================================================================
6108 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6109 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6110 * \param theNodes - group of nodes to be doubled.
6111 * \param theModifiedElems - group of elements to be updated.
6112 * \return a new group with newly created nodes
6113 * \sa DoubleNodeGroup()
6115 //================================================================================
6117 SMESH::SMESH_Group_ptr
6118 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6119 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6120 throw (SALOME::SALOME_Exception)
6123 SMESH::SMESH_Group_var aNewGroup;
6125 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6126 return aNewGroup._retn();
6129 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6130 SMESH::long_array_var aModifiedElems;
6131 if ( !CORBA::is_nil( theModifiedElems ) )
6132 aModifiedElems = theModifiedElems->GetListOfID();
6134 aModifiedElems = new SMESH::long_array;
6135 aModifiedElems->length( 0 );
6138 TPythonDump pyDump; // suppress dump by the next line
6140 bool aResult = DoubleNodes( aNodes, aModifiedElems );
6143 // Create group with newly created nodes
6144 SMESH::long_array_var anIds = GetLastCreatedNodes();
6145 if (anIds->length() > 0) {
6146 std::string anUnindexedName (theNodes->GetName());
6147 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6148 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6149 aNewGroup->Add(anIds);
6150 pyDump << aNewGroup << " = ";
6154 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6155 << theModifiedElems << " )";
6157 return aNewGroup._retn();
6159 SMESH_CATCH( SMESH::throwCorbaException );
6163 //================================================================================
6165 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6166 This method provided for convenience works as DoubleNodes() described above.
6167 \param theNodes - list of groups of nodes to be doubled
6168 \param theModifiedElems - list of groups of elements to be updated.
6169 \return TRUE if operation has been completed successfully, FALSE otherwise
6170 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6172 //================================================================================
6174 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6175 const SMESH::ListOfGroups& theModifiedElems )
6176 throw (SALOME::SALOME_Exception)
6181 std::list< int > aNodes;
6183 for ( i = 0, n = theNodes.length(); i < n; i++ )
6185 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6186 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6188 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6189 for ( j = 0, m = aCurr->length(); j < m; j++ )
6190 aNodes.push_back( aCurr[ j ] );
6194 std::list< int > anElems;
6195 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6197 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ 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 anElems.push_back( aCurr[ j ] );
6206 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6208 declareMeshModified( /*isReComputeSafe=*/false );
6210 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6214 SMESH_CATCH( SMESH::throwCorbaException );
6218 //================================================================================
6220 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6221 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6222 * \param theNodes - group of nodes to be doubled.
6223 * \param theModifiedElems - group of elements to be updated.
6224 * \return a new group with newly created nodes
6225 * \sa DoubleNodeGroups()
6227 //================================================================================
6229 SMESH::SMESH_Group_ptr
6230 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6231 const SMESH::ListOfGroups& theModifiedElems )
6232 throw (SALOME::SALOME_Exception)
6234 SMESH::SMESH_Group_var aNewGroup;
6236 TPythonDump pyDump; // suppress dump by the next line
6238 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6242 // Create group with newly created nodes
6243 SMESH::long_array_var anIds = GetLastCreatedNodes();
6244 if (anIds->length() > 0) {
6245 std::string anUnindexedName (theNodes[0]->GetName());
6246 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6247 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6248 aNewGroup->Add(anIds);
6249 pyDump << aNewGroup << " = ";
6253 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6254 << theModifiedElems << " )";
6256 return aNewGroup._retn();
6260 //================================================================================
6262 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6263 \param theElems - the list of elements (edges or faces) to be replicated
6264 The nodes for duplication could be found from these elements
6265 \param theNodesNot - list of nodes to NOT replicate
6266 \param theAffectedElems - the list of elements (cells and edges) to which the
6267 replicated nodes should be associated to.
6268 \return TRUE if operation has been completed successfully, FALSE otherwise
6269 \sa DoubleNodeGroup(), DoubleNodeGroups()
6271 //================================================================================
6273 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6274 const SMESH::long_array& theNodesNot,
6275 const SMESH::long_array& theAffectedElems )
6276 throw (SALOME::SALOME_Exception)
6281 SMESHDS_Mesh* aMeshDS = getMeshDS();
6282 TIDSortedElemSet anElems, aNodes, anAffected;
6283 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6284 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6285 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6287 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6289 // Update Python script
6290 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6291 << theNodesNot << ", " << theAffectedElems << " )";
6293 declareMeshModified( /*isReComputeSafe=*/false );
6296 SMESH_CATCH( SMESH::throwCorbaException );
6300 //================================================================================
6302 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6303 \param theElems - the list of elements (edges or faces) to be replicated
6304 The nodes for duplication could be found from these elements
6305 \param theNodesNot - list of nodes to NOT replicate
6306 \param theShape - shape to detect affected elements (element which geometric center
6307 located on or inside shape).
6308 The replicated nodes should be associated to affected elements.
6309 \return TRUE if operation has been completed successfully, FALSE otherwise
6310 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6312 //================================================================================
6314 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6315 const SMESH::long_array& theNodesNot,
6316 GEOM::GEOM_Object_ptr theShape )
6317 throw (SALOME::SALOME_Exception)
6323 SMESHDS_Mesh* aMeshDS = getMeshDS();
6324 TIDSortedElemSet anElems, aNodes;
6325 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6326 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6328 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6329 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6331 // Update Python script
6332 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6333 << theNodesNot << ", " << theShape << " )";
6335 declareMeshModified( /*isReComputeSafe=*/false );
6338 SMESH_CATCH( SMESH::throwCorbaException );
6342 //================================================================================
6344 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6345 \param theElems - group of of elements (edges or faces) to be replicated
6346 \param theNodesNot - group of nodes not to replicated
6347 \param theAffectedElems - group of elements to which the replicated nodes
6348 should be associated to.
6349 \return TRUE if operation has been completed successfully, FALSE otherwise
6350 \sa DoubleNodes(), DoubleNodeGroups()
6352 //================================================================================
6355 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6356 SMESH::SMESH_GroupBase_ptr theNodesNot,
6357 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6358 throw (SALOME::SALOME_Exception)
6361 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6367 SMESHDS_Mesh* aMeshDS = getMeshDS();
6368 TIDSortedElemSet anElems, aNodes, anAffected;
6369 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6370 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6371 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6373 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6375 // Update Python script
6376 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6377 << theNodesNot << ", " << theAffectedElems << " )";
6379 declareMeshModified( /*isReComputeSafe=*/false );
6382 SMESH_CATCH( SMESH::throwCorbaException );
6386 //================================================================================
6388 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6389 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6390 * \param theElems - group of of elements (edges or faces) to be replicated
6391 * \param theNodesNot - group of nodes not to replicated
6392 * \param theAffectedElems - group of elements to which the replicated nodes
6393 * should be associated to.
6394 * \return a new group with newly created elements
6395 * \sa DoubleNodeElemGroup()
6397 //================================================================================
6399 SMESH::SMESH_Group_ptr
6400 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6401 SMESH::SMESH_GroupBase_ptr theNodesNot,
6402 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6403 throw (SALOME::SALOME_Exception)
6406 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6410 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6411 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6413 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6415 << theNodesNot << ", "
6416 << theAffectedElems << " )";
6418 return elemGroup._retn();
6421 //================================================================================
6423 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6424 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6425 * \param theElems - group of of elements (edges or faces) to be replicated
6426 * \param theNodesNot - group of nodes not to replicated
6427 * \param theAffectedElems - group of elements to which the replicated nodes
6428 * should be associated to.
6429 * \return a new group with newly created elements
6430 * \sa DoubleNodeElemGroup()
6432 //================================================================================
6434 SMESH::ListOfGroups*
6435 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6436 SMESH::SMESH_GroupBase_ptr theNodesNot,
6437 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6438 CORBA::Boolean theElemGroupNeeded,
6439 CORBA::Boolean theNodeGroupNeeded)
6440 throw (SALOME::SALOME_Exception)
6443 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6444 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6445 aTwoGroups->length( 2 );
6447 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6448 return aTwoGroups._retn();
6453 SMESHDS_Mesh* aMeshDS = getMeshDS();
6454 TIDSortedElemSet anElems, aNodes, anAffected;
6455 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6456 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6457 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6460 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6462 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6468 // Create group with newly created elements
6469 CORBA::String_var elemGroupName = theElems->GetName();
6470 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6471 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6473 SMESH::long_array_var anIds = GetLastCreatedElems();
6474 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6475 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6476 aNewElemGroup->Add(anIds);
6478 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6480 SMESH::long_array_var anIds = GetLastCreatedNodes();
6481 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6482 aNewNodeGroup->Add(anIds);
6486 // Update Python script
6489 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6490 else pyDump << aNewElemGroup << ", ";
6491 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6492 else pyDump << aNewNodeGroup << " ] = ";
6494 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6495 << theNodesNot << ", "
6496 << theAffectedElems << ", "
6497 << theElemGroupNeeded << ", "
6498 << theNodeGroupNeeded <<" )";
6500 aTwoGroups[0] = aNewElemGroup._retn();
6501 aTwoGroups[1] = aNewNodeGroup._retn();
6502 return aTwoGroups._retn();
6504 SMESH_CATCH( SMESH::throwCorbaException );
6508 //================================================================================
6510 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6511 \param theElems - group of of elements (edges or faces) to be replicated
6512 \param theNodesNot - group of nodes not to replicated
6513 \param theShape - shape to detect affected elements (element which geometric center
6514 located on or inside shape).
6515 The replicated nodes should be associated to affected elements.
6516 \return TRUE if operation has been completed successfully, FALSE otherwise
6517 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6519 //================================================================================
6522 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6523 SMESH::SMESH_GroupBase_ptr theNodesNot,
6524 GEOM::GEOM_Object_ptr theShape )
6525 throw (SALOME::SALOME_Exception)
6528 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6534 SMESHDS_Mesh* aMeshDS = getMeshDS();
6535 TIDSortedElemSet anElems, aNodes, anAffected;
6536 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6537 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6539 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6540 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6543 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6545 // Update Python script
6546 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6547 << theNodesNot << ", " << theShape << " )";
6550 SMESH_CATCH( SMESH::throwCorbaException );
6554 //================================================================================
6556 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6557 * \param [in] theGrpList - groups
6558 * \param [in] theMeshDS - mesh
6559 * \param [out] theElemSet - set of elements
6560 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6562 //================================================================================
6564 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6565 SMESHDS_Mesh* theMeshDS,
6566 TIDSortedElemSet& theElemSet,
6567 const bool theIsNodeGrp)
6569 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6571 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6572 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6573 : aGrp->GetType() != SMESH::NODE ) )
6575 SMESH::long_array_var anIDs = aGrp->GetIDs();
6576 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6581 //================================================================================
6583 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6584 This method provided for convenience works as DoubleNodes() described above.
6585 \param theElems - list of groups of elements (edges or faces) to be replicated
6586 \param theNodesNot - list of groups of nodes not to replicated
6587 \param theAffectedElems - group of elements to which the replicated nodes
6588 should be associated to.
6589 \return TRUE if operation has been completed successfully, FALSE otherwise
6590 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6592 //================================================================================
6595 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6596 const SMESH::ListOfGroups& theNodesNot,
6597 const SMESH::ListOfGroups& theAffectedElems)
6598 throw (SALOME::SALOME_Exception)
6604 SMESHDS_Mesh* aMeshDS = getMeshDS();
6605 TIDSortedElemSet anElems, aNodes, anAffected;
6606 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6607 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6608 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6610 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6612 // Update Python script
6613 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6614 << &theNodesNot << ", " << &theAffectedElems << " )";
6616 declareMeshModified( /*isReComputeSafe=*/false );
6619 SMESH_CATCH( SMESH::throwCorbaException );
6623 //================================================================================
6625 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6626 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6627 \param theElems - list of groups of elements (edges or faces) to be replicated
6628 \param theNodesNot - list of groups of nodes not to replicated
6629 \param theAffectedElems - group of elements to which the replicated nodes
6630 should be associated to.
6631 * \return a new group with newly created elements
6632 * \sa DoubleNodeElemGroups()
6634 //================================================================================
6636 SMESH::SMESH_Group_ptr
6637 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6638 const SMESH::ListOfGroups& theNodesNot,
6639 const SMESH::ListOfGroups& theAffectedElems)
6640 throw (SALOME::SALOME_Exception)
6643 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6647 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6648 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6650 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6652 << theNodesNot << ", "
6653 << theAffectedElems << " )";
6655 return elemGroup._retn();
6658 //================================================================================
6660 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6661 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6662 \param theElems - list of groups of elements (edges or faces) to be replicated
6663 \param theNodesNot - list of groups of nodes not to replicated
6664 \param theAffectedElems - group of elements to which the replicated nodes
6665 should be associated to.
6666 * \return a new group with newly created elements
6667 * \sa DoubleNodeElemGroups()
6669 //================================================================================
6671 SMESH::ListOfGroups*
6672 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6673 const SMESH::ListOfGroups& theNodesNot,
6674 const SMESH::ListOfGroups& theAffectedElems,
6675 CORBA::Boolean theElemGroupNeeded,
6676 CORBA::Boolean theNodeGroupNeeded)
6677 throw (SALOME::SALOME_Exception)
6680 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6681 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6682 aTwoGroups->length( 2 );
6687 SMESHDS_Mesh* aMeshDS = getMeshDS();
6688 TIDSortedElemSet anElems, aNodes, anAffected;
6689 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6690 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6691 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6693 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6695 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6700 // Create group with newly created elements
6701 CORBA::String_var elemGroupName = theElems[0]->GetName();
6702 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6703 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6705 SMESH::long_array_var anIds = GetLastCreatedElems();
6706 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6707 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6708 aNewElemGroup->Add(anIds);
6710 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6712 SMESH::long_array_var anIds = GetLastCreatedNodes();
6713 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6714 aNewNodeGroup->Add(anIds);
6718 // Update Python script
6721 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6722 else pyDump << aNewElemGroup << ", ";
6723 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6724 else pyDump << aNewNodeGroup << " ] = ";
6726 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6727 << &theNodesNot << ", "
6728 << &theAffectedElems << ", "
6729 << theElemGroupNeeded << ", "
6730 << theNodeGroupNeeded << " )";
6732 aTwoGroups[0] = aNewElemGroup._retn();
6733 aTwoGroups[1] = aNewNodeGroup._retn();
6734 return aTwoGroups._retn();
6736 SMESH_CATCH( SMESH::throwCorbaException );
6740 //================================================================================
6742 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6743 This method provided for convenience works as DoubleNodes() described above.
6744 \param theElems - list of groups of elements (edges or faces) to be replicated
6745 \param theNodesNot - list of groups of nodes not to replicated
6746 \param theShape - shape to detect affected elements (element which geometric center
6747 located on or inside shape).
6748 The replicated nodes should be associated to affected elements.
6749 \return TRUE if operation has been completed successfully, FALSE otherwise
6750 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6752 //================================================================================
6755 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6756 const SMESH::ListOfGroups& theNodesNot,
6757 GEOM::GEOM_Object_ptr theShape )
6758 throw (SALOME::SALOME_Exception)
6764 SMESHDS_Mesh* aMeshDS = getMeshDS();
6765 TIDSortedElemSet anElems, aNodes;
6766 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6767 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6769 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6770 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6772 // Update Python script
6773 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6774 << &theNodesNot << ", " << theShape << " )";
6776 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6779 SMESH_CATCH( SMESH::throwCorbaException );
6783 //================================================================================
6785 \brief Identify the elements that will be affected by node duplication (actual
6786 duplication is not performed.
6787 This method is the first step of DoubleNodeElemGroupsInRegion.
6788 \param theElems - list of groups of elements (edges or faces) to be replicated
6789 \param theNodesNot - list of groups of nodes not to replicated
6790 \param theShape - shape to detect affected elements (element which geometric center
6791 located on or inside shape).
6792 The replicated nodes should be associated to affected elements.
6793 \return groups of affected elements
6794 \sa DoubleNodeElemGroupsInRegion()
6796 //================================================================================
6797 SMESH::ListOfGroups*
6798 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6799 const SMESH::ListOfGroups& theNodesNot,
6800 GEOM::GEOM_Object_ptr theShape )
6801 throw (SALOME::SALOME_Exception)
6804 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6805 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6806 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6807 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6811 ::SMESH_MeshEditor aMeshEditor(myMesh);
6813 SMESHDS_Mesh* aMeshDS = getMeshDS();
6814 TIDSortedElemSet anElems, aNodes;
6815 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6816 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6817 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6819 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6820 TIDSortedElemSet anAffected;
6821 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6823 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6826 if ( aResult && anAffected.size() > 0 )
6828 SMESH::long_array_var volumeIds = new SMESH::long_array;
6829 SMESH::long_array_var faceIds = new SMESH::long_array;
6830 SMESH::long_array_var edgeIds = new SMESH::long_array;
6831 volumeIds->length( anAffected.size() );
6832 faceIds ->length( anAffected.size() );
6833 edgeIds ->length( anAffected.size() );
6838 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6839 for (; eIt != anAffected.end(); ++eIt)
6841 const SMDS_MeshElement* anElem = *eIt;
6842 int elemId = anElem->GetID();
6843 switch ( anElem->GetType() ) {
6844 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6845 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6846 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6850 volumeIds->length(ivol);
6851 faceIds->length(iface);
6852 edgeIds->length(iedge);
6857 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6858 GenerateGroupName("affectedVolumes").c_str());
6859 aNewVolumeGroup->Add(volumeIds);
6860 aListOfGroups->length( nbGroups+1 );
6861 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6865 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6866 GenerateGroupName("affectedFaces").c_str());
6867 aNewFaceGroup->Add(faceIds);
6868 aListOfGroups->length( nbGroups+1 );
6869 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6873 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6874 GenerateGroupName("affectedEdges").c_str());
6875 aNewEdgeGroup->Add(edgeIds);
6876 aListOfGroups->length( nbGroups+1 );
6877 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6881 // Update Python script
6883 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6884 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6886 return aListOfGroups._retn();
6888 SMESH_CATCH( SMESH::throwCorbaException );
6892 //================================================================================
6894 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6895 The created 2D mesh elements based on nodes of free faces of boundary volumes
6896 \return TRUE if operation has been completed successfully, FALSE otherwise
6898 //================================================================================
6900 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6901 throw (SALOME::SALOME_Exception)
6906 bool aResult = getEditor().Make2DMeshFrom3D();
6908 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6910 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6913 SMESH_CATCH( SMESH::throwCorbaException );
6917 //================================================================================
6919 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6920 * The list of groups must contain at least two groups. The groups have to be disjoint:
6921 * no common element into two different groups.
6922 * The nodes of the internal faces at the boundaries of the groups are doubled.
6923 * Optionally, the internal faces are replaced by flat elements.
6924 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6925 * The flat elements are stored in groups of volumes.
6926 * These groups are named according to the position of the group in the list:
6927 * 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.
6928 * 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.
6929 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6930 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6931 * \param theDomains - list of groups of volumes
6932 * \param createJointElems - if TRUE, create the elements
6933 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6934 * the boundary between \a theDomains and the rest mesh
6935 * \return TRUE if operation has been completed successfully, FALSE otherwise
6937 //================================================================================
6940 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6941 CORBA::Boolean createJointElems,
6942 CORBA::Boolean onAllBoundaries )
6943 throw (SALOME::SALOME_Exception)
6950 SMESHDS_Mesh* aMeshDS = getMeshDS();
6952 // MESSAGE("theDomains.length = "<<theDomains.length());
6953 if ( theDomains.length() <= 1 && !onAllBoundaries )
6954 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6956 vector<TIDSortedElemSet> domains;
6957 domains.resize( theDomains.length() );
6959 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6961 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6962 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6964 // if ( aGrp->GetType() != SMESH::VOLUME )
6965 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6966 SMESH::long_array_var anIDs = aGrp->GetIDs();
6967 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6971 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6972 // TODO publish the groups of flat elements in study
6974 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6976 // Update Python script
6977 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6978 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6980 SMESH_CATCH( SMESH::throwCorbaException );
6982 myMesh_i->CreateGroupServants(); // publish created groups if any
6987 //================================================================================
6989 * \brief Double nodes on some external faces and create flat elements.
6990 * Flat elements are mainly used by some types of mechanic calculations.
6992 * Each group of the list must be constituted of faces.
6993 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6994 * @param theGroupsOfFaces - list of groups of faces
6995 * @return TRUE if operation has been completed successfully, FALSE otherwise
6997 //================================================================================
7000 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
7001 throw (SALOME::SALOME_Exception)
7006 SMESHDS_Mesh* aMeshDS = getMeshDS();
7008 vector<TIDSortedElemSet> faceGroups;
7011 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
7013 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
7014 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
7016 TIDSortedElemSet faceGroup;
7018 faceGroups.push_back(faceGroup);
7019 SMESH::long_array_var anIDs = aGrp->GetIDs();
7020 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
7024 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
7025 // TODO publish the groups of flat elements in study
7027 declareMeshModified( /*isReComputeSafe=*/ !aResult );
7029 // Update Python script
7030 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
7033 SMESH_CATCH( SMESH::throwCorbaException );
7037 //================================================================================
7039 * \brief Identify all the elements around a geom shape, get the faces delimiting
7042 * Build groups of volume to remove, groups of faces to replace on the skin of the
7043 * object, groups of faces to remove inside the object, (idem edges).
7044 * Build ordered list of nodes at the border of each group of faces to replace
7045 * (to be used to build a geom subshape).
7047 //================================================================================
7049 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
7050 GEOM::GEOM_Object_ptr theShape,
7051 const char* groupName,
7052 const SMESH::double_array& theNodesCoords,
7053 SMESH::array_of_long_array_out GroupsOfNodes)
7054 throw (SALOME::SALOME_Exception)
7059 std::vector<std::vector<int> > aListOfListOfNodes;
7060 ::SMESH_MeshEditor aMeshEditor( myMesh );
7062 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
7063 if ( !theNodeSearcher )
7064 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
7066 vector<double> nodesCoords;
7067 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
7069 nodesCoords.push_back( theNodesCoords[i] );
7072 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
7073 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
7074 nodesCoords, aListOfListOfNodes);
7076 GroupsOfNodes = new SMESH::array_of_long_array;
7077 GroupsOfNodes->length( aListOfListOfNodes.size() );
7078 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
7079 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
7081 vector<int>& aListOfNodes = *llIt;
7082 vector<int>::iterator lIt = aListOfNodes.begin();;
7083 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
7084 aGroup.length( aListOfNodes.size() );
7085 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
7086 aGroup[ j ] = (*lIt);
7088 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
7091 << ", '" << groupName << "', "
7092 << theNodesCoords << " )";
7094 SMESH_CATCH( SMESH::throwCorbaException );
7097 // issue 20749 ===================================================================
7099 * \brief Creates missing boundary elements
7100 * \param elements - elements whose boundary is to be checked
7101 * \param dimension - defines type of boundary elements to create
7102 * \param groupName - a name of group to store created boundary elements in,
7103 * "" means not to create the group
7104 * \param meshName - a name of new mesh to store created boundary elements in,
7105 * "" means not to create the new mesh
7106 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
7107 * \param toCopyExistingBondary - if true, not only new but also pre-existing
7108 * boundary elements will be copied into the new mesh
7109 * \param group - returns the create group, if any
7110 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7112 // ================================================================================
7114 SMESH::SMESH_Mesh_ptr
7115 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7116 SMESH::Bnd_Dimension dim,
7117 const char* groupName,
7118 const char* meshName,
7119 CORBA::Boolean toCopyElements,
7120 CORBA::Boolean toCopyExistingBondary,
7121 SMESH::SMESH_Group_out group)
7122 throw (SALOME::SALOME_Exception)
7127 if ( dim > SMESH::BND_1DFROM2D )
7128 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7130 SMESHDS_Mesh* aMeshDS = getMeshDS();
7132 SMESH::SMESH_Mesh_var mesh_var;
7133 SMESH::SMESH_Group_var group_var;
7137 TIDSortedElemSet elements;
7138 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7139 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7143 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7144 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7146 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7148 // group of new boundary elements
7149 SMESH_Group* smesh_group = 0;
7150 if ( strlen(groupName) )
7152 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7153 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7154 smesh_group = group_i->GetSmeshGroup();
7158 getEditor().MakeBoundaryMesh( elements,
7159 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7163 toCopyExistingBondary);
7166 smesh_mesh->GetMeshDS()->Modified();
7169 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7171 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7172 if ( mesh_var->_is_nil() )
7173 pyDump << myMesh_i->_this() << ", ";
7175 pyDump << mesh_var << ", ";
7176 if ( group_var->_is_nil() )
7177 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7179 pyDump << group_var << " = ";
7180 pyDump << this << ".MakeBoundaryMesh( "
7182 << "SMESH." << dimName[int(dim)] << ", "
7183 << "'" << groupName << "', "
7184 << "'" << meshName<< "', "
7185 << toCopyElements << ", "
7186 << toCopyExistingBondary << ")";
7188 group = group_var._retn();
7189 return mesh_var._retn();
7191 SMESH_CATCH( SMESH::throwCorbaException );
7192 return SMESH::SMESH_Mesh::_nil();
7195 //================================================================================
7197 * \brief Creates missing boundary elements
7198 * \param dimension - defines type of boundary elements to create
7199 * \param groupName - a name of group to store all boundary elements in,
7200 * "" means not to create the group
7201 * \param meshName - a name of a new mesh, which is a copy of the initial
7202 * mesh + created boundary elements; "" means not to create the new mesh
7203 * \param toCopyAll - if true, the whole initial mesh will be copied into
7204 * the new mesh else only boundary elements will be copied into the new mesh
7205 * \param groups - optional groups of elements to make boundary around
7206 * \param mesh - returns the mesh where elements were added to
7207 * \param group - returns the created group, if any
7208 * \retval long - number of added boundary elements
7210 //================================================================================
7212 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7213 const char* groupName,
7214 const char* meshName,
7215 CORBA::Boolean toCopyAll,
7216 const SMESH::ListOfIDSources& groups,
7217 SMESH::SMESH_Mesh_out mesh,
7218 SMESH::SMESH_Group_out group)
7219 throw (SALOME::SALOME_Exception)
7224 if ( dim > SMESH::BND_1DFROM2D )
7225 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7227 // separate groups belonging to this and other mesh
7228 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7229 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7230 groupsOfThisMesh ->length( groups.length() );
7231 groupsOfOtherMesh->length( groups.length() );
7232 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7233 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7235 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7236 if ( !m->_is_nil() && myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7237 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7239 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7240 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7241 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7243 groupsOfThisMesh->length( nbGroups );
7244 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7249 if ( nbGroupsOfOtherMesh > 0 )
7251 // process groups belonging to another mesh
7252 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7253 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7254 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7255 groupsOfOtherMesh, mesh, group );
7258 SMESH::SMESH_Mesh_var mesh_var;
7259 SMESH::SMESH_Group_var group_var;
7262 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7263 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7267 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7269 /*toCopyGroups=*/false,
7270 /*toKeepIDs=*/true);
7272 mesh_var = makeMesh(meshName);
7274 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7275 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7278 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7279 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7281 // group of boundary elements
7282 SMESH_Group* smesh_group = 0;
7283 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7284 if ( strlen( groupName ))
7286 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7287 group_var = mesh_i->CreateGroup( groupType, groupName );
7288 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7289 smesh_group = group_i->GetSmeshGroup();
7292 TIDSortedElemSet elements;
7294 if ( groups.length() > 0 )
7296 for ( int i = 0; i < nbGroups; ++i )
7299 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7301 SMESH::Bnd_Dimension bdim =
7302 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7303 nbAdded += getEditor().MakeBoundaryMesh( elements,
7304 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7307 /*toCopyElements=*/false,
7308 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7309 /*toAddExistingBondary=*/true,
7310 /*aroundElements=*/true);
7316 nbAdded += getEditor().MakeBoundaryMesh( elements,
7317 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7320 /*toCopyElements=*/false,
7321 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7322 /*toAddExistingBondary=*/true);
7324 tgtMesh->GetMeshDS()->Modified();
7326 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7328 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7329 pyDump << "nbAdded, ";
7330 if ( mesh_var->_is_nil() )
7331 pyDump << myMesh_i->_this() << ", ";
7333 pyDump << mesh_var << ", ";
7334 if ( group_var->_is_nil() )
7335 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7337 pyDump << group_var << " = ";
7338 pyDump << this << ".MakeBoundaryElements( "
7339 << "SMESH." << dimName[int(dim)] << ", "
7340 << "'" << groupName << "', "
7341 << "'" << meshName<< "', "
7342 << toCopyAll << ", "
7345 mesh = mesh_var._retn();
7346 group = group_var._retn();
7349 SMESH_CATCH( SMESH::throwCorbaException );
7353 //================================================================================
7355 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7356 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7357 * plane passing through pairs of points specified by each PolySegment structure.
7358 * If there are several paths connecting a pair of points, the shortest path is
7359 * selected by the module. Position of the cutting plane is defined by the two
7360 * points and an optional vector lying on the plane specified by a PolySegment.
7361 * By default the vector is defined by Mesh module as following. A middle point
7362 * of the two given points is computed. The middle point is projected to the mesh.
7363 * The vector goes from the middle point to the projection point. In case of planar
7364 * mesh, the vector is normal to the mesh.
7365 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7366 * Return the used vector and position of the middle point.
7367 * \param [in] groupName - optional name of a group where created mesh segments will
7370 //================================================================================
7372 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7373 const char* theGroupName)
7374 throw (SALOME::SALOME_Exception)
7376 if ( theSegments.length() == 0 )
7377 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7378 if ( myMesh->NbFaces() == 0 )
7379 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7382 initData(/*deleteSearchers=*/false);
7384 SMESHDS_Group* groupDS = 0;
7385 SMESHDS_Mesh* meshDS = getMeshDS();
7386 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7388 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7389 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7390 while ( faceIt->more() )
7391 tmpMesh->Copy( faceIt->next() );
7392 meshDS = tmpMesh->GetMeshDS();
7394 else if ( theGroupName[0] ) // find/create a group of segments
7396 // SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7397 // while ( !groupDS && grpIt->more() )
7399 // SMESH_Group* group = grpIt->next();
7400 // if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7401 // strcmp( group->GetName(), theGroupName ) == 0 )
7403 // groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7408 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7410 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7411 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7415 // convert input polySegments
7416 SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() );
7417 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7419 SMESH::PolySegment& segIn = theSegments[ i ];
7420 SMESH_MeshAlgos::PolySegment& segOut = segments[ i ];
7421 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7422 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7423 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7424 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7425 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7428 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7431 segOut.myVector.SetCoord( segIn.vector.PS.x,
7433 segIn.vector.PS.z );
7436 // get a static ElementSearcher
7437 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7438 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7439 if ( !theElementSearcher )
7440 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7443 std::vector<const SMDS_MeshElement*> newEdges;
7444 std::vector<const SMDS_MeshNode*> newNodes;
7445 SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes,
7446 groupDS ? &groupDS->SMDSGroup() : 0,
7447 theElementSearcher );
7449 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ).
7451 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ).
7452 assign( newNodes.begin(), newNodes.end() );
7455 if ( myIsPreviewMode )
7457 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7459 SMESH::PolySegment& segOut = theSegments[ i ];
7460 SMESH_MeshAlgos::PolySegment& segIn = segments[ i ];
7461 segOut.vector.PS.x = segIn.myVector.X();
7462 segOut.vector.PS.y = segIn.myVector.Y();
7463 segOut.vector.PS.z = segIn.myVector.Z();
7468 TPythonDump() << "_segments = []";
7469 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7471 SMESH::PolySegment& segIn = theSegments[ i ];
7472 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7473 << segIn.node1ID1 << ", "
7474 << segIn.node1ID2 << ", "
7475 << segIn.node2ID1 << ", "
7476 << segIn.node2ID2 << ", "
7477 << "smeshBuilder.MakeDirStruct( "
7478 << segIn.vector.PS.x << ", "
7479 << segIn.vector.PS.y << ", "
7480 << segIn.vector.PS.z << ")))";
7482 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7485 SMESH_CATCH( SMESH::throwCorbaException );
7489 //================================================================================
7491 * \brief Create a slot of given width around given 1D elements lying on a triangle mesh.
7492 * The slot is constructed by cutting faces by cylindrical surfaces made
7493 * around each segment. Segments are expected to be created by MakePolyLine().
7494 * \return Edges located at the slot boundary
7496 //================================================================================
7498 SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments,
7499 CORBA::Double theWidth)
7500 throw (SALOME::SALOME_Exception)
7502 if ( CORBA::is_nil( theSegments ) ||
7503 theSegments->GetType() != SMESH::EDGE )
7504 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7505 if ( myMesh->NbFaces() == 0 )
7506 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7508 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
7511 initData(/*deleteSearchers=*/false);
7513 SMESHDS_Mesh* meshDS = getMeshDS();
7515 // get standalone face groups to be updated
7516 std::vector< SMDS_MeshGroup* > faceGroups;
7517 const std::set<SMESHDS_GroupBase*>& allGroups = meshDS->GetGroups();
7518 std::set<SMESHDS_GroupBase*>::const_iterator grIt = allGroups.begin();
7519 for ( ; grIt != allGroups.end(); ++grIt )
7520 if ( const SMESHDS_Group* gr = dynamic_cast< const SMESHDS_Group* >( *grIt ))
7521 if ( gr->GetType() == SMDSAbs_Face )
7522 faceGroups.push_back( & const_cast< SMESHDS_Group* >( gr )->SMDSGroup() );
7524 std::vector< SMESH_MeshAlgos::Edge > edges =
7525 SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ),
7526 theWidth, meshDS, faceGroups );
7528 resultEdges->length( edges.size() );
7529 for ( size_t i = 0; i < edges.size(); ++i )
7531 resultEdges[ i ].node1 = edges[i]._node1->GetID();
7532 resultEdges[ i ].node2 = edges[i]._node2->GetID();
7533 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
7537 SMESH_CATCH( SMESH::throwCorbaException );
7539 TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed
7541 return resultEdges._retn();